diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/src/main/java/de/welterde/em/Entity.java b/src/main/java/de/welterde/em/Entity.java
new file mode 100644
index 0000000..062735c
--- /dev/null
+++ b/src/main/java/de/welterde/em/Entity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2026 welterde
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package de.welterde.em;
+
+/**
+ *
+ * @author welterde
+ */
+public abstract class Entity {
+ protected final EntityStorage ctx;
+ protected final int id;
+
+ public Entity(EntityStorage ctx, int id) {
+ this.id = id;
+ this.ctx = ctx;
+ }
+
+ public int getEntityId() {
+ return this.id;
+ }
+}
diff --git a/src/main/java/de/welterde/em/EntityRef.java b/src/main/java/de/welterde/em/EntityRef.java
new file mode 100644
index 0000000..cda120c
--- /dev/null
+++ b/src/main/java/de/welterde/em/EntityRef.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2026 welterde
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package de.welterde.em;
+
+import java.lang.ref.WeakReference;
+
+/**
+ *
+ * @author welterde
+ * @param
+ */
+public class EntityRef {
+ protected final EntityStorage ctx;
+
+ protected WeakReference ref;
+ protected final int entityId;
+ protected boolean invalid;
+
+ public EntityRef(EntityStorage ctx, X entity) {
+ this.ctx = ctx;
+ this.entityId = entity.getEntityId();
+ this.invalid = false;
+ }
+
+ public X get() {
+ if(this.invalid)
+ throw new InvalidEntityReference(this.entityId);
+
+ var e = this.ref.get();
+ if(e != null)
+ return e;
+
+ synchronized(this) {
+ var ee = this.ctx.getEntity(this.entityId);
+ // check if entity was already destroyed
+ if (ee == null) {
+ this.invalid = true;
+ throw new InvalidEntityReference(this.entityId);
+ }
+
+ // try to cast it to the correct type and since we do not reuse
+ // entity ids this should not go wrong, but maybe it did..
+ try {
+ X eee = (X) ee;
+ this.ref = new WeakReference(eee);
+ return eee;
+ } catch(ClassCastException exc) {
+ this.invalid = true;
+ throw new InvalidEntityReference(this.entityId);
+ }
+ }
+ }
+}
diff --git a/src/main/java/de/welterde/em/EntityStorage.java b/src/main/java/de/welterde/em/EntityStorage.java
new file mode 100644
index 0000000..7aec1b4
--- /dev/null
+++ b/src/main/java/de/welterde/em/EntityStorage.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2026 welterde
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package de.welterde.em;
+
+/**
+ *
+ * @author welterde
+ */
+public interface EntityStorage {
+ public Entity getEntity(int entityId);
+}
diff --git a/src/main/java/de/welterde/em/InvalidEntityReference.java b/src/main/java/de/welterde/em/InvalidEntityReference.java
new file mode 100644
index 0000000..86664e7
--- /dev/null
+++ b/src/main/java/de/welterde/em/InvalidEntityReference.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2026 welterde
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package de.welterde.em;
+
+/**
+ *
+ * @author welterde
+ */
+public class InvalidEntityReference extends RuntimeException {
+
+ /**
+ * Creates a new instance of InvalidEntityReference without
+ * detail message.
+ */
+ public InvalidEntityReference() {
+ }
+
+ /**
+ * Constructs an instance of InvalidEntityReference with the
+ * specified detail message.
+ *
+ * @param msg the detail message.
+ */
+ public InvalidEntityReference(int eid) {
+ super("Invalid entity reference to entity=" + eid);
+ }
+}
diff --git a/src/main/java/de/welterde/em/data/CounterName.java b/src/main/java/de/welterde/em/data/CounterName.java
index f70c076..d2cc251 100644
--- a/src/main/java/de/welterde/em/data/CounterName.java
+++ b/src/main/java/de/welterde/em/data/CounterName.java
@@ -21,6 +21,9 @@ package de.welterde.em.data;
* @author welterde
*/
public enum CounterName {
+ COUNTRY_IDX,
+ DIMENSION_IDX,
+ AREA_IDX,
LOCATION_IDX,
ENTITY_IDX,
}
diff --git a/src/main/java/de/welterde/em/data/Entity.java b/src/main/java/de/welterde/em/data/Entity.java
index 2fec36a..b4db73d 100644
--- a/src/main/java/de/welterde/em/data/Entity.java
+++ b/src/main/java/de/welterde/em/data/Entity.java
@@ -37,6 +37,12 @@ public interface Entity {
*/
public Location getLocation();
+ /**
+ * Relative position within location
+ * @return
+ */
+ public LocationPos getLocationPos();
+
public boolean isMovable();
public MovementStatus getMovementStatus();
diff --git a/src/main/java/de/welterde/em/data/LocationPos.java b/src/main/java/de/welterde/em/data/LocationPos.java
new file mode 100644
index 0000000..d11b8da
--- /dev/null
+++ b/src/main/java/de/welterde/em/data/LocationPos.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2026 welterde
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package de.welterde.em.data;
+
+/**
+ *
+ * @author welterde
+ */
+public interface LocationPos {
+
+}
diff --git a/src/main/java/de/welterde/em/w/Area.java b/src/main/java/de/welterde/em/w/Area.java
new file mode 100644
index 0000000..6d8b46e
--- /dev/null
+++ b/src/main/java/de/welterde/em/w/Area.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2026 welterde
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package de.welterde.em.w;
+
+import de.welterde.em.data.Location;
+import de.welterde.em.data.TerrainGen;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ *
+ * @author welterde
+ */
+public class Area {
+ protected final int id;
+ protected final ReadWriteLock structLock;
+
+ protected final AreaMap map;
+ protected final Map locations;
+
+ public Area(int id, TerrainGen gen) {
+ this.id = id;
+ this.structLock = new ReentrantReadWriteLock();
+
+ this.map = new AreaMap(gen);
+ this.locations = new HashMap<>();
+ }
+}
diff --git a/src/main/java/de/welterde/em/w/AreaMap.java b/src/main/java/de/welterde/em/w/AreaMap.java
new file mode 100644
index 0000000..5dad232
--- /dev/null
+++ b/src/main/java/de/welterde/em/w/AreaMap.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2026 welterde
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package de.welterde.em.w;
+
+import de.welterde.em.data.MapCoord;
+import de.welterde.em.data.TerrainGen;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ *
+ * @author welterde
+ */
+public class AreaMap {
+ protected final Map blockMap;
+ protected final TerrainGen gen;
+ protected final ReadWriteLock structLock;
+
+ public AreaMap(TerrainGen gen) {
+ this.gen = gen;
+ this.blockMap = new HashMap<>();
+ this.structLock = new ReentrantReadWriteLock();
+ }
+
+ public Block getBlock(MapCoord c) {
+ if(!this.blockMap.containsKey(c)) {
+ // default to the terrain generator
+ return this.gen.generateBlock(this, c);
+ } else {
+ return this.tiles.get(c);
+ }
+ }
+}
diff --git a/src/main/java/de/welterde/em/w/Block.java b/src/main/java/de/welterde/em/w/Block.java
new file mode 100644
index 0000000..6bb3d9f
--- /dev/null
+++ b/src/main/java/de/welterde/em/w/Block.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2026 welterde
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package de.welterde.em.w;
+
+/**
+ * 5m x 5m block of the world
+ * @author welterde
+ */
+public class Block {
+
+}
diff --git a/src/main/java/de/welterde/em/w/BlockCoord.java b/src/main/java/de/welterde/em/w/BlockCoord.java
new file mode 100644
index 0000000..e5db199
--- /dev/null
+++ b/src/main/java/de/welterde/em/w/BlockCoord.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2026 welterde
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package de.welterde.em.w;
+
+/**
+ *
+ * @author welterde
+ */
+class BlockCoord {
+
+}
diff --git a/src/main/java/de/welterde/em/w/Country.java b/src/main/java/de/welterde/em/w/Country.java
index 8923416..991ed6d 100644
--- a/src/main/java/de/welterde/em/w/Country.java
+++ b/src/main/java/de/welterde/em/w/Country.java
@@ -16,10 +16,17 @@
*/
package de.welterde.em.w;
+import de.welterde.em.Entity;
+import de.welterde.em.EntityStorage;
+
/**
*
* @author welterde
*/
-public class Country {
+public class Country extends Entity {
+
+ public Country(EntityStorage ctx, int id) {
+ super(ctx, id);
+ }
}
diff --git a/src/main/java/de/welterde/em/w/Dimension.java b/src/main/java/de/welterde/em/w/Dimension.java
index 32f9815..44178b5 100644
--- a/src/main/java/de/welterde/em/w/Dimension.java
+++ b/src/main/java/de/welterde/em/w/Dimension.java
@@ -16,10 +16,39 @@
*/
package de.welterde.em.w;
+import de.welterde.em.Entity;
+import de.welterde.em.data.CounterName;
+import de.welterde.em.data.TerrainGen;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
/**
*
* @author welterde
*/
-public class Dimension {
+public class Dimension extends Entity {
+ protected final ReadWriteLock structLock;
+ protected final Map areas;
+
+ public Dimension(World ctx, int id) {
+ super(ctx, id);
+ this.structLock = new ReentrantReadWriteLock();
+
+ this.areas = new HashMap<>();
+ }
+
+ public Area addArea(TerrainGen gen) {
+ this.structLock.writeLock().lock();
+ try {
+ var areaId = this.ctx.allocateId(CounterName.AREA_IDX);
+ var area = new Area(areaId, gen);
+ this.areas.put(areaId, area);
+ return area;
+ } finally {
+ this.structLock.writeLock().unlock();
+ }
+ }
}
diff --git a/src/main/java/de/welterde/em/w/World.java b/src/main/java/de/welterde/em/w/World.java
index 96bcab4..47b40ea 100644
--- a/src/main/java/de/welterde/em/w/World.java
+++ b/src/main/java/de/welterde/em/w/World.java
@@ -16,10 +16,72 @@
*/
package de.welterde.em.w;
+import de.welterde.em.Entity;
+import de.welterde.em.EntityRef;
+import de.welterde.em.EntityStorage;
+import de.welterde.em.data.CounterName;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
/**
*
* @author welterde
*/
-public class World {
+public class World implements EntityStorage {
+ protected final ArrayList entities;
+ protected final EnumMap counters;
+ protected final ArrayList> dimensions;
+ protected final Map> countries;
+ protected final ReadWriteLock structLock;
+ public World() {
+ this.counters = new EnumMap<>(CounterName.class);
+ this.dimensions = new ArrayList<>();
+ this.countries = new HashMap<>();
+ this.entities = new ArrayList<>();
+
+ this.structLock = new ReentrantReadWriteLock();
+ }
+
+
+ public int allocateId(CounterName name) {
+ synchronized(this.counters) {
+ // start counter at zero if not yet a thing
+ if(!this.counters.containsKey(name))
+ this.counters.put(name, 0);
+
+ var nextVal = this.counters.get(name) + 1;
+ this.counters.put(name, nextVal);
+ return nextVal;
+ }
+ }
+
+ public Dimension addDimension() {
+ this.structLock.writeLock().lock();
+ try{
+ var dim = new Dimension(this, this.dimensions.size());
+ this.dimensions.add(dim);
+ return dim;
+ } finally {
+ this.structLock.writeLock().unlock();
+ }
+ }
+ public Dimension getDimension(int id) {
+ this.structLock.readLock().lock();
+ try {
+ return this.dimensions.get(id);
+ } finally {
+ this.structLock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public Entity getEntity(int entityId) {
+ return this.entities.get(entityId);
+ }
}