mirror of
https://github.com/simon987/Much-Assembly-Required.git
synced 2025-04-18 02:06:43 +00:00
Merge branch 'master' into vaults
# Conflicts: # Server/src/main/java/net/simon987/server/GameServer.java # Server/src/main/java/net/simon987/server/game/World.java
This commit is contained in:
commit
3d10e4306b
@ -52,7 +52,6 @@ public class CubotLaser extends CpuHardware {
|
|||||||
Point frontTile = cubot.getFrontTile();
|
Point frontTile = cubot.getFrontTile();
|
||||||
ArrayList<GameObject> objects = cubot.getWorld().getGameObjectsBlockingAt(frontTile.x, frontTile.y);
|
ArrayList<GameObject> objects = cubot.getWorld().getGameObjectsBlockingAt(frontTile.x, frontTile.y);
|
||||||
|
|
||||||
|
|
||||||
if (cubot.getCurrentAction() == Action.IDLE && objects.size() > 0) {
|
if (cubot.getCurrentAction() == Action.IDLE && objects.size() > 0) {
|
||||||
//FIXME: Problem here if more than 1 object
|
//FIXME: Problem here if more than 1 object
|
||||||
if (objects.get(0) instanceof InventoryHolder) {
|
if (objects.get(0) instanceof InventoryHolder) {
|
||||||
|
@ -37,37 +37,40 @@ public class CubotLeg extends CpuHardware implements JSONSerialisable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInterrupt(Status status) {
|
public void handleInterrupt(Status status) {
|
||||||
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
|
||||||
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
|
||||||
|
|
||||||
if (a == LEGS_SET_DIR) {
|
if (cubot.getCurrentAction() == Action.IDLE) {
|
||||||
|
int a = getCpu().getRegisterSet().getRegister("A").getValue();
|
||||||
|
int b = getCpu().getRegisterSet().getRegister("B").getValue();
|
||||||
|
|
||||||
|
if (a == LEGS_SET_DIR) {
|
||||||
|
|
||||||
|
|
||||||
Direction dir = Direction.getDirection(b);
|
|
||||||
|
|
||||||
if (dir != null) {
|
|
||||||
if (cubot.spendEnergy(20)) {
|
|
||||||
cubot.setDirection(Direction.getDirection(b));
|
|
||||||
status.setErrorFlag(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
status.setErrorFlag(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else if (a == LEGS_SET_DIR_AND_WALK) {
|
|
||||||
|
|
||||||
if (cubot.getMaxEnergy() >= 100) {
|
|
||||||
Direction dir = Direction.getDirection(b);
|
Direction dir = Direction.getDirection(b);
|
||||||
|
|
||||||
if (dir != null) {
|
if (dir != null) {
|
||||||
cubot.setDirection(Direction.getDirection(b));
|
if (cubot.spendEnergy(20)) {
|
||||||
status.setErrorFlag(false);
|
cubot.setDirection(Direction.getDirection(b));
|
||||||
|
status.setErrorFlag(false);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
status.setErrorFlag(true);
|
status.setErrorFlag(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
cubot.setCurrentAction(Action.WALKING);
|
|
||||||
|
} else if (a == LEGS_SET_DIR_AND_WALK) {
|
||||||
|
|
||||||
|
if (cubot.getMaxEnergy() >= 100) {
|
||||||
|
Direction dir = Direction.getDirection(b);
|
||||||
|
|
||||||
|
if (dir != null) {
|
||||||
|
cubot.setDirection(Direction.getDirection(b));
|
||||||
|
status.setErrorFlag(false);
|
||||||
|
} else {
|
||||||
|
status.setErrorFlag(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
cubot.setCurrentAction(Action.WALKING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,35 +20,35 @@ public class UserCreationListener implements GameEventListener {
|
|||||||
@Override
|
@Override
|
||||||
public void handle(GameEvent event) {
|
public void handle(GameEvent event) {
|
||||||
|
|
||||||
User user = (User) event.getSource();
|
|
||||||
|
|
||||||
LogManager.LOGGER.fine("(Plugin) Handled User creation event (Cubot Plugin)");
|
|
||||||
|
|
||||||
Cubot cubot = new Cubot();
|
|
||||||
|
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
int spawnX = GameServer.INSTANCE.getConfig().getInt("new_user_worldX") + random.nextInt(5);
|
|
||||||
int spawnY = GameServer.INSTANCE.getConfig().getInt("new_user_worldY") + random.nextInt(5);
|
|
||||||
|
|
||||||
cubot.setWorld(GameServer.INSTANCE.getGameUniverse().getWorld(spawnX, spawnY, true));
|
|
||||||
cubot.getWorld().getGameObjects().add(cubot);
|
|
||||||
cubot.getWorld().incUpdatable();
|
|
||||||
|
|
||||||
|
User user = (User) event.getSource();
|
||||||
|
Cubot cubot = new Cubot();
|
||||||
cubot.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId());
|
cubot.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId());
|
||||||
|
|
||||||
cubot.setHeldItem(GameServer.INSTANCE.getConfig().getInt("new_user_item"));
|
Point point = null;
|
||||||
|
while (point == null || cubot.getWorld() == null) {
|
||||||
|
int spawnX = GameServer.INSTANCE.getConfig().getInt("new_user_worldX") + random.nextInt(5);
|
||||||
|
int spawnY = GameServer.INSTANCE.getConfig().getInt("new_user_worldY") + random.nextInt(5);
|
||||||
|
cubot.setWorld(GameServer.INSTANCE.getGameUniverse().getWorld(spawnX, spawnY, true));
|
||||||
|
|
||||||
|
point = cubot.getWorld().getRandomPassableTile();
|
||||||
|
}
|
||||||
|
|
||||||
|
cubot.setX(point.x);
|
||||||
|
cubot.setY(point.y);
|
||||||
|
cubot.getWorld().addObject(cubot);
|
||||||
|
cubot.getWorld().incUpdatable();
|
||||||
|
|
||||||
|
cubot.setHeldItem(GameServer.INSTANCE.getConfig().getInt("new_user_item"));
|
||||||
cubot.setEnergy(GameServer.INSTANCE.getConfig().getInt("battery_max_energy"));
|
cubot.setEnergy(GameServer.INSTANCE.getConfig().getInt("battery_max_energy"));
|
||||||
cubot.setMaxEnergy(GameServer.INSTANCE.getConfig().getInt("battery_max_energy"));
|
cubot.setMaxEnergy(GameServer.INSTANCE.getConfig().getInt("battery_max_energy"));
|
||||||
|
|
||||||
cubot.setParent(user);
|
cubot.setParent(user);
|
||||||
|
|
||||||
Point point = cubot.getWorld().getRandomPassableTile();
|
|
||||||
|
|
||||||
cubot.setX(point.x);
|
|
||||||
cubot.setY(point.y);
|
|
||||||
|
|
||||||
user.setControlledUnit(cubot);
|
user.setControlledUnit(cubot);
|
||||||
|
|
||||||
|
LogManager.LOGGER.fine("(Plugin) Handled User creation event (Cubot Plugin)");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,6 @@ public class CubotTest {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
assertEquals(1,2);
|
assertEquals(1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -74,7 +74,7 @@ public class Factory extends GameObject implements Updatable {
|
|||||||
npc.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId());
|
npc.setObjectId(GameServer.INSTANCE.getGameUniverse().getNextObjectId());
|
||||||
npc.setX(p.x);
|
npc.setX(p.x);
|
||||||
npc.setY(p.y);
|
npc.setY(p.y);
|
||||||
getWorld().getGameObjects().add(npc);
|
getWorld().addObject(npc);
|
||||||
getWorld().incUpdatable();
|
getWorld().incUpdatable();
|
||||||
npc.setFactory(this);
|
npc.setFactory(this);
|
||||||
|
|
||||||
|
@ -33,14 +33,9 @@ public class HarvestTask extends NPCTask {
|
|||||||
|
|
||||||
if (pause == 0) {
|
if (pause == 0) {
|
||||||
//Get biomass
|
//Get biomass
|
||||||
ArrayList<GameObject> biomass = new ArrayList<>(10);
|
/* todo replace by some sort of .collect call with object
|
||||||
|
id (See https://github.com/simon987/Much-Assembly-Required/pull/66)*/
|
||||||
for (GameObject object : npc.getWorld().getGameObjects()) {
|
ArrayList<GameObject> biomass = npc.getWorld().findObjects(0x4000);
|
||||||
//Plant MAP_INFO
|
|
||||||
if ((object.getMapInfo() & 0x4000) == 0x4000) {
|
|
||||||
biomass.add(object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get closest one
|
//Get closest one
|
||||||
int minDist = Integer.MAX_VALUE;
|
int minDist = Integer.MAX_VALUE;
|
||||||
|
@ -48,7 +48,9 @@ public class HarvesterNPC extends NonPlayerCharacter {
|
|||||||
@Override
|
@Override
|
||||||
public void onDeadCallback() {
|
public void onDeadCallback() {
|
||||||
|
|
||||||
getFactory().getNpcs().remove(this);
|
if (getFactory() != null && getFactory().getNpcs() != null) {
|
||||||
|
getFactory().getNpcs().remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
GameServer.INSTANCE.getEventDispatcher().dispatch(
|
GameServer.INSTANCE.getEventDispatcher().dispatch(
|
||||||
new ObjectDeathEvent(this, ID));
|
new ObjectDeathEvent(this, ID));
|
||||||
|
@ -53,7 +53,7 @@ public class WorldCreationListener implements GameEventListener {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
world.getGameObjects().add(factory);
|
world.addObject(factory);
|
||||||
world.incUpdatable();
|
world.incUpdatable();
|
||||||
|
|
||||||
LogManager.LOGGER.info("Spawned Factory at (" + world.getX() + ", " + world.getY() +
|
LogManager.LOGGER.info("Spawned Factory at (" + world.getX() + ", " + world.getY() +
|
||||||
@ -84,7 +84,7 @@ public class WorldCreationListener implements GameEventListener {
|
|||||||
|
|
||||||
if (radioTower.getAdjacentTile() != null) {
|
if (radioTower.getAdjacentTile() != null) {
|
||||||
//Radio Tower has adjacent tiles
|
//Radio Tower has adjacent tiles
|
||||||
world.getGameObjects().add(radioTower);
|
world.addObject(radioTower);
|
||||||
world.incUpdatable(); //In case the Factory couldn't be spawned.
|
world.incUpdatable(); //In case the Factory couldn't be spawned.
|
||||||
|
|
||||||
NpcPlugin.getRadioTowers().add(radioTower);
|
NpcPlugin.getRadioTowers().add(radioTower);
|
||||||
|
@ -29,18 +29,23 @@ public class ObjectDeathListener implements GameEventListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(GameEvent event) {
|
public void handle(GameEvent event) {
|
||||||
// a HarvesterNPC ObjectDeathEvent is received
|
|
||||||
// TODO: setup enum with all GameObject type IDs
|
// TODO: setup enum with all GameObject type IDs
|
||||||
if (((ObjectDeathEvent) event).getSourceObjectId() == 10) {
|
if (((ObjectDeathEvent) event).getSourceObjectId() == 10) {
|
||||||
|
//An HarvesterNPC ObjectDeathEvent is received
|
||||||
GameObject dyingHarvesterNPC = (GameObject)event.getSource();
|
GameObject dyingHarvesterNPC = (GameObject)event.getSource();
|
||||||
|
|
||||||
// create a new biomass
|
|
||||||
BiomassBlob newBiomassBlob = createBiomassBlobAt(
|
//Don't spawn biomass on World border
|
||||||
dyingHarvesterNPC.getX(), dyingHarvesterNPC.getY(), dyingHarvesterNPC.getWorld());
|
if (dyingHarvesterNPC.getX() != 0 && dyingHarvesterNPC.getX() != World.WORLD_SIZE - 1 &&
|
||||||
// add it to the world game objects
|
dyingHarvesterNPC.getY() != 0 && dyingHarvesterNPC.getY() != World.WORLD_SIZE - 1) {
|
||||||
dyingHarvesterNPC.getWorld().getGameObjects().add(newBiomassBlob);
|
//Create a new biomass
|
||||||
LogManager.LOGGER.fine("Spawned biomass at (" + newBiomassBlob.getX() +
|
BiomassBlob newBiomassBlob = createBiomassBlobAt(
|
||||||
", " + newBiomassBlob.getY() + ")");
|
dyingHarvesterNPC.getX(), dyingHarvesterNPC.getY(), dyingHarvesterNPC.getWorld());
|
||||||
|
//Add it to the world game objects
|
||||||
|
dyingHarvesterNPC.getWorld().addObject(newBiomassBlob);
|
||||||
|
LogManager.LOGGER.fine("Spawned biomass at (" + newBiomassBlob.getX() +
|
||||||
|
", " + newBiomassBlob.getY() + ")");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,9 @@ public class WorldCreationListener implements GameEventListener {
|
|||||||
ArrayList<BiomassBlob> biomassBlobs = WorldUtils.generateBlobs(((WorldGenerationEvent) event).getWorld(),
|
ArrayList<BiomassBlob> biomassBlobs = WorldUtils.generateBlobs(((WorldGenerationEvent) event).getWorld(),
|
||||||
minCount, maxCount, yield);
|
minCount, maxCount, yield);
|
||||||
|
|
||||||
((WorldGenerationEvent) event).getWorld().getGameObjects().addAll(biomassBlobs);
|
for (BiomassBlob blob : biomassBlobs) {
|
||||||
|
((WorldGenerationEvent) event).getWorld().addObject(blob);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,11 @@ public class WorldUpdateListener implements GameEventListener {
|
|||||||
|
|
||||||
private HashMap<World, Long> worldWaitMap = new HashMap<>(200);
|
private HashMap<World, Long> worldWaitMap = new HashMap<>(200);
|
||||||
|
|
||||||
private int minBlobCount;
|
private static int minBlobCount;
|
||||||
private int maxBlobCount;
|
private static int maxBlobCount;
|
||||||
private int blobYield;
|
private static int blobYield;
|
||||||
private int waitTime;
|
private static int waitTime;
|
||||||
private int blobThreshold;
|
private static int blobThreshold;
|
||||||
|
|
||||||
public WorldUpdateListener(ServerConfiguration config) {
|
public WorldUpdateListener(ServerConfiguration config) {
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ public class WorldUpdateListener implements GameEventListener {
|
|||||||
World world = ((WorldUpdateEvent) event).getWorld();
|
World world = ((WorldUpdateEvent) event).getWorld();
|
||||||
|
|
||||||
//If there is less than the respawn threshold,
|
//If there is less than the respawn threshold,
|
||||||
if (world.getGameObjects(BiomassBlob.class).size() < blobThreshold) {
|
if (world.findObjects(BiomassBlob.class).size() < blobThreshold) {
|
||||||
|
|
||||||
//Set a timer for respawn_time ticks
|
//Set a timer for respawn_time ticks
|
||||||
if (!worldWaitMap.containsKey(world) || worldWaitMap.get(world) == 0L) {
|
if (!worldWaitMap.containsKey(world) || worldWaitMap.get(world) == 0L) {
|
||||||
@ -59,7 +59,9 @@ public class WorldUpdateListener implements GameEventListener {
|
|||||||
//If the timer was set less than respawn_time ticks ago, respawn the blobs
|
//If the timer was set less than respawn_time ticks ago, respawn the blobs
|
||||||
ArrayList<BiomassBlob> newBlobs = WorldUtils.generateBlobs(world, minBlobCount,
|
ArrayList<BiomassBlob> newBlobs = WorldUtils.generateBlobs(world, minBlobCount,
|
||||||
maxBlobCount, blobYield);
|
maxBlobCount, blobYield);
|
||||||
world.getGameObjects().addAll(newBlobs);
|
for (BiomassBlob blob : newBlobs) {
|
||||||
|
world.addObject(blob);
|
||||||
|
}
|
||||||
|
|
||||||
//Set the 'waitUntil' time to 0 to indicate that we are not waiting
|
//Set the 'waitUntil' time to 0 to indicate that we are not waiting
|
||||||
worldWaitMap.replace(world, 0L);
|
worldWaitMap.replace(world, 0L);
|
||||||
|
@ -75,6 +75,15 @@
|
|||||||
</archive>
|
</archive>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.7.2</version>
|
||||||
|
<configuration>
|
||||||
|
<workingDirectory>./src/main/resources</workingDirectory>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import net.simon987.server.event.TickEvent;
|
|||||||
import net.simon987.server.game.DayNightCycle;
|
import net.simon987.server.game.DayNightCycle;
|
||||||
import net.simon987.server.game.GameUniverse;
|
import net.simon987.server.game.GameUniverse;
|
||||||
import net.simon987.server.game.World;
|
import net.simon987.server.game.World;
|
||||||
import net.simon987.server.io.FileUtils;
|
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import net.simon987.server.plugin.PluginManager;
|
import net.simon987.server.plugin.PluginManager;
|
||||||
import net.simon987.server.user.User;
|
import net.simon987.server.user.User;
|
||||||
@ -18,8 +17,6 @@ import net.simon987.server.crypto.CryptoProvider;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class GameServer implements Runnable {
|
public class GameServer implements Runnable {
|
||||||
|
|
||||||
@ -39,11 +36,20 @@ public class GameServer implements Runnable {
|
|||||||
|
|
||||||
private CryptoProvider cryptoProvider;
|
private CryptoProvider cryptoProvider;
|
||||||
|
|
||||||
|
private MongoClient mongo = null;
|
||||||
|
|
||||||
public GameServer() {
|
public GameServer() {
|
||||||
|
|
||||||
this.config = new ServerConfiguration("config.properties");
|
this.config = new ServerConfiguration("config.properties");
|
||||||
|
|
||||||
|
try{
|
||||||
|
mongo = new MongoClient("localhost", 27017);
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
gameUniverse = new GameUniverse(config);
|
gameUniverse = new GameUniverse(config);
|
||||||
|
gameUniverse.setMongo(mongo);
|
||||||
pluginManager = new PluginManager();
|
pluginManager = new PluginManager();
|
||||||
|
|
||||||
maxExecutionTime = config.getInt("user_timeout");
|
maxExecutionTime = config.getInt("user_timeout");
|
||||||
@ -130,8 +136,7 @@ public class GameServer implements Runnable {
|
|||||||
|
|
||||||
|
|
||||||
//Process user code
|
//Process user code
|
||||||
ArrayList<User> users_ = new ArrayList<>(gameUniverse.getUsers());
|
for (User user : gameUniverse.getUsers()) {
|
||||||
for (User user : users_) {
|
|
||||||
|
|
||||||
if (user.getCpu() != null) {
|
if (user.getCpu() != null) {
|
||||||
try {
|
try {
|
||||||
@ -151,10 +156,8 @@ public class GameServer implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Process each worlds
|
//Process each worlds
|
||||||
//Avoid concurrent modification
|
|
||||||
ArrayList<World> worlds = new ArrayList<>(gameUniverse.getWorlds());
|
|
||||||
int updatedWorlds = 0;
|
int updatedWorlds = 0;
|
||||||
for (World world : worlds) {
|
for (World world : gameUniverse.getWorlds()) {
|
||||||
if (world.shouldUpdate()) {
|
if (world.shouldUpdate()) {
|
||||||
world.update();
|
world.update();
|
||||||
updatedWorlds++;
|
updatedWorlds++;
|
||||||
@ -166,115 +169,100 @@ public class GameServer implements Runnable {
|
|||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up history files
|
|
||||||
if (gameUniverse.getTime() % config.getInt("clean_interval") == 0) {
|
|
||||||
FileUtils.cleanHistory(config.getInt("history_size"));
|
|
||||||
}
|
|
||||||
|
|
||||||
socketServer.tick();
|
socketServer.tick();
|
||||||
|
|
||||||
LogManager.LOGGER.info("Processed " + gameUniverse.getWorlds().size() + " worlds (" + updatedWorlds +
|
LogManager.LOGGER.info("Processed " + gameUniverse.getWorldCount() + " worlds (" + updatedWorlds +
|
||||||
") updated");
|
") updated");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void load() {
|
void load() {
|
||||||
|
|
||||||
LogManager.LOGGER.info("Loading from MongoDB");
|
LogManager.LOGGER.info("Loading all data from MongoDB");
|
||||||
MongoClient mongo;
|
|
||||||
try {
|
|
||||||
mongo = new MongoClient("localhost", 27017);
|
|
||||||
|
|
||||||
DB db = mongo.getDB("mar");
|
DB db = mongo.getDB("mar");
|
||||||
|
|
||||||
DBCollection worlds = db.getCollection("world");
|
DBCollection worlds = db.getCollection("world");
|
||||||
DBCollection users = db.getCollection("user");
|
DBCollection users = db.getCollection("user");
|
||||||
DBCollection server = db.getCollection("server");
|
DBCollection server = db.getCollection("server");
|
||||||
|
|
||||||
//Load worlds
|
BasicDBObject whereQuery = new BasicDBObject();
|
||||||
DBCursor cursor = worlds.find();
|
whereQuery.put("shouldUpdate", true);
|
||||||
while (cursor.hasNext()) {
|
DBCursor cursor = worlds.find(whereQuery);
|
||||||
GameServer.INSTANCE.getGameUniverse().getWorlds().add(World.deserialize(cursor.next()));
|
GameUniverse universe = GameServer.INSTANCE.getGameUniverse();
|
||||||
}
|
while (cursor.hasNext()) {
|
||||||
|
World w = World.deserialize(cursor.next());
|
||||||
//Load users
|
universe.addWorld(w);
|
||||||
cursor = users.find();
|
|
||||||
while (cursor.hasNext()) {
|
|
||||||
try {
|
|
||||||
GameServer.INSTANCE.getGameUniverse().getUsers().add(User.deserialize(cursor.next()));
|
|
||||||
} catch (CancelledException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Load misc server info
|
|
||||||
cursor = server.find();
|
|
||||||
if (cursor.hasNext()) {
|
|
||||||
DBObject serverObj = cursor.next();
|
|
||||||
gameUniverse.setTime((long) serverObj.get("time"));
|
|
||||||
gameUniverse.setNextObjectId((long) serverObj.get("nextObjectId"));
|
|
||||||
}
|
|
||||||
|
|
||||||
LogManager.LOGGER.info("Done loading! W:" + GameServer.INSTANCE.getGameUniverse().getWorlds().size() +
|
|
||||||
" | U:" + GameServer.INSTANCE.getGameUniverse().getUsers().size());
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Load users
|
||||||
|
cursor = users.find();
|
||||||
|
while (cursor.hasNext()) {
|
||||||
|
try {
|
||||||
|
universe.addUser(User.deserialize(cursor.next()));
|
||||||
|
} catch (CancelledException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load misc server info
|
||||||
|
cursor = server.find();
|
||||||
|
if (cursor.hasNext()) {
|
||||||
|
DBObject serverObj = cursor.next();
|
||||||
|
gameUniverse.setTime((long) serverObj.get("time"));
|
||||||
|
gameUniverse.setNextObjectId((long) serverObj.get("nextObjectId"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LogManager.LOGGER.info("Done loading! W:" + GameServer.INSTANCE.getGameUniverse().getWorldCount() +
|
||||||
|
" | U:" + GameServer.INSTANCE.getGameUniverse().getUserCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void save() {
|
private void save() {
|
||||||
|
|
||||||
LogManager.LOGGER.info("Saving to MongoDB | W:" + gameUniverse.getWorlds().size() + " | U:" + gameUniverse.getUsers().size());
|
LogManager.LOGGER.info("Saving to MongoDB | W:" + gameUniverse.getWorldCount() + " | U:" + gameUniverse.getUserCount());
|
||||||
|
try{
|
||||||
|
DB db = mongo.getDB("mar");
|
||||||
|
|
||||||
MongoClient mongo;
|
int unloaded_worlds = 0;
|
||||||
try {
|
|
||||||
mongo = new MongoClient("localhost", 27017);
|
|
||||||
|
|
||||||
DB db = mongo.getDB("mar");
|
DBCollection worlds = db.getCollection("world");
|
||||||
|
DBCollection users = db.getCollection("user");
|
||||||
|
DBCollection server = db.getCollection("server");
|
||||||
|
|
||||||
db.dropDatabase(); //Todo: Update database / keep history instead of overwriting
|
int insertedWorlds = 0;
|
||||||
|
GameUniverse universe = GameServer.INSTANCE.getGameUniverse();
|
||||||
DBCollection worlds = db.getCollection("world");
|
for (World w : universe.getWorlds()) {
|
||||||
DBCollection users = db.getCollection("user");
|
// LogManager.LOGGER.fine("Saving world "+w.getId()+" to mongodb");
|
||||||
DBCollection server = db.getCollection("server");
|
|
||||||
|
|
||||||
List<DBObject> worldDocuments = new ArrayList<>();
|
|
||||||
int perBatch = 35;
|
|
||||||
int insertedWorlds = 0;
|
|
||||||
ArrayList<World> worlds_ = new ArrayList<>(GameServer.INSTANCE.getGameUniverse().getWorlds());
|
|
||||||
for (World w : worlds_) {
|
|
||||||
worldDocuments.add(w.mongoSerialise());
|
|
||||||
insertedWorlds++;
|
insertedWorlds++;
|
||||||
|
worlds.save(w.mongoSerialise());
|
||||||
|
|
||||||
if (worldDocuments.size() >= perBatch || insertedWorlds >= GameServer.INSTANCE.getGameUniverse().getWorlds().size()) {
|
// If the world should unload, it is removed from the Universe after having been saved.
|
||||||
worlds.insert(worldDocuments);
|
if (w.shouldUnload()){
|
||||||
worldDocuments.clear();
|
unloaded_worlds++;
|
||||||
}
|
// LogManager.LOGGER.fine("Unloading world "+w.getId()+" from universe");
|
||||||
}
|
universe.removeWorld(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<DBObject> userDocuments = new ArrayList<>();
|
for (User u : GameServer.INSTANCE.getGameUniverse().getUsers()) {
|
||||||
int insertedUsers = 0;
|
|
||||||
ArrayList<User> users_ = new ArrayList<>(GameServer.INSTANCE.getGameUniverse().getUsers());
|
|
||||||
for (User u : users_) {
|
|
||||||
|
|
||||||
insertedUsers++;
|
if (!u.isGuest()) {
|
||||||
|
users.save(u.mongoSerialise());
|
||||||
|
}
|
||||||
|
|
||||||
if (!u.isGuest()) {
|
}
|
||||||
userDocuments.add(u.mongoSerialise());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userDocuments.size() >= perBatch || insertedUsers >= GameServer.INSTANCE.getGameUniverse().getUsers().size()) {
|
BasicDBObject serverObj = new BasicDBObject();
|
||||||
users.insert(userDocuments);
|
serverObj.put("_id","serverinfo"); // a constant id ensures only one entry is kept and updated, instead of a new entry created every save.
|
||||||
userDocuments.clear();
|
serverObj.put("time", gameUniverse.getTime());
|
||||||
}
|
serverObj.put("nextObjectId", gameUniverse.getNextObjectId());
|
||||||
}
|
server.save(serverObj);
|
||||||
|
|
||||||
BasicDBObject serverObj = new BasicDBObject();
|
LogManager.LOGGER.info(""+insertedWorlds+" worlds saved, "+unloaded_worlds+" unloaded");
|
||||||
serverObj.put("time", gameUniverse.getTime());
|
LogManager.LOGGER.info("Done!");
|
||||||
serverObj.put("nextObjectId", gameUniverse.getNextObjectId());
|
} catch (Exception e) {
|
||||||
server.insert(serverObj);
|
LogManager.LOGGER.severe("Problem happened during save function");
|
||||||
|
|
||||||
LogManager.LOGGER.info("Done!");
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ public class Assembler {
|
|||||||
|
|
||||||
private RegisterSet registerSet;
|
private RegisterSet registerSet;
|
||||||
|
|
||||||
private static final int MEM_SIZE = 0x10000; // Size in words
|
private static final int MEM_SIZE = 0x10000; // Size in words todo load from config
|
||||||
|
|
||||||
public Assembler(InstructionSet instructionSet, RegisterSet registerSet, ServerConfiguration config) {
|
public Assembler(InstructionSet instructionSet, RegisterSet registerSet, ServerConfiguration config) {
|
||||||
this.instructionSet = instructionSet;
|
this.instructionSet = instructionSet;
|
||||||
@ -54,7 +54,7 @@ public class Assembler {
|
|||||||
*/
|
*/
|
||||||
private static String removeLabel(String line) {
|
private static String removeLabel(String line) {
|
||||||
|
|
||||||
return line.replaceAll("\\b\\w*\\b:", "");
|
return line.replaceAll("^\\s*\\b\\w*\\b:", "");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,11 +97,11 @@ public class Assembler {
|
|||||||
line = removeComment(line);
|
line = removeComment(line);
|
||||||
|
|
||||||
//Check for labels
|
//Check for labels
|
||||||
Pattern pattern = Pattern.compile("\\b\\w*\\b:");
|
Pattern pattern = Pattern.compile("^\\s*\\b\\w*\\b:");
|
||||||
Matcher matcher = pattern.matcher(line);
|
Matcher matcher = pattern.matcher(line);
|
||||||
|
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
String label = matcher.group(0).substring(0, matcher.group(0).length() - 1);
|
String label = matcher.group(0).substring(0, matcher.group(0).length() - 1).trim();
|
||||||
|
|
||||||
LogManager.LOGGER.fine("DEBUG: Label " + label + " @ " + (result.origin + currentOffset));
|
LogManager.LOGGER.fine("DEBUG: Label " + label + " @ " + (result.origin + currentOffset));
|
||||||
result.labels.put(label, (char) (result.origin + currentOffset));
|
result.labels.put(label, (char) (result.origin + currentOffset));
|
||||||
@ -175,7 +175,18 @@ public class Assembler {
|
|||||||
out.writeChar(0);
|
out.writeChar(0);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidOperandException("Invalid operand \"" + value + '"', currentLine);
|
|
||||||
|
//Integer.decode failed, try binary
|
||||||
|
if (value.startsWith("0b")) {
|
||||||
|
try {
|
||||||
|
out.writeChar(Integer.parseInt(value.substring(2), 2));
|
||||||
|
} catch (NumberFormatException e2) {
|
||||||
|
throw new InvalidOperandException("Invalid operand \"" + value + '"', currentLine);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new InvalidOperandException("Invalid operand \"" + value + '"', currentLine);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,25 +267,25 @@ public class Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for and handle segment declarations (.text & .data)
|
* Check for and handle section declarations (.text & .data)
|
||||||
*
|
*
|
||||||
* @param line Current line
|
* @param line Current line
|
||||||
*/
|
*/
|
||||||
private static void checkForSegmentDeclaration(String line, AssemblyResult result,
|
private static void checkForSectionDeclaration(String line, AssemblyResult result,
|
||||||
int currentLine, int currentOffset) throws AssemblyException {
|
int currentLine, int currentOffset) throws AssemblyException {
|
||||||
|
|
||||||
String[] tokens = line.split("\\s+");
|
String[] tokens = line.split("\\s+");
|
||||||
|
|
||||||
if (tokens[0].toUpperCase().equals(".TEXT")) {
|
if (tokens[0].toUpperCase().equals(".TEXT")) {
|
||||||
|
|
||||||
result.defineSegment(Segment.TEXT, currentLine, currentOffset);
|
result.defineSecton(Section.TEXT, currentLine, currentOffset);
|
||||||
throw new PseudoInstructionException(currentLine);
|
throw new PseudoInstructionException(currentLine);
|
||||||
|
|
||||||
} else if (tokens[0].toUpperCase().equals(".DATA")) {
|
} else if (tokens[0].toUpperCase().equals(".DATA")) {
|
||||||
|
|
||||||
LogManager.LOGGER.fine("DEBUG: .data @" + currentLine);
|
LogManager.LOGGER.fine("DEBUG: .data @" + currentLine);
|
||||||
|
|
||||||
result.defineSegment(Segment.DATA, currentLine, currentOffset);
|
result.defineSecton(Section.DATA, currentLine, currentOffset);
|
||||||
throw new PseudoInstructionException(currentLine);
|
throw new PseudoInstructionException(currentLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -296,7 +307,7 @@ public class Assembler {
|
|||||||
String[] tokens = line.split("\\s+");
|
String[] tokens = line.split("\\s+");
|
||||||
|
|
||||||
|
|
||||||
if (line.toUpperCase().contains(" EQU ")) {
|
if (line.toUpperCase().matches(".*\\bEQU\\b.*")) {
|
||||||
if (tokens[1].toUpperCase().equals("EQU") && tokens.length == 3) {
|
if (tokens[1].toUpperCase().equals("EQU") && tokens.length == 3) {
|
||||||
try {
|
try {
|
||||||
//Save value as a label
|
//Save value as a label
|
||||||
@ -385,7 +396,7 @@ public class Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Check for pseudo instructions
|
//Check for pseudo instructions
|
||||||
checkForSegmentDeclaration(line, result, currentLine, currentOffset);
|
checkForSectionDeclaration(line, result, currentLine, currentOffset);
|
||||||
checkForEQUInstruction(line, result.labels, currentLine);
|
checkForEQUInstruction(line, result.labels, currentLine);
|
||||||
checkForORGInstruction(line, result, currentLine);
|
checkForORGInstruction(line, result, currentLine);
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package net.simon987.server.assembly;
|
|||||||
|
|
||||||
import net.simon987.server.ServerConfiguration;
|
import net.simon987.server.ServerConfiguration;
|
||||||
import net.simon987.server.assembly.exception.AssemblyException;
|
import net.simon987.server.assembly.exception.AssemblyException;
|
||||||
import net.simon987.server.assembly.exception.DuplicateSegmentException;
|
import net.simon987.server.assembly.exception.DuplicateSectionException;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@ -27,15 +27,15 @@ public class AssemblyResult {
|
|||||||
* List of exceptions encountered during the assembly attempt,
|
* List of exceptions encountered during the assembly attempt,
|
||||||
* they will be displayed in the editor
|
* they will be displayed in the editor
|
||||||
*/
|
*/
|
||||||
ArrayList<AssemblyException> exceptions = new ArrayList<>(50);
|
public ArrayList<AssemblyException> exceptions = new ArrayList<>(50);
|
||||||
/**
|
/**
|
||||||
* Offset of the code segment
|
* Offset of the code segment
|
||||||
*/
|
*/
|
||||||
private int codeSegmentOffset;
|
private int codeSectionOffset;
|
||||||
/**
|
/**
|
||||||
* Line of the code segment definition
|
* Line of the code segment definition
|
||||||
*/
|
*/
|
||||||
private int codeSegmentLine;
|
private int codeSectionLine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The encoded user code (will be incomplete or invalid if the
|
* The encoded user code (will be incomplete or invalid if the
|
||||||
@ -45,60 +45,60 @@ public class AssemblyResult {
|
|||||||
/**
|
/**
|
||||||
* Offset of the data segment
|
* Offset of the data segment
|
||||||
*/
|
*/
|
||||||
private int dataSegmentOffset;
|
private int dataSectionOffset;
|
||||||
/**
|
/**
|
||||||
* Line of the data segment definition
|
* Line of the data segment definition
|
||||||
*/
|
*/
|
||||||
private int dataSegmentLine;
|
private int dataSectionLine;
|
||||||
/**
|
/**
|
||||||
* Whether or not the code segment is set
|
* Whether or not the code segment is set
|
||||||
*/
|
*/
|
||||||
private boolean codeSegmentSet = false;
|
private boolean codeSectionSet = false;
|
||||||
/**
|
/**
|
||||||
* Whether or not the data segment is set
|
* Whether or not the data segment is set
|
||||||
*/
|
*/
|
||||||
private boolean dataSegmentSet = false;
|
private boolean dataSectionSet = false;
|
||||||
|
|
||||||
AssemblyResult(ServerConfiguration config) {
|
AssemblyResult(ServerConfiguration config) {
|
||||||
origin = config.getInt("org_offset");
|
origin = config.getInt("org_offset");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a segment.
|
* Define a section.
|
||||||
*
|
*
|
||||||
* @param segment Segment to define
|
* @param section Section to define
|
||||||
* @param currentOffset Current offset, in bytes of the segment
|
* @param currentOffset Current offset, in bytes of the section
|
||||||
* @param currentLine Line number of the segment declaration
|
* @param currentLine Line number of the section declaration
|
||||||
* @throws DuplicateSegmentException when a segment is defined twice
|
* @throws DuplicateSectionException when a section is defined twice
|
||||||
*/
|
*/
|
||||||
void defineSegment(Segment segment, int currentLine, int currentOffset) throws DuplicateSegmentException {
|
void defineSecton(Section section, int currentLine, int currentOffset) throws DuplicateSectionException {
|
||||||
|
|
||||||
if (segment == Segment.TEXT) {
|
if (section == Section.TEXT) {
|
||||||
//Code segment
|
//Code section
|
||||||
|
|
||||||
if (!codeSegmentSet) {
|
if (!codeSectionSet) {
|
||||||
codeSegmentOffset = origin + currentOffset;
|
codeSectionOffset = origin + currentOffset;
|
||||||
codeSegmentLine = currentLine;
|
codeSectionLine = currentLine;
|
||||||
|
|
||||||
LogManager.LOGGER.fine("DEBUG: .text offset @" + codeSegmentOffset);
|
LogManager.LOGGER.fine("DEBUG: .text offset @" + codeSectionOffset);
|
||||||
|
|
||||||
|
|
||||||
codeSegmentSet = true;
|
codeSectionSet = true;
|
||||||
} else {
|
} else {
|
||||||
throw new DuplicateSegmentException(currentLine);
|
throw new DuplicateSectionException(currentLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//Data segment
|
//Data section
|
||||||
if (!dataSegmentSet) {
|
if (!dataSectionSet) {
|
||||||
dataSegmentOffset = origin + currentOffset;
|
dataSectionOffset = origin + currentOffset;
|
||||||
dataSegmentLine = currentLine;
|
dataSectionLine = currentLine;
|
||||||
|
|
||||||
LogManager.LOGGER.fine("DEBUG: .data offset @" + dataSegmentOffset);
|
LogManager.LOGGER.fine("DEBUG: .data offset @" + dataSectionOffset);
|
||||||
|
|
||||||
dataSegmentSet = true;
|
dataSectionSet = true;
|
||||||
} else {
|
} else {
|
||||||
throw new DuplicateSegmentException(currentLine);
|
throw new DuplicateSectionException(currentLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -113,9 +113,9 @@ public class AssemblyResult {
|
|||||||
return assembledCode;
|
return assembledCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCodeSegmentOffset() {
|
public int getCodeSectionOffset() {
|
||||||
if (codeSegmentSet) {
|
if (codeSectionSet) {
|
||||||
return codeSegmentOffset;
|
return codeSectionOffset;
|
||||||
} else {
|
} else {
|
||||||
return origin;
|
return origin;
|
||||||
}
|
}
|
||||||
|
@ -43,10 +43,10 @@ public class CPU implements MongoSerialisable {
|
|||||||
private RegisterSet registerSet;
|
private RegisterSet registerSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Offset of the code segment. The code starts to get
|
* Offset of the code section. The code starts to get
|
||||||
* executed at this address each tick. Defaults to org_offset@config.properties
|
* executed at this address each tick. Defaults to org_offset@config.properties
|
||||||
*/
|
*/
|
||||||
private int codeSegmentOffset;
|
private int codeSectionOffset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instruction pointer, always points to the next instruction
|
* Instruction pointer, always points to the next instruction
|
||||||
@ -73,7 +73,7 @@ public class CPU implements MongoSerialisable {
|
|||||||
instructionSet = new DefaultInstructionSet();
|
instructionSet = new DefaultInstructionSet();
|
||||||
registerSet = new DefaultRegisterSet();
|
registerSet = new DefaultRegisterSet();
|
||||||
attachedHardware = new HashMap<>();
|
attachedHardware = new HashMap<>();
|
||||||
codeSegmentOffset = config.getInt("org_offset");
|
codeSectionOffset = config.getInt("org_offset");
|
||||||
|
|
||||||
instructionSet.add(new JmpInstruction(this));
|
instructionSet.add(new JmpInstruction(this));
|
||||||
instructionSet.add(new JnzInstruction(this));
|
instructionSet.add(new JnzInstruction(this));
|
||||||
@ -112,7 +112,7 @@ public class CPU implements MongoSerialisable {
|
|||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
status.clear();
|
status.clear();
|
||||||
ip = codeSegmentOffset;
|
ip = codeSectionOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int execute(int timeout) {
|
public int execute(int timeout) {
|
||||||
@ -352,7 +352,7 @@ public class CPU implements MongoSerialisable {
|
|||||||
dbObject.put("memory", memory.mongoSerialise());
|
dbObject.put("memory", memory.mongoSerialise());
|
||||||
|
|
||||||
dbObject.put("registerSet", registerSet.mongoSerialise());
|
dbObject.put("registerSet", registerSet.mongoSerialise());
|
||||||
dbObject.put("codeSegmentOffset", codeSegmentOffset);
|
dbObject.put("codeSegmentOffset", codeSectionOffset);
|
||||||
|
|
||||||
BasicDBList hardwareList = new BasicDBList();
|
BasicDBList hardwareList = new BasicDBList();
|
||||||
|
|
||||||
@ -375,7 +375,7 @@ public class CPU implements MongoSerialisable {
|
|||||||
|
|
||||||
CPU cpu = new CPU(GameServer.INSTANCE.getConfig(), user);
|
CPU cpu = new CPU(GameServer.INSTANCE.getConfig(), user);
|
||||||
|
|
||||||
cpu.codeSegmentOffset = (int) obj.get("codeSegmentOffset");
|
cpu.codeSectionOffset = (int) obj.get("codeSegmentOffset");
|
||||||
|
|
||||||
BasicDBList hardwareList = (BasicDBList) obj.get("hardware");
|
BasicDBList hardwareList = (BasicDBList) obj.get("hardware");
|
||||||
|
|
||||||
@ -416,8 +416,8 @@ public class CPU implements MongoSerialisable {
|
|||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCodeSegmentOffset(int codeSegmentOffset) {
|
public void setCodeSectionOffset(int codeSectionOffset) {
|
||||||
this.codeSegmentOffset = codeSegmentOffset;
|
this.codeSectionOffset = codeSectionOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void attachHardware(CpuHardware hardware, int address) {
|
public void attachHardware(CpuHardware hardware, int address) {
|
||||||
|
@ -44,6 +44,8 @@ public class DefaultInstructionSet implements InstructionSet {
|
|||||||
add(new RclInstruction());
|
add(new RclInstruction());
|
||||||
add(new RcrInstruction());
|
add(new RcrInstruction());
|
||||||
add(new SarInstruction());
|
add(new SarInstruction());
|
||||||
|
add(new IncInstruction());
|
||||||
|
add(new DecInstruction());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,7 +6,6 @@ import com.mongodb.DBObject;
|
|||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.io.MongoSerialisable;
|
import net.simon987.server.io.MongoSerialisable;
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import org.json.simple.JSONObject;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -157,36 +156,6 @@ public class Memory implements Target, MongoSerialisable {
|
|||||||
return memory;
|
return memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Memory deserialize(JSONObject json) {
|
|
||||||
|
|
||||||
Memory memory = new Memory(0);
|
|
||||||
|
|
||||||
String zipBytesStr = (String) json.get("zipBytes");
|
|
||||||
|
|
||||||
if (zipBytesStr != null) {
|
|
||||||
byte[] compressedBytes = Base64.getDecoder().decode((String) json.get("zipBytes"));
|
|
||||||
|
|
||||||
try {
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
Inflater decompressor = new Inflater(true);
|
|
||||||
InflaterOutputStream inflaterOutputStream = new InflaterOutputStream(baos, decompressor);
|
|
||||||
inflaterOutputStream.write(compressedBytes);
|
|
||||||
inflaterOutputStream.close();
|
|
||||||
|
|
||||||
memory.setBytes(baos.toByteArray());
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LogManager.LOGGER.severe("Memory was manually deleted");
|
|
||||||
memory = new Memory(GameServer.INSTANCE.getConfig().getInt("memory_size"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBytes(byte[] bytes) {
|
public void setBytes(byte[] bytes) {
|
||||||
this.words = new char[bytes.length / 2];
|
this.words = new char[bytes.length / 2];
|
||||||
ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).asCharBuffer().get(this.words);
|
ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).asCharBuffer().get(this.words);
|
||||||
|
@ -224,11 +224,30 @@ public class Operand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//label is invalid
|
//label is invalid
|
||||||
|
|
||||||
data = Integer.decode(expr);
|
data = Integer.decode(expr);
|
||||||
value += registerSet.size() * 2; //refers to memory with disp
|
value += registerSet.size() * 2; //refers to memory with disp
|
||||||
return true;
|
return true;
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
|
|
||||||
|
//Integer.decode failed, try binary
|
||||||
|
if (expr.startsWith("+0b")) {
|
||||||
|
try {
|
||||||
|
data = Integer.parseInt(expr.substring(3), 2);
|
||||||
|
value += registerSet.size() * 2; //refers to memory with disp
|
||||||
|
return true;
|
||||||
|
} catch (NumberFormatException e2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (expr.startsWith("-0b")) {
|
||||||
|
try {
|
||||||
|
data = -Integer.parseInt(expr.substring(3), 2);
|
||||||
|
value += registerSet.size() * 2; //refers to memory with disp
|
||||||
|
return true;
|
||||||
|
} catch (NumberFormatException e2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,9 @@ package net.simon987.server.assembly;
|
|||||||
/**
|
/**
|
||||||
* Section of a user-created program.
|
* Section of a user-created program.
|
||||||
* The execution will start at the beginning of the code
|
* The execution will start at the beginning of the code
|
||||||
* segment and a warning message will be displayed when execution
|
* segment.
|
||||||
* reached the data segment during debugging
|
|
||||||
*/
|
*/
|
||||||
public enum Segment {
|
public enum Section {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Code section of the program. Contains executable code
|
* Code section of the program. Contains executable code
|
@ -3,17 +3,17 @@ package net.simon987.server.assembly.exception;
|
|||||||
/**
|
/**
|
||||||
* Threw when a user attempts to define the same section twice
|
* Threw when a user attempts to define the same section twice
|
||||||
*/
|
*/
|
||||||
public class DuplicateSegmentException extends AssemblyException {
|
public class DuplicateSectionException extends AssemblyException {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message of the exception
|
* Message of the exception
|
||||||
*/
|
*/
|
||||||
private static final String message = "Segments can only be defined once";
|
private static final String message = "Sections can only be defined once";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Duplicate Segment Exception
|
* Create a new Duplicate Section Exception
|
||||||
*/
|
*/
|
||||||
public DuplicateSegmentException(int line) {
|
public DuplicateSectionException(int line) {
|
||||||
super(message, line);
|
super(message, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ public class FatalAssemblyException extends AssemblyException {
|
|||||||
private static final String message = "A fatal assembly error has occurred";
|
private static final String message = "A fatal assembly error has occurred";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Duplicate Segment Exception
|
* Create a new Duplicate Section Exception
|
||||||
*/
|
*/
|
||||||
public FatalAssemblyException(String msg, int line) {
|
public FatalAssemblyException(String msg, int line) {
|
||||||
super(msg, line);
|
super(msg, line);
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
package net.simon987.server.assembly.instruction;
|
||||||
|
|
||||||
|
import net.simon987.server.assembly.Instruction;
|
||||||
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.assembly.Target;
|
||||||
|
import net.simon987.server.assembly.Util;
|
||||||
|
|
||||||
|
public class DecInstruction extends Instruction {
|
||||||
|
|
||||||
|
public static final int OPCODE = 0x2B;
|
||||||
|
|
||||||
|
public DecInstruction() {
|
||||||
|
super("dec", OPCODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Status execute(Target dst, int dstIndex, Status status) {
|
||||||
|
char a = (char) dst.get(dstIndex);
|
||||||
|
int result = a - 1;
|
||||||
|
|
||||||
|
// Like x86 Carry flag is preserved during INC/DEC
|
||||||
|
// (Use ADD x, 1 to have carry flag change)
|
||||||
|
// Other flags set according to result
|
||||||
|
status.setSignFlag(Util.checkSign16(result));
|
||||||
|
status.setZeroFlag((char) result == 0);
|
||||||
|
status.setOverflowFlag(Util.checkOverFlowSub16(a, 1));
|
||||||
|
|
||||||
|
dst.set(dstIndex, result);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
package net.simon987.server.assembly.instruction;
|
||||||
|
|
||||||
|
import net.simon987.server.assembly.Instruction;
|
||||||
|
import net.simon987.server.assembly.Status;
|
||||||
|
import net.simon987.server.assembly.Target;
|
||||||
|
import net.simon987.server.assembly.Util;
|
||||||
|
|
||||||
|
public class IncInstruction extends Instruction {
|
||||||
|
|
||||||
|
public static final int OPCODE = 0x2A;
|
||||||
|
|
||||||
|
public IncInstruction() {
|
||||||
|
super("inc", OPCODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Status execute(Target dst, int dstIndex, Status status) {
|
||||||
|
char a = (char) dst.get(dstIndex);
|
||||||
|
int result = a + 1;
|
||||||
|
|
||||||
|
// Like x86 Carry flag is preserved during INC/DEC
|
||||||
|
// (Use ADD x, 1 to have carry flag change)
|
||||||
|
// Other flags set according to result
|
||||||
|
status.setSignFlag(Util.checkSign16(result));
|
||||||
|
status.setZeroFlag((char) result == 0);
|
||||||
|
status.setOverflowFlag(Util.checkOverFlowAdd16(a, 1));
|
||||||
|
|
||||||
|
dst.set(dstIndex, result);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,12 +7,14 @@ public class ObjectDeathEvent extends GameEvent {
|
|||||||
/**
|
/**
|
||||||
* The GameObject type ID of object that init this event
|
* The GameObject type ID of object that init this event
|
||||||
*/
|
*/
|
||||||
private int sourceObjectId;
|
private long sourceObjectId;
|
||||||
|
|
||||||
public ObjectDeathEvent(Object source, int sourceObjectId) {
|
public ObjectDeathEvent(Object source, int sourceObjectId) {
|
||||||
setSource(source);
|
setSource(source);
|
||||||
this.sourceObjectId = sourceObjectId;
|
this.sourceObjectId = sourceObjectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSourceObjectId() { return sourceObjectId; }
|
public long getSourceObjectId() {
|
||||||
|
return sourceObjectId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
package net.simon987.server.game;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Types of GameEffects
|
|
||||||
*/
|
|
||||||
public enum EffectType {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Warning icon
|
|
||||||
*/
|
|
||||||
WARNING,
|
|
||||||
/**
|
|
||||||
* Error icon
|
|
||||||
*/
|
|
||||||
ERROR,
|
|
||||||
/**
|
|
||||||
* Dig particle effect
|
|
||||||
*/
|
|
||||||
DIG,
|
|
||||||
/**
|
|
||||||
* 'A' Icon
|
|
||||||
*/
|
|
||||||
A_EMOTE
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
package net.simon987.server.game;
|
|
||||||
|
|
||||||
import net.simon987.server.io.JSONSerialisable;
|
|
||||||
import org.json.simple.JSONObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a game effect in a World (e.g. Particles made when digging, Error animation, Attack effects etc..)
|
|
||||||
* <br>
|
|
||||||
* These effects are purely visual and could be changed or ignored by the client
|
|
||||||
*/
|
|
||||||
public class GameEffect implements JSONSerialisable {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type of the effect
|
|
||||||
*/
|
|
||||||
private EffectType type;
|
|
||||||
|
|
||||||
private int x;
|
|
||||||
|
|
||||||
private int y;
|
|
||||||
|
|
||||||
public GameEffect(EffectType type, int x, int y) {
|
|
||||||
this.type = type;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JSONObject serialise() {
|
|
||||||
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
|
|
||||||
json.put("x", x);
|
|
||||||
json.put("y", y);
|
|
||||||
json.put("type", type);
|
|
||||||
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EffectType getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setType(EffectType type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setX(int x) {
|
|
||||||
this.x = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setY(int y) {
|
|
||||||
this.y = y;
|
|
||||||
}
|
|
||||||
}
|
|
@ -84,9 +84,9 @@ public abstract class GameObject implements JSONSerialisable, MongoSerialisable
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (leftWorld != null) {
|
if (leftWorld != null) {
|
||||||
world.getGameObjects().remove(this);
|
world.removeObject(this);
|
||||||
world.decUpdatable();
|
world.decUpdatable();
|
||||||
leftWorld.getGameObjects().add(this);
|
leftWorld.addObject(this);
|
||||||
leftWorld.incUpdatable();
|
leftWorld.incUpdatable();
|
||||||
setWorld(leftWorld);
|
setWorld(leftWorld);
|
||||||
|
|
||||||
@ -103,9 +103,9 @@ public abstract class GameObject implements JSONSerialisable, MongoSerialisable
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rightWorld != null) {
|
if (rightWorld != null) {
|
||||||
world.getGameObjects().remove(this);
|
world.removeObject(this);
|
||||||
world.decUpdatable();
|
world.decUpdatable();
|
||||||
rightWorld.getGameObjects().add(this);
|
rightWorld.addObject(this);
|
||||||
rightWorld.incUpdatable();
|
rightWorld.incUpdatable();
|
||||||
setWorld(rightWorld);
|
setWorld(rightWorld);
|
||||||
|
|
||||||
@ -123,9 +123,9 @@ public abstract class GameObject implements JSONSerialisable, MongoSerialisable
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (upWorld != null) {
|
if (upWorld != null) {
|
||||||
world.getGameObjects().remove(this);
|
world.removeObject(this);
|
||||||
world.decUpdatable();
|
world.decUpdatable();
|
||||||
upWorld.getGameObjects().add(this);
|
upWorld.addObject(this);
|
||||||
upWorld.incUpdatable();
|
upWorld.incUpdatable();
|
||||||
setWorld(upWorld);
|
setWorld(upWorld);
|
||||||
|
|
||||||
@ -143,9 +143,9 @@ public abstract class GameObject implements JSONSerialisable, MongoSerialisable
|
|||||||
|
|
||||||
|
|
||||||
if (downWorld != null) {
|
if (downWorld != null) {
|
||||||
world.getGameObjects().remove(this);
|
world.removeObject(this);
|
||||||
world.decUpdatable();
|
world.decUpdatable();
|
||||||
downWorld.getGameObjects().add(this);
|
downWorld.addObject(this);
|
||||||
downWorld.incUpdatable();
|
downWorld.incUpdatable();
|
||||||
setWorld(downWorld);
|
setWorld(downWorld);
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.simon987.server.game;
|
package net.simon987.server.game;
|
||||||
|
|
||||||
|
import com.mongodb.*;
|
||||||
import net.simon987.server.GameServer;
|
import net.simon987.server.GameServer;
|
||||||
import net.simon987.server.ServerConfiguration;
|
import net.simon987.server.ServerConfiguration;
|
||||||
import net.simon987.server.assembly.Assembler;
|
import net.simon987.server.assembly.Assembler;
|
||||||
@ -9,14 +10,20 @@ import net.simon987.server.assembly.exception.CancelledException;
|
|||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
import net.simon987.server.user.User;
|
import net.simon987.server.user.User;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class GameUniverse {
|
public class GameUniverse {
|
||||||
|
|
||||||
private ArrayList<World> worlds;
|
//private ArrayList<World> worlds;
|
||||||
private ArrayList<User> users;
|
private ConcurrentHashMap<String, World> worlds;
|
||||||
|
//username:user
|
||||||
|
private ConcurrentHashMap<String, User> users;
|
||||||
private WorldGenerator worldGenerator;
|
private WorldGenerator worldGenerator;
|
||||||
|
|
||||||
|
private MongoClient mongo = null;
|
||||||
|
|
||||||
|
|
||||||
private long time;
|
private long time;
|
||||||
|
|
||||||
private long nextObjectId = 0;
|
private long nextObjectId = 0;
|
||||||
@ -25,64 +32,144 @@ public class GameUniverse {
|
|||||||
|
|
||||||
public GameUniverse(ServerConfiguration config) {
|
public GameUniverse(ServerConfiguration config) {
|
||||||
|
|
||||||
worlds = new ArrayList<>(32);
|
worlds = new ConcurrentHashMap<>(256);
|
||||||
users = new ArrayList<>(16);
|
users = new ConcurrentHashMap<>(16);
|
||||||
|
|
||||||
worldGenerator = new WorldGenerator(config);
|
worldGenerator = new WorldGenerator(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMongo(MongoClient mongo){
|
||||||
|
this.mongo = mongo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTime() {
|
public long getTime() {
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public World getWorld(int x, int y, boolean createNew) {
|
/**
|
||||||
|
* Attempts loading a world from mongoDB by coordinates
|
||||||
|
*
|
||||||
|
* @param x the x coordinate of the world
|
||||||
|
* @param y the y coordinate of the world
|
||||||
|
*
|
||||||
|
* @return World, null if not found
|
||||||
|
*/
|
||||||
|
private World loadWorld(int x, int y){
|
||||||
|
|
||||||
|
DB db = mongo.getDB("mar");
|
||||||
|
DBCollection worlds = db.getCollection("world");
|
||||||
|
|
||||||
for (World world : worlds) {
|
BasicDBObject whereQuery = new BasicDBObject();
|
||||||
if (world.getX() == x && world.getY() == y) {
|
whereQuery.put("_id", World.idFromCoordinates(x,y));
|
||||||
return world;
|
DBCursor cursor = worlds.find(whereQuery);
|
||||||
}
|
if (cursor.hasNext()) {
|
||||||
|
World w = World.deserialize(cursor.next());
|
||||||
|
return w;
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
if (x >= 0 && x <= maxWidth && y >= 0 && y <= maxWidth) {
|
|
||||||
if (createNew) {
|
|
||||||
//World does not exist
|
|
||||||
World world = createWorld(x, y);
|
|
||||||
worlds.add(world);
|
|
||||||
|
|
||||||
return world;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public World createWorld(int x, int y) {
|
/**
|
||||||
|
* Get a world by coordinates, attempts to load from mongoDB if not found.
|
||||||
|
*
|
||||||
|
* @param x the x coordinate of the world
|
||||||
|
* @param y the y coordinate of the world
|
||||||
|
* @param createNew if true, a new world is created when a world with given coordinates is not found
|
||||||
|
*
|
||||||
|
* @return World, null if not found and not created.
|
||||||
|
*/
|
||||||
|
public World getWorld(int x, int y, boolean createNew) {
|
||||||
|
|
||||||
|
// Wrapping coordinates around cyclically
|
||||||
|
x %= maxWidth+1;
|
||||||
|
y %= maxWidth+1;
|
||||||
|
|
||||||
|
// Looks for a previously loaded world
|
||||||
|
World world = getLoadedWorld(x,y);
|
||||||
|
if (world != null){
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tries loading the world from the database
|
||||||
|
world = loadWorld(x,y);
|
||||||
|
if (world != null){
|
||||||
|
addWorld(world);
|
||||||
|
LogManager.LOGGER.fine("Loaded world "+(World.idFromCoordinates(x,y))+" from mongodb.");
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
// World does not exist
|
||||||
|
if (createNew) {
|
||||||
|
// Creates a new world
|
||||||
|
world = createWorld(x, y);
|
||||||
|
addWorld(world);
|
||||||
|
LogManager.LOGGER.fine("Created new world "+(World.idFromCoordinates(x,y))+".");
|
||||||
|
return world;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public World getLoadedWorld(int x, int y) {
|
||||||
|
// Wrapping coordinates around cyclically
|
||||||
|
x %= maxWidth+1;
|
||||||
|
y %= maxWidth+1;
|
||||||
|
|
||||||
|
return worlds.get(World.idFromCoordinates(x,y));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new or freshly loaded world to the universe (if not already present).
|
||||||
|
*
|
||||||
|
* @param world the world to be added
|
||||||
|
*/
|
||||||
|
public void addWorld(World world){
|
||||||
|
World w = worlds.get(world.getId());
|
||||||
|
if (w == null){
|
||||||
|
world.setUniverse(this);
|
||||||
|
worlds.put(world.getId(),world);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the world with given coordinates from the universe.
|
||||||
|
*
|
||||||
|
* @param x the x coordinate of the world to be removed
|
||||||
|
* @param y the y coordinate of the world to be removed
|
||||||
|
*/
|
||||||
|
public void removeWorld(int x, int y){
|
||||||
|
World w = worlds.remove(World.idFromCoordinates(x,y));
|
||||||
|
if (w != null){
|
||||||
|
w.setUniverse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the given world from the universe.
|
||||||
|
*
|
||||||
|
* @param world the world to be removed.
|
||||||
|
*/
|
||||||
|
public void removeWorld(World world){
|
||||||
|
World w = worlds.remove(world.getId());
|
||||||
|
if (w != null){
|
||||||
|
w.setUniverse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private World createWorld(int x, int y) {
|
||||||
World world = null;
|
World world = null;
|
||||||
try {
|
try {
|
||||||
world = worldGenerator.generateWorld(x, y);
|
world = worldGenerator.generateWorld(x, y);
|
||||||
|
|
||||||
|
|
||||||
} catch (CancelledException e) {
|
} catch (CancelledException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
public User getUser(String username) {
|
public User getUser(String username) {
|
||||||
|
return users.get(username);
|
||||||
for (User user : users) {
|
|
||||||
if (user.getUsername().equals(username)) {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public User getOrCreateUser(String username, boolean makeControlledUnit) {
|
public User getOrCreateUser(String username, boolean makeControlledUnit) {
|
||||||
@ -110,7 +197,7 @@ public class GameUniverse {
|
|||||||
char[] assembledCode = ar.getWords();
|
char[] assembledCode = ar.getWords();
|
||||||
|
|
||||||
user.getCpu().getMemory().write((char) ar.origin, assembledCode, 0, assembledCode.length);
|
user.getCpu().getMemory().write((char) ar.origin, assembledCode, 0, assembledCode.length);
|
||||||
user.getCpu().setCodeSegmentOffset(ar.getCodeSegmentOffset());
|
user.getCpu().setCodeSectionOffset(ar.getCodeSectionOffset());
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -119,7 +206,7 @@ public class GameUniverse {
|
|||||||
|
|
||||||
user.setUsername(username);
|
user.setUsername(username);
|
||||||
|
|
||||||
users.add(user);
|
addUser(user);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
|
|
||||||
@ -141,12 +228,11 @@ public class GameUniverse {
|
|||||||
*/
|
*/
|
||||||
public GameObject getObject(long id) {
|
public GameObject getObject(long id) {
|
||||||
|
|
||||||
//
|
for (World world : getWorlds()) {
|
||||||
for (World world : worlds) {
|
GameObject obj = world.findObject(id);
|
||||||
for (GameObject object : world.getGameObjects()) {
|
|
||||||
if (object.getObjectId() == id) {
|
if (obj != null) {
|
||||||
return object;
|
return obj;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,12 +245,20 @@ public class GameUniverse {
|
|||||||
time++;
|
time++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<World> getWorlds() {
|
public Collection<World> getWorlds() {
|
||||||
return worlds;
|
return worlds.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<User> getUsers() {
|
public int getWorldCount() {
|
||||||
return users;
|
return worlds.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<User> getUsers() {
|
||||||
|
return users.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserCount() {
|
||||||
|
return users.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getNextObjectId() {
|
public long getNextObjectId() {
|
||||||
@ -187,8 +281,12 @@ public class GameUniverse {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addUser(User user) {
|
||||||
|
users.put(user.getUsername(), user);
|
||||||
|
}
|
||||||
|
|
||||||
public void removeUser(User user) {
|
public void removeUser(User user) {
|
||||||
users.remove(user);
|
users.remove(user.getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxWidth() {
|
public int getMaxWidth() {
|
||||||
|
@ -11,7 +11,9 @@ import net.simon987.server.io.MongoSerialisable;
|
|||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class World implements MongoSerialisable {
|
public class World implements MongoSerialisable {
|
||||||
|
|
||||||
@ -29,7 +31,7 @@ public class World implements MongoSerialisable {
|
|||||||
|
|
||||||
private TileMap tileMap;
|
private TileMap tileMap;
|
||||||
|
|
||||||
private ArrayList<GameObject> gameObjects = new ArrayList<>(16);
|
private ConcurrentHashMap<Long, GameObject> gameObjects = new ConcurrentHashMap<>(8);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this number is greater than 0, the World will be updated.
|
* If this number is greater than 0, the World will be updated.
|
||||||
@ -58,7 +60,28 @@ public class World implements MongoSerialisable {
|
|||||||
public boolean isTileBlocked(int x, int y) {
|
public boolean isTileBlocked(int x, int y) {
|
||||||
|
|
||||||
return getGameObjectsBlockingAt(x, y).size() > 0 || tileMap.getTileAt(x, y) == TileMap.WALL_TILE;
|
return getGameObjectsBlockingAt(x, y).size() > 0 || tileMap.getTileAt(x, y) == TileMap.WALL_TILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the world's unique id from its coordinates.
|
||||||
|
*
|
||||||
|
* @param x the x coordinate of the world
|
||||||
|
* @param y the y coordinate of the world
|
||||||
|
*
|
||||||
|
* @return long
|
||||||
|
*/
|
||||||
|
public static String idFromCoordinates(int x, int y){
|
||||||
|
return "w-"+"0x"+Integer.toHexString(x)+"-"+"0x"+Integer.toHexString(y);
|
||||||
|
//return ((long)x)*(((long)maxWidth)+1)+((long)y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the world's unique id, computed with idFromCoordinates.
|
||||||
|
*
|
||||||
|
* @return long
|
||||||
|
*/
|
||||||
|
public String getId(){
|
||||||
|
return World.idFromCoordinates(x,y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getX() {
|
public int getX() {
|
||||||
@ -69,26 +92,48 @@ public class World implements MongoSerialisable {
|
|||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public ArrayList<GameObject> findObjects(Class clazz) {
|
||||||
* Get all the game objects that are instances of the specified class
|
|
||||||
*/
|
|
||||||
public ArrayList getGameObjects(Class<? extends GameObject> clazz) {
|
|
||||||
|
|
||||||
ArrayList<GameObject> objects = new ArrayList<>(gameObjects.size());
|
ArrayList<GameObject> matchingObjects = new ArrayList<>(2);
|
||||||
|
|
||||||
for (GameObject object : gameObjects) {
|
for (GameObject obj : gameObjects.values()) {
|
||||||
if (object.getClass().equals(clazz)) {
|
|
||||||
objects.add(object);
|
if (obj.getClass().equals(clazz)) {
|
||||||
|
matchingObjects.add(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return objects;
|
return matchingObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<GameObject> getGameObjects() {
|
|
||||||
return gameObjects;
|
public ArrayList<GameObject> findObjects(int mapInfo) {
|
||||||
|
|
||||||
|
ArrayList<GameObject> matchingObjects = new ArrayList<>(2);
|
||||||
|
|
||||||
|
for (GameObject obj : gameObjects.values()) {
|
||||||
|
if ((obj.getMapInfo() & mapInfo) == mapInfo) {
|
||||||
|
matchingObjects.add(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchingObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addObject(GameObject object) {
|
||||||
|
gameObjects.put(object.getObjectId(), object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeObject(GameObject object) {
|
||||||
|
gameObjects.remove(object.getObjectId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameObject findObject(long objectId) {
|
||||||
|
return gameObjects.get(objectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update this World and its GameObjects
|
* Update this World and its GameObjects
|
||||||
* <br>
|
* <br>
|
||||||
@ -100,13 +145,11 @@ public class World implements MongoSerialisable {
|
|||||||
GameEvent event = new WorldUpdateEvent(this);
|
GameEvent event = new WorldUpdateEvent(this);
|
||||||
GameServer.INSTANCE.getEventDispatcher().dispatch(event); //Ignore cancellation
|
GameServer.INSTANCE.getEventDispatcher().dispatch(event); //Ignore cancellation
|
||||||
|
|
||||||
ArrayList<GameObject> gameObjects_ = new ArrayList<>(gameObjects);
|
for (GameObject object : gameObjects.values()) {
|
||||||
|
|
||||||
for (GameObject object : gameObjects_) {
|
|
||||||
//Clean up dead objects
|
//Clean up dead objects
|
||||||
if (object.isDead()) {
|
if (object.isDead()) {
|
||||||
object.onDeadCallback();
|
object.onDeadCallback();
|
||||||
gameObjects.remove(object);
|
removeObject(object);
|
||||||
//LogManager.LOGGER.fine("Removed object " + object + " id: " + object.getObjectId());
|
//LogManager.LOGGER.fine("Removed object " + object + " id: " + object.getObjectId());
|
||||||
} else if (object instanceof Updatable) {
|
} else if (object instanceof Updatable) {
|
||||||
((Updatable) object).update();
|
((Updatable) object).update();
|
||||||
@ -120,11 +163,13 @@ public class World implements MongoSerialisable {
|
|||||||
BasicDBObject dbObject = new BasicDBObject();
|
BasicDBObject dbObject = new BasicDBObject();
|
||||||
|
|
||||||
BasicDBList objects = new BasicDBList();
|
BasicDBList objects = new BasicDBList();
|
||||||
ArrayList<GameObject> gameObjects_ = new ArrayList<>(gameObjects);
|
for (GameObject obj : gameObjects.values()) {
|
||||||
for (GameObject obj : gameObjects_) {
|
|
||||||
objects.add(obj.mongoSerialise());
|
objects.add(obj.mongoSerialise());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
dbObject.put("_id", getId());
|
||||||
|
|
||||||
dbObject.put("objects", objects);
|
dbObject.put("objects", objects);
|
||||||
dbObject.put("terrain", tileMap.mongoSerialise());
|
dbObject.put("terrain", tileMap.mongoSerialise());
|
||||||
|
|
||||||
@ -133,7 +178,7 @@ public class World implements MongoSerialisable {
|
|||||||
dbObject.put("size", worldSize);
|
dbObject.put("size", worldSize);
|
||||||
|
|
||||||
dbObject.put("updatable", updatable);
|
dbObject.put("updatable", updatable);
|
||||||
|
dbObject.put("shouldUpdate",shouldUpdate());
|
||||||
|
|
||||||
return dbObject;
|
return dbObject;
|
||||||
}
|
}
|
||||||
@ -171,7 +216,7 @@ public class World implements MongoSerialisable {
|
|||||||
GameObject object = GameObject.deserialize((DBObject) obj);
|
GameObject object = GameObject.deserialize((DBObject) obj);
|
||||||
|
|
||||||
object.setWorld(world);
|
object.setWorld(world);
|
||||||
world.gameObjects.add(object);
|
world.addObject(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
return world;
|
return world;
|
||||||
@ -209,7 +254,7 @@ public class World implements MongoSerialisable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Objects
|
//Objects
|
||||||
for (GameObject obj : this.gameObjects) {
|
for (GameObject obj : gameObjects.values()) {
|
||||||
mapInfo[obj.getX()][obj.getY()] |= obj.getMapInfo();
|
mapInfo[obj.getX()][obj.getY()] |= obj.getMapInfo();
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -263,17 +308,16 @@ public class World implements MongoSerialisable {
|
|||||||
*/
|
*/
|
||||||
public ArrayList<GameObject> getGameObjectsBlockingAt(int x, int y) {
|
public ArrayList<GameObject> getGameObjectsBlockingAt(int x, int y) {
|
||||||
|
|
||||||
ArrayList<GameObject> gameObjects = new ArrayList<>(2);
|
ArrayList<GameObject> objectsLooking = new ArrayList<>(2);
|
||||||
|
for (GameObject obj : gameObjects.values()) {
|
||||||
for (GameObject obj : this.gameObjects) {
|
|
||||||
|
|
||||||
if (obj.isAt(x, y)) {
|
if (obj.isAt(x, y)) {
|
||||||
gameObjects.add(obj);
|
objectsLooking.add(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return gameObjects;
|
return objectsLooking;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -287,17 +331,15 @@ public class World implements MongoSerialisable {
|
|||||||
* @return the list of game objects at a location
|
* @return the list of game objects at a location
|
||||||
*/
|
*/
|
||||||
public ArrayList<GameObject> getGameObjectsAt(int x, int y) {
|
public ArrayList<GameObject> getGameObjectsAt(int x, int y) {
|
||||||
ArrayList<GameObject> gameObjects = new ArrayList<>(2);
|
ArrayList<GameObject> objectsAt = new ArrayList<>(2);
|
||||||
|
for (GameObject obj : gameObjects.values()) {
|
||||||
|
|
||||||
for (GameObject obj : this.gameObjects) {
|
if (obj.isAt(x, y)) {
|
||||||
|
objectsAt.add(obj);
|
||||||
if (obj.getX() == x && obj.getY() == y) {
|
|
||||||
gameObjects.add(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return objectsAt;
|
||||||
return gameObjects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void incUpdatable() {
|
public void incUpdatable() {
|
||||||
@ -315,4 +357,76 @@ public class World implements MongoSerialisable {
|
|||||||
public int getWorldSize() {
|
public int getWorldSize() {
|
||||||
return worldSize;
|
return worldSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private GameUniverse universe = null;
|
||||||
|
|
||||||
|
public void setUniverse(GameUniverse universe){
|
||||||
|
this.universe = universe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<World> getNeighbouringLoadedWorlds(){
|
||||||
|
ArrayList<World> neighbouringWorlds = new ArrayList<>();
|
||||||
|
|
||||||
|
if (universe == null){
|
||||||
|
return neighbouringWorlds;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int dx=-1; dx<=+1; dx+=2){
|
||||||
|
World nw = universe.getLoadedWorld(x+dx,y);
|
||||||
|
if (nw != null){
|
||||||
|
neighbouringWorlds.add(nw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int dy=-1; dy<=+1; dy+=2){
|
||||||
|
World nw = universe.getLoadedWorld(x,y+dy);
|
||||||
|
if (nw != null){
|
||||||
|
neighbouringWorlds.add(nw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return neighbouringWorlds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<World> getNeighbouringExistingWorlds(){
|
||||||
|
ArrayList<World> neighbouringWorlds = new ArrayList<>();
|
||||||
|
|
||||||
|
if (universe == null){
|
||||||
|
return neighbouringWorlds;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int dx=-1; dx<=+1; dx+=2){
|
||||||
|
World nw = universe.getWorld(x+dx,y,false);
|
||||||
|
if (nw != null){
|
||||||
|
neighbouringWorlds.add(nw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int dy=-1; dy<=+1; dy+=2){
|
||||||
|
World nw = universe.getWorld(x,y+dy,false);
|
||||||
|
if (nw != null){
|
||||||
|
neighbouringWorlds.add(nw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return neighbouringWorlds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean canUnload(){
|
||||||
|
return updatable==0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldUnload(){
|
||||||
|
boolean res = canUnload();
|
||||||
|
|
||||||
|
for (World nw : getNeighbouringLoadedWorlds() ){
|
||||||
|
res &= nw.canUnload();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<GameObject> getGameObjects() {
|
||||||
|
return gameObjects.values();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import java.util.Collections;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to compute paths in the game universe. It supports
|
* Class to compute paths in the game universe. It supports
|
||||||
* paths between within the same World.
|
* paths within the same World.
|
||||||
*/
|
*/
|
||||||
public class Pathfinder {
|
public class Pathfinder {
|
||||||
|
|
||||||
|
@ -1,35 +1,12 @@
|
|||||||
package net.simon987.server.io;
|
package net.simon987.server.io;
|
||||||
|
|
||||||
import net.simon987.server.logging.LogManager;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipOutputStream;
|
|
||||||
|
|
||||||
public class FileUtils {
|
public class FileUtils {
|
||||||
|
|
||||||
private static final int BUFFER_SIZE = 1024;
|
|
||||||
private static final String STR_ENCODING = "UTF-8";
|
|
||||||
private static final String DATE_FORMAT = "yyyyMMddHHmmss";
|
private static final String DATE_FORMAT = "yyyyMMddHHmmss";
|
||||||
private static final String FILE_TYPE = ".zip";
|
|
||||||
private static final Path ROOT_DIR;
|
|
||||||
private static final String DIR_NAME = "history";
|
|
||||||
public static final Path DIR_PATH;
|
|
||||||
|
|
||||||
static {
|
|
||||||
ROOT_DIR = Paths.get(".").normalize();
|
|
||||||
DIR_PATH = ROOT_DIR.resolve(DIR_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Private constructor
|
|
||||||
private FileUtils() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new stamp containing the current date and time
|
* Creates a new stamp containing the current date and time
|
||||||
@ -42,143 +19,4 @@ public class FileUtils {
|
|||||||
return f.format(millisToDate);
|
return f.format(millisToDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Created a directory if none exists with the specified name
|
|
||||||
*
|
|
||||||
* @param directory folder to create
|
|
||||||
* @return true is the file exists or create operation is successful
|
|
||||||
*/
|
|
||||||
public static boolean prepDirectory(Path directory) {
|
|
||||||
File file = directory.toFile();
|
|
||||||
|
|
||||||
//If the directory exists or the directory created successfully return true
|
|
||||||
if (file.exists() || file.mkdir()) {
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
System.out.println("Error creating directory: " + file.toString());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a file into an array of bytes
|
|
||||||
*
|
|
||||||
* @param path the file to be converted into bytes
|
|
||||||
* @return the byte array of the given file
|
|
||||||
*/
|
|
||||||
public static byte[] bytifyFile(Path path) {
|
|
||||||
byte[] bytes = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
bytes = Files.readAllBytes(path);
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("Failed to extract bytes from: " + path);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes in a file that had been converted to a byte[] to be written to a new
|
|
||||||
* zip file
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* contains data in byte array form to be written, typically a file
|
|
||||||
* that has been converted with bytifyFile()
|
|
||||||
* @throws IOException
|
|
||||||
* if an error occurs during the write process
|
|
||||||
*/
|
|
||||||
public static void writeSaveToZip(String name, byte[] data) throws IOException {
|
|
||||||
|
|
||||||
String newFile = DIR_PATH.resolve(getDateTimeStamp() + FILE_TYPE).toString();
|
|
||||||
FileOutputStream output = new FileOutputStream(newFile);
|
|
||||||
ZipOutputStream stream = new ZipOutputStream(output);
|
|
||||||
byte[] buffer = new byte[BUFFER_SIZE];
|
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
|
|
||||||
|
|
||||||
while ((bais.read(buffer)) > -1) {
|
|
||||||
// File name
|
|
||||||
ZipEntry entry = new ZipEntry(name);
|
|
||||||
// Set to start of next entry in the stream.
|
|
||||||
stream.putNextEntry(entry);
|
|
||||||
// Data to write.
|
|
||||||
stream.write(data);
|
|
||||||
// Close the current entry.
|
|
||||||
stream.closeEntry();
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.close();
|
|
||||||
output.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void cleanHistory(int size) {
|
|
||||||
|
|
||||||
|
|
||||||
File[] files = new File(DIR_PATH.toString()).listFiles();
|
|
||||||
File[] sorted = new File[size];
|
|
||||||
|
|
||||||
File currentFile;
|
|
||||||
boolean changed;
|
|
||||||
|
|
||||||
if (files != null) {
|
|
||||||
for (int i = 0; i < files.length / 2; i++) {
|
|
||||||
currentFile = files[i];
|
|
||||||
files[i] = files[files.length - i - 1];
|
|
||||||
files[files.length - i - 1] = currentFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int f = 0; f < files.length; f++) {
|
|
||||||
changed = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
long dirFile = Long.parseLong(files[f].getName().substring(0, (files[f].getName().length() - 4)));
|
|
||||||
|
|
||||||
if (f < size && sorted[f] == null) {
|
|
||||||
sorted[f] = files[f];
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
for (int s = 0; s < sorted.length; s++) {
|
|
||||||
|
|
||||||
long sortedFile = Long.parseLong(sorted[s].getName().substring(0, (sorted[s].getName().length() - 4)));
|
|
||||||
|
|
||||||
if (dirFile > sortedFile) {
|
|
||||||
|
|
||||||
if (s == sorted.length - 1) {
|
|
||||||
sorted[s] = files[f];
|
|
||||||
|
|
||||||
} else {
|
|
||||||
sorted[s] = files[f];
|
|
||||||
}
|
|
||||||
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!changed) {
|
|
||||||
files[f].delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
LogManager.LOGGER.info("Non-save file in history directory: " + files[f].getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a byte array into human readable format using the provided encoding
|
|
||||||
*
|
|
||||||
* @param bytes data to be encoded to String
|
|
||||||
* @return a String containing the encoded bytes
|
|
||||||
*/
|
|
||||||
public static String byteArrAsString(byte[] bytes) throws UnsupportedEncodingException {
|
|
||||||
return new String(bytes, STR_ENCODING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,30 @@ public class LogManager {
|
|||||||
public static void initialize() {
|
public static void initialize() {
|
||||||
LOGGER.setUseParentHandlers(false);
|
LOGGER.setUseParentHandlers(false);
|
||||||
|
|
||||||
Handler handler = new ConsoleHandler();
|
/*
|
||||||
|
* Having warning/error directed to stderr
|
||||||
|
*/
|
||||||
|
Handler errHandler = new ConsoleHandler();
|
||||||
|
errHandler.setFormatter(new GenericFormatter());
|
||||||
|
errHandler.setLevel(Level.WARNING);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only have info and below directed to stdout
|
||||||
|
*/
|
||||||
|
Handler handler = new StreamHandler(System.out, new GenericFormatter()) {
|
||||||
|
@Override
|
||||||
|
public synchronized void publish(LogRecord record) {
|
||||||
|
super.publish(record);
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
handler.setFilter(new Filter() {
|
||||||
|
@Override
|
||||||
|
public boolean isLoggable(LogRecord record) {
|
||||||
|
return record.getLevel().intValue() <= Level.INFO.intValue();
|
||||||
|
}
|
||||||
|
});
|
||||||
handler.setLevel(Level.ALL);
|
handler.setLevel(Level.ALL);
|
||||||
handler.setFormatter(new GenericFormatter());
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Handler fileHandler = new FileHandler("mar.log");
|
Handler fileHandler = new FileHandler("mar.log");
|
||||||
@ -29,6 +50,7 @@ public class LogManager {
|
|||||||
fileHandler.setFormatter(new GenericFormatter());
|
fileHandler.setFormatter(new GenericFormatter());
|
||||||
|
|
||||||
LOGGER.addHandler(handler);
|
LOGGER.addHandler(handler);
|
||||||
|
LOGGER.addHandler(errHandler);
|
||||||
LOGGER.addHandler(fileHandler);
|
LOGGER.addHandler(fileHandler);
|
||||||
LOGGER.setLevel(Level.ALL);
|
LOGGER.setLevel(Level.ALL);
|
||||||
|
|
||||||
@ -36,6 +58,5 @@ public class LogManager {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ public class User implements MongoSerialisable {
|
|||||||
|
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
BasicDBObject dbObject = new BasicDBObject();
|
||||||
|
|
||||||
|
dbObject.put("_id", username); // a constant id ensures only one entry per user is kept and updated, instead of a new entry created every save for every user.
|
||||||
dbObject.put("username", username);
|
dbObject.put("username", username);
|
||||||
dbObject.put("code", userCode);
|
dbObject.put("code", userCode);
|
||||||
dbObject.put("controlledUnit", controlledUnit.getObjectId());
|
dbObject.put("controlledUnit", controlledUnit.getObjectId());
|
||||||
|
@ -21,30 +21,35 @@ public class CodeUploadHandler implements MessageHandler {
|
|||||||
//TODO Should we wait at the end of the tick to modify the CPU ?
|
//TODO Should we wait at the end of the tick to modify the CPU ?
|
||||||
user.getUser().setUserCode((String) json.get("code"));
|
user.getUser().setUserCode((String) json.get("code"));
|
||||||
|
|
||||||
AssemblyResult ar = new Assembler(user.getUser().getCpu().getInstructionSet(),
|
if (user.getUser().getUserCode() != null) {
|
||||||
user.getUser().getCpu().getRegisterSet(),
|
AssemblyResult ar = new Assembler(user.getUser().getCpu().getInstructionSet(),
|
||||||
GameServer.INSTANCE.getConfig()).parse(user.getUser().getUserCode());
|
user.getUser().getCpu().getRegisterSet(),
|
||||||
|
GameServer.INSTANCE.getConfig()).parse(user.getUser().getUserCode());
|
||||||
|
|
||||||
user.getUser().getCpu().getMemory().clear();
|
user.getUser().getCpu().getMemory().clear();
|
||||||
|
|
||||||
//Write assembled code to mem
|
//Write assembled code to mem
|
||||||
char[] assembledCode = ar.getWords();
|
char[] assembledCode = ar.getWords();
|
||||||
|
|
||||||
user.getUser().getCpu().getMemory().write((char) ar.origin, assembledCode, 0, assembledCode.length);
|
user.getUser().getCpu().getMemory().write((char) ar.origin, assembledCode, 0, assembledCode.length);
|
||||||
user.getUser().getCpu().setCodeSegmentOffset(ar.getCodeSegmentOffset());
|
user.getUser().getCpu().setCodeSectionOffset(ar.getCodeSectionOffset());
|
||||||
|
|
||||||
//Clear keyboard buffer
|
//Clear keyboard buffer
|
||||||
if (user.getUser().getControlledUnit() != null &&
|
if (user.getUser().getControlledUnit() != null &&
|
||||||
user.getUser().getControlledUnit().getKeyboardBuffer() != null) {
|
user.getUser().getControlledUnit().getKeyboardBuffer() != null) {
|
||||||
user.getUser().getControlledUnit().getKeyboardBuffer().clear();
|
user.getUser().getControlledUnit().getKeyboardBuffer().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Clear registers
|
||||||
|
user.getUser().getCpu().getRegisterSet().clear();
|
||||||
|
|
||||||
|
JSONObject response = new JSONObject();
|
||||||
|
response.put("t", "codeResponse");
|
||||||
|
response.put("bytes", ar.bytes.length);
|
||||||
|
response.put("exceptions", ar.exceptions.size());
|
||||||
|
|
||||||
|
user.getWebSocket().send(response.toJSONString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JSONObject response = new JSONObject();
|
|
||||||
response.put("t", "codeResponse");
|
|
||||||
response.put("bytes", ar.bytes.length);
|
|
||||||
|
|
||||||
user.getWebSocket().send(response.toJSONString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package net.simon987.server.webserver;
|
|||||||
|
|
||||||
|
|
||||||
import net.simon987.server.logging.LogManager;
|
import net.simon987.server.logging.LogManager;
|
||||||
|
import org.java_websocket.exceptions.WebsocketNotConnectedException;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
import org.json.simple.parser.JSONParser;
|
import org.json.simple.parser.JSONParser;
|
||||||
import org.json.simple.parser.ParseException;
|
import org.json.simple.parser.ParseException;
|
||||||
@ -28,9 +29,16 @@ public class MessageEventDispatcher {
|
|||||||
try {
|
try {
|
||||||
JSONObject json = (JSONObject) parser.parse(message);
|
JSONObject json = (JSONObject) parser.parse(message);
|
||||||
|
|
||||||
if (json.containsKey("t")) {
|
if (json.containsKey("t") && user.getWebSocket().isOpen()) {
|
||||||
for (MessageHandler handler : handlers) {
|
for (MessageHandler handler : handlers) {
|
||||||
handler.handle(user, json);
|
try {
|
||||||
|
handler.handle(user, json);
|
||||||
|
} catch (WebsocketNotConnectedException e) {
|
||||||
|
LogManager.LOGGER.fine("Catched WebsocketNotConnectedException");
|
||||||
|
} catch (Exception e1) {
|
||||||
|
LogManager.LOGGER.severe(e1.getMessage());
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LogManager.LOGGER.severe("Malformed JSON sent by " + user.getUser().getUsername());
|
LogManager.LOGGER.severe("Malformed JSON sent by " + user.getUser().getUsername());
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package net.simon987.server.webserver;
|
package net.simon987.server.webserver;
|
||||||
|
|
||||||
|
import org.java_websocket.exceptions.WebsocketNotConnectedException;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
public interface MessageHandler {
|
public interface MessageHandler {
|
||||||
|
|
||||||
void handle(OnlineUser user, JSONObject json);
|
void handle(OnlineUser user, JSONObject json) throws WebsocketNotConnectedException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,6 @@ import net.simon987.server.logging.LogManager;
|
|||||||
import org.json.simple.JSONArray;
|
import org.json.simple.JSONArray;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class ObjectsRequestHandler implements MessageHandler {
|
public class ObjectsRequestHandler implements MessageHandler {
|
||||||
|
|
||||||
|
|
||||||
@ -29,13 +27,12 @@ public class ObjectsRequestHandler implements MessageHandler {
|
|||||||
World world = GameServer.INSTANCE.getGameUniverse().getWorld(x, y, false);
|
World world = GameServer.INSTANCE.getGameUniverse().getWorld(x, y, false);
|
||||||
|
|
||||||
if (world != null) {
|
if (world != null) {
|
||||||
ArrayList<GameObject> gameObjects = world.getGameObjects();
|
|
||||||
|
|
||||||
JSONObject response = new JSONObject();
|
JSONObject response = new JSONObject();
|
||||||
JSONArray objects = new JSONArray();
|
JSONArray objects = new JSONArray();
|
||||||
|
|
||||||
|
|
||||||
for (GameObject object : gameObjects) {
|
for (GameObject object : world.getGameObjects()) {
|
||||||
objects.add(object.serialise());
|
objects.add(object.serialise());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import net.simon987.server.assembly.exception.CancelledException;
|
|||||||
import net.simon987.server.user.User;
|
import net.simon987.server.user.User;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class CPUTest {
|
public class CPUTest {
|
||||||
@ -13,7 +12,7 @@ public class CPUTest {
|
|||||||
@Test
|
@Test
|
||||||
public void executeInstruction() throws CancelledException {
|
public void executeInstruction() throws CancelledException {
|
||||||
|
|
||||||
ServerConfiguration config = new ServerConfiguration(new File("config.properties"));
|
ServerConfiguration config = new ServerConfiguration("config.properties");
|
||||||
User user = new User();
|
User user = new User();
|
||||||
CPU cpu = new CPU(config, user);
|
CPU cpu = new CPU(config, user);
|
||||||
|
|
@ -3,15 +3,13 @@ package net.simon987.server.assembly;
|
|||||||
import net.simon987.server.ServerConfiguration;
|
import net.simon987.server.ServerConfiguration;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
|
||||||
public class MemoryTest {
|
public class MemoryTest {
|
||||||
@Test
|
@Test
|
||||||
public void getSet() {
|
public void getSet() {
|
||||||
ServerConfiguration config = new ServerConfiguration(new File("config.properties"));
|
ServerConfiguration config = new ServerConfiguration("config.properties");
|
||||||
int memorySize = config.getInt("memory_size");
|
int memorySize = config.getInt("memory_size");
|
||||||
Memory memory = new Memory(memorySize);
|
Memory memory = new Memory(memorySize);
|
||||||
|
|
||||||
@ -31,7 +29,7 @@ public class MemoryTest {
|
|||||||
@Test
|
@Test
|
||||||
public void write() {
|
public void write() {
|
||||||
|
|
||||||
ServerConfiguration config = new ServerConfiguration(new File("config.properties"));
|
ServerConfiguration config = new ServerConfiguration("config.properties");
|
||||||
int memorySize = config.getInt("memory_size");
|
int memorySize = config.getInt("memory_size");
|
||||||
Memory memory = new Memory(memorySize);
|
Memory memory = new Memory(memorySize);
|
||||||
|
|
@ -7,8 +7,6 @@ import net.simon987.server.assembly.RegisterSet;
|
|||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
|
||||||
@ -20,7 +18,7 @@ public class AddInstructionTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void addTargetTarget() {
|
public void addTargetTarget() {
|
||||||
ServerConfiguration config = new ServerConfiguration(new File("config.properties"));
|
ServerConfiguration config = new ServerConfiguration("config.properties");
|
||||||
int memorySize = config.getInt("memory_size");
|
int memorySize = config.getInt("memory_size");
|
||||||
|
|
||||||
//Memory
|
//Memory
|
||||||
@ -131,7 +129,7 @@ public class AddInstructionTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void addTargetImm() {
|
public void addTargetImm() {
|
||||||
ServerConfiguration config = new ServerConfiguration(new File("config.properties"));
|
ServerConfiguration config = new ServerConfiguration("config.properties");
|
||||||
int memorySize = config.getInt("memory_size");
|
int memorySize = config.getInt("memory_size");
|
||||||
|
|
||||||
//Memory
|
//Memory
|
@ -5,8 +5,6 @@ import net.simon987.server.assembly.Memory;
|
|||||||
import net.simon987.server.assembly.Status;
|
import net.simon987.server.assembly.Status;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
|
||||||
@ -14,7 +12,7 @@ public class AndInstructionTest {
|
|||||||
@Test
|
@Test
|
||||||
public void executeTargetTarget() {
|
public void executeTargetTarget() {
|
||||||
|
|
||||||
ServerConfiguration config = new ServerConfiguration(new File("config.properties"));
|
ServerConfiguration config = new ServerConfiguration("config.properties");
|
||||||
int memorySize = config.getInt("memory_size");
|
int memorySize = config.getInt("memory_size");
|
||||||
|
|
||||||
//Memory
|
//Memory
|
||||||
@ -56,7 +54,7 @@ public class AndInstructionTest {
|
|||||||
@Test
|
@Test
|
||||||
public void executeTargetImm() {
|
public void executeTargetImm() {
|
||||||
|
|
||||||
ServerConfiguration config = new ServerConfiguration(new File("config.properties"));
|
ServerConfiguration config = new ServerConfiguration("config.properties");
|
||||||
int memorySize = config.getInt("memory_size");
|
int memorySize = config.getInt("memory_size");
|
||||||
|
|
||||||
//Memory
|
//Memory
|
@ -5,15 +5,13 @@ import net.simon987.server.assembly.*;
|
|||||||
import net.simon987.server.user.User;
|
import net.simon987.server.user.User;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
public class CallInstructionTest {
|
public class CallInstructionTest {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void execute() throws Exception {
|
public void execute() throws Exception {
|
||||||
|
|
||||||
ServerConfiguration config = new ServerConfiguration(new File("config.properties"));
|
ServerConfiguration config = new ServerConfiguration("config.properties");
|
||||||
int memorySize = config.getInt("memory_size");
|
int memorySize = config.getInt("memory_size");
|
||||||
|
|
||||||
//Memory
|
//Memory
|
Loading…
x
Reference in New Issue
Block a user