Objects can enter & leave vaults

This commit is contained in:
simon 2018-03-04 14:56:02 -05:00
parent 0ada6c29d4
commit f35e6c5a9a
12 changed files with 301 additions and 30 deletions

View File

@ -50,6 +50,8 @@ public class NpcPlugin extends ServerPlugin implements GameObjectDeserializer, C
return Obstacle.deserialize(obj);
} else if (objType == ElectricBox.ID) {
return ElectricBox.deserialize(obj);
} else if (objType == Portal.ID) {
return Portal.deserialize(obj);
}
return null;

View File

@ -0,0 +1,93 @@
package net.simon987.npcplugin;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import net.simon987.server.GameServer;
import net.simon987.server.game.*;
import org.json.simple.JSONObject;
public class Portal extends GameObject implements Enterable {
private Location dst;
public static final int MAP_INFO = 0x0020;
public static final int ID = 8;
@Override
public boolean enter(GameObject object) {
World world = GameServer.INSTANCE.getGameUniverse().getWorld(dst.worldX, dst.worldY, false, dst.dimension);
if (object instanceof Updatable) {
object.getWorld().decUpdatable();
world.incUpdatable();
}
object.getWorld().removeObject(object);
object.setWorld(world);
world.addObject(object);
object.setX(dst.x);
object.setY(dst.y);
return true;
}
@Override
public char getMapInfo() {
return MAP_INFO;
}
@Override
public BasicDBObject mongoSerialise() {
BasicDBObject dbObject = new BasicDBObject();
dbObject.put("i", getObjectId());
dbObject.put("x", getX());
dbObject.put("y", getY());
dbObject.put("t", ID);
dbObject.put("dstWorldX", dst.worldX);
dbObject.put("dstWorldY", dst.worldY);
dbObject.put("dstX", dst.x);
dbObject.put("dstY", dst.y);
dbObject.put("dstDimension", dst.dimension);
return dbObject;
}
public static Portal deserialize(DBObject obj) {
Portal portal = new Portal();
portal.dst = new Location(
(int) obj.get("dstWorldX"),
(int) obj.get("dstWorldY"),
(String) obj.get("dstDimension"),
(int) obj.get("dstX"),
(int) obj.get("dstY"));
portal.setX((int) obj.get("x"));
portal.setY((int) obj.get("y"));
return portal;
}
@Override
public JSONObject serialise() {
JSONObject json = new JSONObject();
json.put("i", getObjectId());
json.put("x", getX());
json.put("y", getY());
json.put("t", ID);
return json;
}
public Location getDst() {
return dst;
}
public void setDst(Location dst) {
this.dst = dst;
}
}

View File

@ -2,7 +2,10 @@ package net.simon987.npcplugin;
import net.simon987.server.GameServer;
import net.simon987.server.game.Direction;
import net.simon987.server.game.Location;
import net.simon987.server.game.TileMap;
import net.simon987.server.game.World;
import net.simon987.server.logging.LogManager;
import java.awt.*;
import java.util.ArrayList;
@ -19,9 +22,12 @@ public class VaultDimension {
private World homeWorld;
public VaultDimension(long vaultDoorId) {
private int homeX;
private int homeY;
name = "v" + vaultDoorId + "-";
public VaultDimension(VaultDoor vaultDoor) {
name = "v" + vaultDoor.getObjectId() + "-";
/*
* Creates a group of vault worlds and pieces them together with openings.
@ -35,6 +41,7 @@ public class VaultDimension {
* 2. For each world in the current layer, attach a random number of new worlds
* 3. Repeat the same step for the newly added layer
* 4. Choose a random world from the last layer and create the vault box there (objective)
* 5. Create an exit portal in the home world
*
* This process is actually done in 2 passes, in the first pass, worlds are defined
* as a set of coordinates + a list of opening directions, then they are actually generated
@ -125,6 +132,31 @@ public class VaultDimension {
//4. Choose a random world from the last layer and create the vault box there (objective)
World objectiveWorld = lastLayerWorlds.get(random.nextInt(lastLayerWorlds.size()));
//5. Create an exit portal in the home World
Point homePortalPt = homeWorld.getRandomTileWithAdjacent(8, TileMap.VAULT_FLOOR);
if (homePortalPt != null) {
Point exitCoords = vaultDoor.getAdjacentTile();
Location exitLocation = new Location(vaultDoor.getWorld().getX(), vaultDoor.getWorld().getY(), vaultDoor
.getWorld().getDimension(), exitCoords.x, exitCoords.y);
Portal homePortal = new Portal();
homePortal.setDst(exitLocation);
homePortal.setX(homePortalPt.x);
homePortal.setY(homePortalPt.y);
homePortal.setWorld(homeWorld);
homeWorld.addObject(homePortal);
Point entryCoords = homePortal.getAdjacentTile();
homeX = entryCoords.x;
homeY = entryCoords.y;
} else {
LogManager.LOGGER.severe("FIXME: Couldn't create home exit portal for world " + homeWorld.getId());
}
LogManager.LOGGER.severe("DONE");
}
private boolean worldExists(Point coords, HashMap<Integer, ArrayList<WorldBluePrint>> worldLayers) {
@ -137,6 +169,13 @@ public class VaultDimension {
return homeWorld;
}
public int getHomeX() {
return homeX;
}
public int getHomeY() {
return homeY;
}
/**
* Helper class to plan the layout of a vault dimension
*/

View File

@ -28,8 +28,11 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up
*/
private boolean open = false;
private int homeX;
private int homeY;
private World homeWorld;
/**
* Number of ticks to remain the door open
*/
@ -38,26 +41,12 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up
private int openedTimer = 0;
private int cypherId;
public VaultDoor(int cypherId, long objectId) {
public VaultDoor(int cypherId) {
this.cypherId = cypherId;
this.randomStringGenerator = new RandomStringGenerator();
setObjectId(objectId);
this.password = "12345678".toCharArray();
//Get or generate vault world
World world = GameServer.INSTANCE.getGameUniverse().getWorld(0x7FFF, 0x7FFF,
false, "v" + getObjectId() + "-");
if (world != null) {
homeWorld = world;
} else {
VaultDimension vaultDimension = new VaultDimension(getObjectId());
homeWorld = vaultDimension.getHomeWorld();
}
}
@ -119,7 +108,8 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up
homeWorld.incUpdatable();
homeWorld.addObject(object);
object.setWorld(homeWorld);
object.setX(homeX);
object.setY(homeY);
return true;
} else {
@ -140,6 +130,8 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up
dbObject.put("i", getObjectId());
dbObject.put("x", getX());
dbObject.put("y", getY());
dbObject.put("homeX", getHomeX());
dbObject.put("homeY", getHomeY());
dbObject.put("t", ID);
dbObject.put("pw", new String(password));
@ -162,12 +154,48 @@ public class VaultDoor extends GameObject implements Programmable, Enterable, Up
public static VaultDoor deserialize(DBObject obj) {
VaultDoor vaultDoor = new VaultDoor(0, (long) obj.get("i")); //cypherId ?
VaultDoor vaultDoor = new VaultDoor(0); //cypherId ?
vaultDoor.setX((int) obj.get("x"));
vaultDoor.setY((int) obj.get("y"));
if (obj.containsField("homeX") && obj.containsField("homeY")) {
vaultDoor.setHomeX((int) obj.get("homeX"));
vaultDoor.setHomeY((int) obj.get("homeY"));
}
vaultDoor.password = ((String) obj.get("pw")).toCharArray();
return vaultDoor;
}
@Override
public void initialize() {
//Get or generate vault world
homeWorld = GameServer.INSTANCE.getGameUniverse().getWorld(0x7FFF, 0x7FFF,
false, "v" + getObjectId() + "-");
if (homeWorld == null) {
VaultDimension vaultDimension = new VaultDimension(this);
homeWorld = vaultDimension.getHomeWorld();
homeX = vaultDimension.getHomeX();
homeY = vaultDimension.getHomeY();
}
}
public int getHomeX() {
return homeX;
}
public void setHomeX(int homeX) {
this.homeX = homeX;
}
public int getHomeY() {
return homeY;
}
public void setHomeY(int homeY) {
this.homeY = homeY;
}
}

View File

@ -230,7 +230,7 @@ public class VaultWorldGenerator {
for (int y = 0; y < worldSize; y++) {
if (map.getTileAt(x, y) != floorTile && map.getTileAt(x, y) != wallTile) {
map.setTileAt(-1, x, y);
map.setTileAt(TileMap.VOID, x, y);
}
}
}

View File

@ -99,13 +99,9 @@ public class WorldCreationListener implements GameEventListener {
p = world.getRandomPassableTile();
if (p != null) {
VaultDoor vaultDoor = new VaultDoor(0, GameServer.INSTANCE.getGameUniverse().getNextObjectId()); //todo cypherId ?
VaultDoor vaultDoor = new VaultDoor(0); //todo cypherId ?
vaultDoor.setWorld(world);
vaultDoor.setX(p.x);
vaultDoor.setY(p.y);
int counter = 300;
int counter = 700;
while (p.x == 0 || p.x == world.getWorldSize() - 1 || p.y == world.getWorldSize() - 1 || p.y == 0
|| vaultDoor.getAdjacentTileCount(true) < 8) {
p = world.getRandomPassableTile();
@ -128,6 +124,9 @@ public class WorldCreationListener implements GameEventListener {
world.addObject(vaultDoor);
world.incUpdatable(); //In case the Factory & Radio Tower couldn't be spawned.
vaultDoor.setWorld(world);
vaultDoor.initialize();
LogManager.LOGGER.info("Spawned Vault Door at (" + world.getX() + ", " + world.getY() +
") (" + p.x + ", " + p.y + ")");

View File

@ -5,7 +5,7 @@ package net.simon987.server.event;
*/
public class ObjectDeathEvent extends GameEvent {
/**
* The GameObject type ID of object that init this event
* The GameObject type ID of object that initialize this event
*/
private long sourceObjectId;

View File

@ -259,4 +259,8 @@ public abstract class GameObject implements JSONSerialisable, MongoSerialisable
public boolean onDeadCallback() {
return false;
}
public void initialize() {
}
}

View File

@ -0,0 +1,28 @@
package net.simon987.server.game;
/**
* Represents a location in the game universe
*/
public class Location {
public int worldX;
public int worldY;
public String dimension;
public int x;
public int y;
public Location(int worldX, int worldY, String dimension, int x, int y) {
this.worldX = worldX;
this.worldY = worldY;
this.dimension = dimension;
this.x = x;
this.y = y;
}
public String getWorldId() {
return World.idFromCoordinates(worldX, worldY, dimension);
}
}

View File

@ -21,6 +21,7 @@ import java.util.zip.DeflaterOutputStream;
*/
public class TileMap implements JSONSerialisable, MongoSerialisable {
public static final int VOID = -1;
public static final int PLAIN_TILE = 0;
public static final int WALL_TILE = 1;
public static final int IRON_TILE = 2;
@ -186,6 +187,5 @@ public class TileMap implements JSONSerialisable, MongoSerialisable {
return new Point(rx, ry);
}
}
}
}

View File

@ -69,7 +69,7 @@ public class World implements MongoSerialisable {
int tile = tileMap.getTileAt(x, y);
return getGameObjectsBlockingAt(x, y).size() > 0 || tile == TileMap.WALL_TILE ||
tile == TileMap.VAULT_WALL;
tile == TileMap.VAULT_WALL || tile == TileMap.VOID;
}
/**
@ -229,6 +229,8 @@ public class World implements MongoSerialisable {
object.setWorld(world);
world.addObject(object);
object.initialize();
}
return world;
@ -439,7 +441,80 @@ public class World implements MongoSerialisable {
return res;
}
public Point getAdjacentTile(int x, int y) {
if (!isTileBlocked(x + 1, y)) {
return new Point(x + 1, y);
} else if (!isTileBlocked(x, y + 1)) {
return new Point(x, getY() + 1);
} else if (!isTileBlocked(x - 1, y)) {
return new Point(x - 1, getY());
} else if (!isTileBlocked(x, y - 1)) {
return new Point(x, y - 1);
} else {
return null;
}
}
public Collection<GameObject> getGameObjects() {
return gameObjects.values();
}
/**
* Get a random tile with N adjacent non-blocked tile
*
* @param n Number of adjacent tiles of type X
* @return null if no tile is found
*/
public Point getRandomTileWithAdjacent(int n, int tile) {
int counter = 0;
while (true) {
counter++;
//Prevent infinite loop
if (counter >= 2500) {
return null;
}
Point rTile = getTileMap().getRandomTile(tile);
if (rTile != null) {
int adjacentTiles = 0;
if (!isTileBlocked(rTile.x, rTile.y - 1)) {
adjacentTiles++;
}
if (!isTileBlocked(rTile.x + 1, rTile.y)) {
adjacentTiles++;
}
if (!isTileBlocked(rTile.x, rTile.y + 1)) {
adjacentTiles++;
}
if (!isTileBlocked(rTile.x - 1, rTile.y)) {
adjacentTiles++;
}
if (!isTileBlocked(rTile.x + 1, rTile.y + 1)) {
adjacentTiles++;
}
if (!isTileBlocked(rTile.x - 1, rTile.y + 1)) {
adjacentTiles++;
}
if (!isTileBlocked(rTile.x + 1, rTile.y - 1)) {
adjacentTiles++;
}
if (!isTileBlocked(rTile.x - 1, rTile.y - 1)) {
adjacentTiles++;
}
if (adjacentTiles >= n) {
return rTile;
}
}
}
}
}

View File

@ -156,6 +156,9 @@ public class DebugHandler implements MessageHandler {
if (object != null) {
world.addObject(object);
object.setWorld(world);
object.initialize();
return "Created object " + object.getObjectId();