mirror of
https://github.com/simon987/Much-Assembly-Required.git
synced 2025-04-10 14:26:45 +00:00
Objects can enter & leave vaults
This commit is contained in:
parent
0ada6c29d4
commit
f35e6c5a9a
@ -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;
|
||||
|
93
Plugin NPC/src/main/java/net/simon987/npcplugin/Portal.java
Normal file
93
Plugin NPC/src/main/java/net/simon987/npcplugin/Portal.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 + ")");
|
||||
|
@ -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;
|
||||
|
||||
|
@ -259,4 +259,8 @@ public abstract class GameObject implements JSONSerialisable, MongoSerialisable
|
||||
public boolean onDeadCallback() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
|
||||
}
|
||||
}
|
28
Server/src/main/java/net/simon987/server/game/Location.java
Normal file
28
Server/src/main/java/net/simon987/server/game/Location.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user