This commit is contained in:
Tassilo Schweyer 2026-06-12 19:36:27 +02:00
parent 56e19e8039
commit ad4f8727b8
39 changed files with 538 additions and 70 deletions

View file

@ -21,6 +21,7 @@ package de.welterde.em;
* @author welterde * @author welterde
*/ */
public interface Entity { public interface Entity {
public GameContext getContext();
public int getEntityId(); public int getEntityId();
public void initEntity(EntityStorage ctx, int id); public void initEntity(GameContext ctx, int id);
} }

View file

@ -23,7 +23,7 @@ import de.welterde.em.io.EntityRecord;
* @author welterde * @author welterde
*/ */
public abstract class EntityBase implements Entity { public abstract class EntityBase implements Entity {
protected EntityStorage ctx; protected GameContext ctx;
protected int id; protected int id;
public EntityBase() { public EntityBase() {
@ -31,7 +31,7 @@ public abstract class EntityBase implements Entity {
this.ctx = null; this.ctx = null;
} }
public EntityBase(EntityStorage ctx, int id) { public EntityBase(GameContext ctx, int id) {
this.id = id; this.id = id;
this.ctx = ctx; this.ctx = ctx;
} }
@ -41,12 +41,14 @@ public abstract class EntityBase implements Entity {
this.ctx = r.getContext(); this.ctx = r.getContext();
} }
@Override
public int getEntityId() { public int getEntityId() {
if(this.id == -1) if(this.id == -1)
throw new IllegalStateException("Entity not initialized"); throw new IllegalStateException("Entity not initialized");
return this.id; return this.id;
} }
public void initEntity(EntityStorage ctx, int id) { @Override
public void initEntity(GameContext ctx, int id) {
if((this.id != -1) && (this.ctx != null)) if((this.id != -1) && (this.ctx != null))
throw new IllegalStateException("Entity already initialized"); throw new IllegalStateException("Entity already initialized");
if(id == -1) if(id == -1)
@ -61,4 +63,11 @@ public abstract class EntityBase implements Entity {
return this.id != -1; return this.id != -1;
} }
@Override
public GameContext getContext() {
if(this.ctx == null)
throw new IllegalStateException("Entity not initialized");
return this.ctx;
}
} }

View file

@ -0,0 +1,27 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.welterde.em;
/**
*
* @author welterde
*/
public interface EntityContainer {
public void addEntity(Entity e);
public Iterable<Entity> listEntities();
public void removeEntity(Entity e);
}

View file

@ -28,18 +28,24 @@ public class EntityRef<X extends Entity> {
static Location maybeGet(EntityRef<Location> currentLocation) { static Location maybeGet(EntityRef<Location> currentLocation) {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
} }
protected final EntityStorage ctx; protected final GameContext ctx;
protected WeakReference<X> ref; protected WeakReference<X> ref;
protected final int entityId; protected final int entityId;
protected boolean invalid; protected boolean invalid;
public EntityRef(EntityStorage ctx, X entity) { public EntityRef(GameContext ctx, X entity) {
this.ctx = ctx; this.ctx = ctx;
this.entityId = entity.getEntityId(); this.entityId = entity.getEntityId();
this.invalid = false; this.invalid = false;
} }
public EntityRef(X entity) {
this.ctx = entity.getContext();
this.entityId = entity.getEntityId();
this.invalid = false;
}
public X get() { public X get() {
if(this.invalid) if(this.invalid)
throw new InvalidEntityReference(this.entityId); throw new InvalidEntityReference(this.entityId);
@ -68,4 +74,5 @@ public class EntityRef<X extends Entity> {
} }
} }
} }
} }

View file

@ -0,0 +1,33 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.welterde.em;
import de.welterde.em.data.CounterName;
/**
*
* @author welterde
*/
public interface GameContext {
public Entity getEntity(int entityId);
public EntityContainer getContainer(int entityId);
int allocateId(CounterName name);
int addEntity(EntityBase e);
}

View file

@ -20,13 +20,7 @@ package de.welterde.em;
* *
* @author welterde * @author welterde
*/ */
public class LocatedEntity extends EntityBase { public interface LocatedEntity extends Entity {
protected EntityRef<Location> currentLocation; public Location getLocation();
public void setLocation(Location newLoc);
public Location getLocation() {
if(this.currentLocation == null)
return null;
else
return this.currentLocation.get();
}
} }

View file

@ -0,0 +1,42 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.welterde.em;
/**
*
* @author welterde
*/
public class LocatedEntityBase extends EntityBase implements LocatedEntity {
protected EntityRef<Location> currentLocation;
@Override
public Location getLocation() {
if(this.currentLocation == null)
return null;
else
return this.currentLocation.get();
}
@Override
public void setLocation(Location newLoc) {
newLoc.addEntity(this);
if(this.currentLocation != null) {
this.currentLocation.get().removeEntity(this);
}
this.currentLocation = new EntityRef(newLoc);
}
}

View file

@ -16,11 +16,18 @@
*/ */
package de.welterde.em; package de.welterde.em;
import de.welterde.em.w.Area;
/** /**
* *
* @author welterde * @author welterde
*/ */
public interface Location extends Entity { public interface Location extends Entity, EntityContainer {
public short getSecurityLevel(); public short getSecurityLevel();
public Location setSecurityLevel(short newLevel); public Location setSecurityLevel(short newLevel);
public Area getArea();
public void setArea(Area area);
} }

View file

@ -20,6 +20,6 @@ package de.welterde.em;
* *
* @author welterde * @author welterde
*/ */
public interface EntityStorage { public interface LocationListener {
public EntityBase getEntity(int entityId);
} }

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package de.welterde.em;
/**
*
* @author welterde
*/
public interface MovableEntity extends Entity, Positioned, LocatedEntity {
}

View file

@ -36,5 +36,5 @@ public interface PositionTracker {
public void moveEntityCardinal(Entity e, Direction dir); public void moveEntityCardinal(Entity e, Direction dir);
public void enrollEntity(Entity e, MapCoord startCoord); public void enrollEntity(LocatedEntity e, MapCoord startCoord);
} }

View file

@ -16,17 +16,50 @@
*/ */
package de.welterde.em; package de.welterde.em;
import de.welterde.em.data.Direction;
import de.welterde.em.data.MapCoord; import de.welterde.em.data.MapCoord;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* *
* @author welterde * @author welterde
*/ */
public class PositionTrackerImpl implements PositionTracker { public class PositionTrackerImpl implements PositionTracker, LocationListener {
protected Map map;
@Override protected MapCoord coordCenter;
public MapCoord getPosition(Entity e) { protected Map<Integer, MapCoord> entityCoord;
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
public PositionTrackerImpl(Map map, MapCoord coordCenter) {
this.map = map;
this.coordCenter = coordCenter;
this.entityCoord = new ConcurrentHashMap<>();
} }
@Override
public MapCoord getPosition(Entity e) {
var eid = e.getEntityId();
if(!this.entityCoord.containsKey(eid))
return null;
var c = this.entityCoord.get(eid);
return this.coordCenter.add(c);
}
@Override
public void teleportEntity(Entity e, MapCoord destination) {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
@Override
public void moveEntityCardinal(Entity e, Direction dir) {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
@Override
public void enrollEntity(LocatedEntity e, MapCoord startCoord) {
this.entityCoord.put(e.getEntityId(), startCoord);
}
} }

View file

@ -20,7 +20,7 @@ package de.welterde.em;
* *
* @author welterde * @author welterde
*/ */
public interface Positioned { public interface Positioned extends LocatedEntity {
public PositionTracker getPositionTracker(); public PositionTracker getPositionTracker();
public void setPositionTracker(); public void setPositionTracker(PositionTracker newTracker);
} }

View file

@ -14,26 +14,24 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package de.welterde.em.data; package de.welterde.em;
import de.welterde.em.Location;
/** /**
* *
* @author welterde * @author welterde
*/ */
public abstract class LocationBase implements Location { public class PositionedEntityBase extends LocatedEntityBase implements Positioned {
protected short securityLevel; protected PositionTracker positionTracker;
@Override @Override
public short getSecurityLevel() { public PositionTracker getPositionTracker() {
return this.securityLevel; return this.positionTracker;
}
@Override
public void setPositionTracker(PositionTracker newTracker) {
this.positionTracker = newTracker;
} }
@Override
public Location setSecurityLevel(short newLevel) {
this.securityLevel = newLevel;
return this;
}
} }

View file

@ -14,9 +14,12 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package de.welterde.em.data; package de.welterde.em;
import de.welterde.em.Location; import de.welterde.em.Location;
import de.welterde.em.data.Direction;
import de.welterde.em.data.Entity;
import de.welterde.em.data.TileType;
/** /**
* *

View file

@ -0,0 +1,27 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.welterde.em;
import de.welterde.em.data.MapCoord;
/**
*
* @author welterde
*/
public interface TileMap {
public Tile getTile(MapCoord c);
}

View file

@ -0,0 +1,102 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.welterde.em.data;
import de.welterde.em.EntityContainer;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import de.welterde.em.GameContext;
/**
*
* @author welterde
*/
public class BasicEntityCollection implements EntityContainer {
protected final GameContext ctx;
protected Set<Integer> entities;
protected final ReadWriteLock structLock;
protected Thread houseKeepingThread;
protected BlockingQueue<Task> taskQ;
public BasicEntityCollection(GameContext ctx) {
this.ctx = ctx;
this.entities = new TreeSet<>();
this.structLock = new ReentrantReadWriteLock();
this.taskQ = new LinkedBlockingDeque<>();
this.houseKeepingThread = Thread
.ofVirtual()
.name("entitycollection")
.start(() -> this.housekeep());
}
@Override
public void addEntity(de.welterde.em.Entity e) {
this.taskQ.add(new Task(e.getEntityId(), false));
}
@Override
public Iterable<de.welterde.em.Entity> listEntities() {
this.structLock.readLock().lock();
try {
// create copy of the entity list so we can hand out the iterator
final Integer[] ids = new Integer[this.entities.size()];
this.entities.toArray(ids);
final Iterable<de.welterde.em.Entity> i = () -> Arrays.stream(ids).map(eid -> (de.welterde.em.Entity) this.ctx.getEntity(eid)).iterator();
return i;
} finally {
this.structLock.readLock().unlock();
}
}
@Override
public void removeEntity(de.welterde.em.Entity e) {
this.taskQ.add(new Task(e.getEntityId(), true));
}
protected void housekeep() {
while(true) {
Task task;
try {
task = this.taskQ.take();
} catch (InterruptedException ex) {
System.getLogger(BasicEntityCollection.class.getName()).log(System.Logger.Level.ERROR, (String) null, ex);
continue;
}
this.structLock.writeLock().lock();
try {
if(task.remove()) {
this.entities.remove(task.eid());
} else {
this.entities.add(task.eid());
}
} finally {
this.structLock.writeLock().unlock();
}
}
}
record Task(Integer eid, boolean remove) {
}
}

View file

@ -16,6 +16,8 @@
*/ */
package de.welterde.em.data; package de.welterde.em.data;
import de.welterde.em.Tile;
/** /**
* Manages position and occupied tiles by entities * Manages position and occupied tiles by entities
* *

View file

@ -16,6 +16,8 @@
*/ */
package de.welterde.em.data; package de.welterde.em.data;
import de.welterde.em.loc.Corridor;
/** /**
* Manages locations like rooms, corridors, sectors * Manages locations like rooms, corridors, sectors
* @author welterde * @author welterde

View file

@ -44,4 +44,8 @@ public record MapCoord(int z, int x, int y) {
public MapCoord add(CoordVector v) { public MapCoord add(CoordVector v) {
return new MapCoord(z + v.dz(), x + v.dx(), y + v.dy()); return new MapCoord(z + v.dz(), x + v.dx(), y + v.dy());
} }
public MapCoord add(MapCoord c) {
return new MapCoord(this.z + c.z(), this.x + c.x(), this.y + c.y());
}
} }

View file

@ -4,6 +4,7 @@
*/ */
package de.welterde.em.data; package de.welterde.em.data;
import de.welterde.em.Tile;
import de.welterde.em.Location; import de.welterde.em.Location;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.HashMap; import java.util.HashMap;

View file

@ -16,6 +16,8 @@
*/ */
package de.welterde.em.data; package de.welterde.em.data;
import de.welterde.em.Tile;
/** /**
* *
* @author welterde * @author welterde

View file

@ -16,6 +16,7 @@
*/ */
package de.welterde.em.data; package de.welterde.em.data;
import de.welterde.em.Tile;
import de.welterde.em.Location; import de.welterde.em.Location;
import de.welterde.em.CollisionException; import de.welterde.em.CollisionException;

View file

@ -19,7 +19,7 @@ package de.welterde.em.data.gen;
import de.welterde.em.data.MapCoord; import de.welterde.em.data.MapCoord;
import de.welterde.em.data.OutpostMap; import de.welterde.em.data.OutpostMap;
import de.welterde.em.data.TerrainGen; import de.welterde.em.data.TerrainGen;
import de.welterde.em.data.Tile; import de.welterde.em.Tile;
import de.welterde.em.data.TileImpl; import de.welterde.em.data.TileImpl;
import de.welterde.em.data.TileType; import de.welterde.em.data.TileType;

View file

@ -19,13 +19,14 @@ package de.welterde.em.e;
import de.welterde.em.EntityBase; import de.welterde.em.EntityBase;
import de.welterde.em.EntityRef; import de.welterde.em.EntityRef;
import de.welterde.em.Location; import de.welterde.em.Location;
import de.welterde.em.PositionedEntityBase;
import de.welterde.em.w.Org; import de.welterde.em.w.Org;
/** /**
* *
* @author welterde * @author welterde
*/ */
public class Employee extends EntityBase { public class Employee extends PositionedEntityBase {
protected String name; protected String name;
protected EntityRef<Org> employer; protected EntityRef<Org> employer;

View file

@ -17,7 +17,7 @@
package de.welterde.em.entity; package de.welterde.em.entity;
import de.welterde.em.EntityBase; import de.welterde.em.EntityBase;
import de.welterde.em.EntityStorage; import de.welterde.em.GameContext;
/** /**
* *
@ -25,7 +25,7 @@ import de.welterde.em.EntityStorage;
*/ */
public abstract class ItemBase extends EntityBase { public abstract class ItemBase extends EntityBase {
public ItemBase(EntityStorage ctx, int id) { public ItemBase(GameContext ctx, int id) {
super(ctx, id); super(ctx, id);
} }
} }

View file

@ -16,7 +16,7 @@
*/ */
package de.welterde.em.io; package de.welterde.em.io;
import de.welterde.em.EntityStorage; import de.welterde.em.GameContext;
/** /**
* *
@ -24,5 +24,5 @@ import de.welterde.em.EntityStorage;
*/ */
public interface EntityRecord { public interface EntityRecord {
public int getID(); public int getID();
public EntityStorage getContext(); public GameContext getContext();
} }

View file

@ -14,8 +14,9 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package de.welterde.em.data; package de.welterde.em.loc;
import de.welterde.em.loc.LocationBase;
import de.welterde.em.Location; import de.welterde.em.Location;
/** /**

View file

@ -0,0 +1,86 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package de.welterde.em.loc;
import de.welterde.em.Entity;
import de.welterde.em.EntityBase;
import de.welterde.em.EntityContainer;
import de.welterde.em.Location;
import de.welterde.em.data.BasicEntityCollection;
import de.welterde.em.w.Area;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import de.welterde.em.GameContext;
/**
*
* @author welterde
*/
public abstract class LocationBase extends EntityBase implements Location {
protected short securityLevel;
protected Area area;
protected final ReadWriteLock structLock;
protected EntityContainer entityContainer;
public LocationBase() {
this.structLock = new ReentrantReadWriteLock();
}
@Override
public short getSecurityLevel() {
return this.securityLevel;
}
@Override
public Location setSecurityLevel(short newLevel) {
this.securityLevel = newLevel;
return this;
}
@Override
public Area getArea() {
return this.area;
}
@Override
public void setArea(Area area) {
this.area = area;
}
@Override
public void initEntity(GameContext ctx, int id) {
super.initEntity(ctx, id);
this.entityContainer = new BasicEntityCollection(ctx);
}
@Override
public void addEntity(Entity e) {
entityContainer.addEntity(e);
}
@Override
public Iterable<Entity> listEntities() {
return entityContainer.listEntities();
}
@Override
public void removeEntity(Entity e) {
entityContainer.removeEntity(e);
}
}

View file

@ -14,8 +14,9 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package de.welterde.em.data; package de.welterde.em.loc;
import de.welterde.em.loc.LocationBase;
import de.welterde.em.Location; import de.welterde.em.Location;
/** /**

View file

@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package de.welterde.em.room; package de.welterde.em.loc;
/** /**
* *
@ -24,4 +24,5 @@ public enum RoomType {
LAB, LAB,
OFFICE, OFFICE,
COMPUTER_ROOM, COMPUTER_ROOM,
LIBRARY,
} }

View file

@ -17,29 +17,38 @@
package de.welterde.em.w; package de.welterde.em.w;
import de.welterde.em.EntityBase; import de.welterde.em.EntityBase;
import de.welterde.em.EntityStorage;
import de.welterde.em.Location; import de.welterde.em.Location;
import de.welterde.em.Tile;
import de.welterde.em.TileMap;
import de.welterde.em.data.MapCoord;
import de.welterde.em.data.TerrainGen; import de.welterde.em.data.TerrainGen;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import de.welterde.em.GameContext;
/** /**
* *
* @author welterde * @author welterde
*/ */
public class Area extends EntityBase { public class Area extends EntityBase implements TileMap {
protected final ReadWriteLock structLock; protected final ReadWriteLock structLock;
protected final AreaMap map; protected final AreaMap map;
protected final Map<Integer, Location> locations; protected final Map<Integer, Location> locations;
public Area(EntityStorage ctx, int id, TerrainGen gen) { public Area(AreaSetup setup) {
super(ctx, id);
this.structLock = new ReentrantReadWriteLock(); this.structLock = new ReentrantReadWriteLock();
this.map = new AreaMap(gen); this.map = new AreaMap(gen);
this.locations = new HashMap<>(); this.locations = new HashMap<>();
} }
@Override
public Tile getTile(MapCoord c) {
return map.getTile(c);
}
} }

View file

@ -16,6 +16,8 @@
*/ */
package de.welterde.em.w; package de.welterde.em.w;
import de.welterde.em.Tile;
import de.welterde.em.TileMap;
import de.welterde.em.data.MapCoord; import de.welterde.em.data.MapCoord;
import de.welterde.em.data.TerrainGen; import de.welterde.em.data.TerrainGen;
import java.util.HashMap; import java.util.HashMap;
@ -27,7 +29,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
* *
* @author welterde * @author welterde
*/ */
public class AreaMap { public class AreaMap implements TileMap {
protected final Map<MapCoord, Block> blockMap; protected final Map<MapCoord, Block> blockMap;
protected final TerrainGen gen; protected final TerrainGen gen;
protected final ReadWriteLock structLock; protected final ReadWriteLock structLock;
@ -46,4 +48,11 @@ public class AreaMap {
return this.tiles.get(c); return this.tiles.get(c);
} }
} }
@Override
public Tile getTile(MapCoord c) {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
} }

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package de.welterde.em.w;
/**
*
* @author welterde
*/
public class AreaSetup {
}

View file

@ -17,14 +17,14 @@
package de.welterde.em.w; package de.welterde.em.w;
import de.welterde.em.EntityBase; import de.welterde.em.EntityBase;
import de.welterde.em.EntityStorage; import de.welterde.em.GameContext;
/** /**
* *
* @author welterde * @author welterde
*/ */
public class City extends EntityBase { public class City extends EntityBase {
public City(EntityStorage ctx, int id) { public City(GameContext ctx, int id) {
super(ctx, id); super(ctx, id);
} }
} }

View file

@ -17,7 +17,7 @@
package de.welterde.em.w; package de.welterde.em.w;
import de.welterde.em.EntityBase; import de.welterde.em.EntityBase;
import de.welterde.em.EntityStorage; import de.welterde.em.GameContext;
/** /**
* *
@ -25,7 +25,7 @@ import de.welterde.em.EntityStorage;
*/ */
public class Country extends EntityBase { public class Country extends EntityBase {
public Country(EntityStorage ctx, int id) { public Country(GameContext ctx, int id) {
super(ctx, id); super(ctx, id);
} }

View file

@ -40,12 +40,12 @@ public class Dimension extends EntityBase {
this.areas = new HashMap<>(); this.areas = new HashMap<>();
} }
public Area addArea(TerrainGen gen) { public Area createArea(AreaSetup setup) {
this.structLock.writeLock().lock(); this.structLock.writeLock().lock();
try { try {
var areaId = this.ctx.allocateId(CounterName.AREA_IDX); var area = new Area(setup);
var area = new Area(areaId, gen); var aid = this.ctx.addEntity(area);
this.areas.put(areaId, area); this.areas.put(aid, area);
return area; return area;
} finally { } finally {
this.structLock.writeLock().unlock(); this.structLock.writeLock().unlock();

View file

@ -18,8 +18,8 @@ package de.welterde.em.w;
import de.welterde.em.EntityBase; import de.welterde.em.EntityBase;
import de.welterde.em.EntityRef; import de.welterde.em.EntityRef;
import de.welterde.em.EntityStorage;
import java.util.EnumSet; import java.util.EnumSet;
import de.welterde.em.GameContext;
/** /**
* *
@ -30,7 +30,7 @@ public class Outpost extends EntityBase {
protected final OutpostLocationType locationType; protected final OutpostLocationType locationType;
protected EntityRef<City> city; protected EntityRef<City> city;
public Outpost(EntityStorage ctx, int id, OutpostLocationType locationType) { public Outpost(GameContext ctx, int id, OutpostLocationType locationType) {
super(ctx, id); super(ctx, id);
this.flags = EnumSet.noneOf(OutpostFlags.class); this.flags = EnumSet.noneOf(OutpostFlags.class);
this.locationType = locationType; this.locationType = locationType;

View file

@ -16,9 +16,10 @@
*/ */
package de.welterde.em.w; package de.welterde.em.w;
import de.welterde.em.Entity;
import de.welterde.em.EntityBase; import de.welterde.em.EntityBase;
import de.welterde.em.EntityContainer;
import de.welterde.em.EntityRef; import de.welterde.em.EntityRef;
import de.welterde.em.EntityStorage;
import de.welterde.em.data.CounterName; import de.welterde.em.data.CounterName;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumMap; import java.util.EnumMap;
@ -28,15 +29,19 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import de.welterde.em.GameContext;
/** /**
* *
* @author welterde * @author welterde
*/ */
public class World implements EntityStorage { public class World implements GameContext {
protected final ArrayList<EntityBase> entities; // base backing storage of entities and entity components
protected final ArrayList<Entity> entities;
protected final Map<Integer,EntityContainer> entityContainers;
protected final EnumMap<CounterName, Integer> counters; protected final EnumMap<CounterName, Integer> counters;
// direct ref to certain top-level entities
protected final ArrayList<Dimension> dimensions; protected final ArrayList<Dimension> dimensions;
protected final Map<Integer, Country> countries; protected final Map<Integer, Country> countries;
protected final Map<Integer, Org> orgs; protected final Map<Integer, Org> orgs;
@ -46,10 +51,13 @@ public class World implements EntityStorage {
protected final AtomicReference<WorldState> state; protected final AtomicReference<WorldState> state;
public World() { public World() {
this.entities = new ArrayList<>();
this.entityContainers = new HashMap<>();
this.counters = new EnumMap<>(CounterName.class); this.counters = new EnumMap<>(CounterName.class);
this.dimensions = new ArrayList<>(); this.dimensions = new ArrayList<>();
this.countries = new HashMap<>(); this.countries = new HashMap<>();
this.entities = new ArrayList<>();
this.orgs = new HashMap<>(); this.orgs = new HashMap<>();
this.outposts = new HashMap<>(); this.outposts = new HashMap<>();
@ -58,6 +66,7 @@ public class World implements EntityStorage {
} }
@Override
public int allocateId(CounterName name) { public int allocateId(CounterName name) {
synchronized(this.counters) { synchronized(this.counters) {
// start counter at zero if not yet a thing // start counter at zero if not yet a thing
@ -90,12 +99,16 @@ public class World implements EntityStorage {
} }
@Override @Override
public EntityBase getEntity(int entityId) { public Entity getEntity(int entityId) {
return this.entities.get(entityId); return this.entities.get(entityId);
} }
@Override
public EntityContainer getContainer(int entityId) {
return this.entityContainers.getOrDefault(entityId, null);
}
@Override
public void addEntity(EntityBase e) { public int addEntity(EntityBase e) {
if(e.isEntityInitialized()) if(e.isEntityInitialized())
throw new IllegalStateException("Entity already initialized"); throw new IllegalStateException("Entity already initialized");
@ -132,4 +145,6 @@ public class World implements EntityStorage {
} }
} }
} }
} }