mirror of
https://github.com/simon987/Much-Assembly-Required.git
synced 2025-04-19 18:46:43 +00:00
Basic world generation for entire Vault dimension
This commit is contained in:
parent
817dbcc6c4
commit
f530dafdee
@ -4,7 +4,11 @@ import net.simon987.server.GameServer;
|
|||||||
import net.simon987.server.game.Direction;
|
import net.simon987.server.game.Direction;
|
||||||
import net.simon987.server.game.World;
|
import net.simon987.server.game.World;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
public class VaultDimension {
|
public class VaultDimension {
|
||||||
|
|
||||||
@ -17,18 +21,153 @@ public class VaultDimension {
|
|||||||
|
|
||||||
name = "v" + vaultDoorId + "-";
|
name = "v" + vaultDoorId + "-";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a group of vault worlds and pieces them together with openings.
|
||||||
|
* For a set number of passes, a random number of vault worlds are added to each world in the
|
||||||
|
* previous 'layer' of worlds in a random direction. Openings are added to allow movement from a
|
||||||
|
* layer to the next, meaning that adjacent worlds are not necessarily connected, and one would
|
||||||
|
* necessarily need to travel through 5 openings to reach the 6th layer, even when that layer is
|
||||||
|
* less than 5 worlds away from the origin/home vault world (the one containing the exit door).
|
||||||
|
*
|
||||||
|
* 1. Create home world (layer 0)
|
||||||
|
* 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)
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
int minLayerCount = 4;
|
||||||
|
int maxLayerCount = 6;
|
||||||
|
int minAttachedWorld = 0;
|
||||||
|
int maxAttachedWorld = 4; //todo cap at 4 to avoid infinite loop
|
||||||
|
|
||||||
|
HashMap<Integer, ArrayList<WorldBluePrint>> worldLayers = new HashMap<>();
|
||||||
VaultWorldGenerator generator = new VaultWorldGenerator();
|
VaultWorldGenerator generator = new VaultWorldGenerator();
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
int layerCount = random.nextInt(maxLayerCount - minLayerCount) + minLayerCount;
|
||||||
|
|
||||||
ArrayList<Direction> openings = new ArrayList<>();
|
//1. Create home world
|
||||||
openings.add(Direction.WEST);
|
WorldBluePrint homeWorld = new WorldBluePrint();
|
||||||
openings.add(Direction.SOUTH);
|
homeWorld.coords.x = 0x7FFF;
|
||||||
openings.add(Direction.EAST);
|
homeWorld.coords.y = 0x7FFF;
|
||||||
openings.add(Direction.NORTH);
|
worldLayers.put(0, new ArrayList<>());
|
||||||
|
worldLayers.get(0).add(homeWorld);
|
||||||
|
|
||||||
World vWorld = generator.generateVaultWorld(0x7FFF, 0x7FFF, openings, name);
|
//2. For each world in the current layer, attach a random number of new worlds
|
||||||
|
for (int i = 1; i <= layerCount; i++) {
|
||||||
|
|
||||||
|
worldLayers.put(i, new ArrayList<>());
|
||||||
|
|
||||||
|
for (WorldBluePrint world : worldLayers.get(i - 1)) {
|
||||||
|
|
||||||
|
int attachedWorlds;
|
||||||
|
if (i == 1) {
|
||||||
|
attachedWorlds = 4; // The home world should have 4 attached worlds
|
||||||
|
} else {
|
||||||
|
attachedWorlds = random.nextInt(maxAttachedWorld - minAttachedWorld) + minAttachedWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < attachedWorlds; j++) {
|
||||||
|
|
||||||
|
int rDirIndex = random.nextInt(4);
|
||||||
|
|
||||||
|
//Try 4 directions (wrap around 0..3)
|
||||||
|
for (int attemptCount = 0; attemptCount < 4; attemptCount++) {
|
||||||
|
Direction rDir = Direction.getDirection(rDirIndex);
|
||||||
|
|
||||||
|
//Don't attach a world at the same spot twice
|
||||||
|
if (!worldExists(world.coordinatesOf(rDir), worldLayers)) {
|
||||||
|
WorldBluePrint attachedWorld = world.attachWorld(rDir);
|
||||||
|
worldLayers.get(i).add(attachedWorld);
|
||||||
|
}
|
||||||
|
rDirIndex = (rDirIndex + 1) % 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<World> lastLayerWorlds = new ArrayList<>();
|
||||||
|
|
||||||
|
//Generate worlds
|
||||||
|
for (Integer key : worldLayers.keySet()) {
|
||||||
|
|
||||||
|
ArrayList<WorldBluePrint> layer = worldLayers.get(key);
|
||||||
|
|
||||||
|
for (WorldBluePrint bp : layer) {
|
||||||
|
World vWorld = generator.generateVaultWorld(bp.coords.x, bp.coords.y, bp.openings, name);
|
||||||
GameServer.INSTANCE.getGameUniverse().addWorld(vWorld);
|
GameServer.INSTANCE.getGameUniverse().addWorld(vWorld);
|
||||||
|
|
||||||
|
if (key == layerCount - 1) {
|
||||||
|
lastLayerWorlds.add(vWorld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//4. Choose a random world from the last layer and create the vault box there (objective)
|
||||||
|
World objectiveWorld = lastLayerWorlds.get(random.nextInt(lastLayerWorlds.size()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean worldExists(Point coords, HashMap<Integer, ArrayList<WorldBluePrint>> worldLayers) {
|
||||||
|
|
||||||
|
//Auto-generated by IntelliJ Idea
|
||||||
|
return worldLayers.values().stream().flatMap(Collection::stream).anyMatch(bp -> bp.coords.equals(coords));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class WorldBluePrint {
|
||||||
|
|
||||||
|
public ArrayList<Direction> openings = new ArrayList<>(4);
|
||||||
|
|
||||||
|
public Point coords = new Point();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the blueprint's openings to allow traveling to the newly attached world
|
||||||
|
*
|
||||||
|
* @param direction direction of the world to attach (relative to this one)
|
||||||
|
* @return The blueprint of the attached world
|
||||||
|
*/
|
||||||
|
public WorldBluePrint attachWorld(Direction direction) {
|
||||||
|
|
||||||
|
WorldBluePrint attachedWorld = new WorldBluePrint();
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case NORTH:
|
||||||
|
openings.add(Direction.NORTH);
|
||||||
|
attachedWorld.openings.add(Direction.SOUTH);
|
||||||
|
break;
|
||||||
|
case EAST:
|
||||||
|
openings.add(Direction.EAST);
|
||||||
|
attachedWorld.openings.add(Direction.WEST);
|
||||||
|
break;
|
||||||
|
case SOUTH:
|
||||||
|
openings.add(Direction.SOUTH);
|
||||||
|
attachedWorld.openings.add(Direction.NORTH);
|
||||||
|
break;
|
||||||
|
case WEST:
|
||||||
|
openings.add(Direction.WEST);
|
||||||
|
attachedWorld.openings.add(Direction.EAST);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
attachedWorld.coords.x = coords.x + direction.dX;
|
||||||
|
attachedWorld.coords.y = coords.y + direction.dY;
|
||||||
|
|
||||||
|
return attachedWorld;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the coordinates of a world that would be attached to this world
|
||||||
|
*
|
||||||
|
* @param direction direction of the attached world
|
||||||
|
*/
|
||||||
|
Point coordinatesOf(Direction direction) {
|
||||||
|
|
||||||
|
return new Point(coords.x + direction.dX, coords.y + direction.dY);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user