This commit is contained in:
Tassilo Schweyer 2026-06-08 12:26:13 +02:00
parent cabfdd4252
commit fb77d13eb5
15 changed files with 447 additions and 3 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target/

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package de.welterde.em;
import java.lang.ref.WeakReference;
/**
*
* @author welterde
* @param <X>
*/
public class EntityRef<X extends Entity> {
protected final EntityStorage ctx;
protected WeakReference<X> 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);
}
}
}
}

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 EntityStorage {
public Entity getEntity(int entityId);
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
package de.welterde.em;
/**
*
* @author welterde
*/
public class InvalidEntityReference extends RuntimeException {
/**
* Creates a new instance of <code>InvalidEntityReference</code> without
* detail message.
*/
public InvalidEntityReference() {
}
/**
* Constructs an instance of <code>InvalidEntityReference</code> with the
* specified detail message.
*
* @param msg the detail message.
*/
public InvalidEntityReference(int eid) {
super("Invalid entity reference to entity=" + eid);
}
}

View file

@ -21,6 +21,9 @@ package de.welterde.em.data;
* @author welterde * @author welterde
*/ */
public enum CounterName { public enum CounterName {
COUNTRY_IDX,
DIMENSION_IDX,
AREA_IDX,
LOCATION_IDX, LOCATION_IDX,
ENTITY_IDX, ENTITY_IDX,
} }

View file

@ -37,6 +37,12 @@ public interface Entity {
*/ */
public Location getLocation(); public Location getLocation();
/**
* Relative position within location
* @return
*/
public LocationPos getLocationPos();
public boolean isMovable(); public boolean isMovable();
public MovementStatus getMovementStatus(); public MovementStatus getMovementStatus();

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.data;
/**
*
* @author welterde
*/
public interface LocationPos {
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<Integer, Location> locations;
public Area(int id, TerrainGen gen) {
this.id = id;
this.structLock = new ReentrantReadWriteLock();
this.map = new AreaMap(gen);
this.locations = new HashMap<>();
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<MapCoord, Block> 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);
}
}
}

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;
/**
* 5m x 5m block of the world
* @author welterde
*/
public class Block {
}

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
*/
class BlockCoord {
}

View file

@ -16,10 +16,17 @@
*/ */
package de.welterde.em.w; package de.welterde.em.w;
import de.welterde.em.Entity;
import de.welterde.em.EntityStorage;
/** /**
* *
* @author welterde * @author welterde
*/ */
public class Country { public class Country extends Entity {
public Country(EntityStorage ctx, int id) {
super(ctx, id);
}
} }

View file

@ -16,10 +16,39 @@
*/ */
package de.welterde.em.w; 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 * @author welterde
*/ */
public class Dimension { public class Dimension extends Entity {
protected final ReadWriteLock structLock;
protected final Map<Integer, Area> 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();
}
}
} }

View file

@ -16,10 +16,72 @@
*/ */
package de.welterde.em.w; 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 * @author welterde
*/ */
public class World { public class World implements EntityStorage {
protected final ArrayList<Entity> entities;
protected final EnumMap<CounterName, Integer> counters;
protected final ArrayList<EntityRef<Dimension>> dimensions;
protected final Map<Integer, EntityRef<Country>> 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);
}
} }