diff --git a/src/main/java/com/syncleus/aethermud/Main.java b/src/main/java/com/syncleus/aethermud/Main.java index 09793c2887294916b48e7deb87d206016a54c636..060c17ebc5201f420e02f4154ecfd62de893e7a3 100644 --- a/src/main/java/com/syncleus/aethermud/Main.java +++ b/src/main/java/com/syncleus/aethermud/Main.java @@ -30,23 +30,15 @@ import com.syncleus.aethermud.player.PlayerManagementManager; import com.syncleus.aethermud.player.PlayerManager; import com.syncleus.aethermud.server.communication.ChannelUtils; import com.syncleus.aethermud.server.telnet.AetherMudServer; -import com.syncleus.aethermud.storage.WorldStorage; import com.syncleus.aethermud.storage.graphdb.*; -import com.syncleus.aethermud.storage.graphdb.model.*; import com.syncleus.aethermud.world.MapsManager; import com.syncleus.aethermud.world.RoomManager; import com.google.common.io.Files; -import com.syncleus.ferma.DelegatingFramedGraph; -import com.syncleus.ferma.WrappedFramedGraph; import org.apache.commons.codec.binary.Base64; import org.apache.commons.configuration.*; import org.apache.http.impl.client.HttpClients; import org.apache.log4j.Logger; -import org.apache.tinkerpop.gremlin.structure.Graph; -import org.apache.tinkerpop.gremlin.structure.io.IoCore; -import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; import java.io.File; -import java.io.IOException; import java.net.InetSocketAddress; import java.util.*; import java.util.concurrent.TimeUnit; @@ -103,8 +95,10 @@ public class Main { GameManager gameManager = new GameManager(graphStorageFactory, aetherMudConfiguration, roomManager, playerManager, entityManager, mapsManager, channelUtils, HttpClients.createDefault()); startUpMessage("Reading world from disk."); - WorldStorage worldExporter = new WorldStorage(roomManager, mapsManager, gameManager.getFloorManager(), entityManager, gameManager); - worldExporter.readWorldFromDisk(); + try( GraphStorageFactory.AetherMudTx tx = gameManager.getGraphStorageFactory().beginTransaction() ) { + tx.getStorage().loadWorld(mapsManager, entityManager, gameManager); + tx.success(); + } startUpMessage("Creating and registering Player Management MBeans."); PlayerManagementManager playerManagementManager = new PlayerManagementManager(gameManager); diff --git a/src/main/java/com/syncleus/aethermud/command/commands/Command.java b/src/main/java/com/syncleus/aethermud/command/commands/Command.java index cd3c03203831fbbb08aca3116ab7c6640116a8bb..2b9b487052316de7771441866c9d99e1f2166321 100644 --- a/src/main/java/com/syncleus/aethermud/command/commands/Command.java +++ b/src/main/java/com/syncleus/aethermud/command/commands/Command.java @@ -24,7 +24,6 @@ import com.syncleus.aethermud.player.PlayerManager; import com.syncleus.aethermud.player.PlayerRole; import com.syncleus.aethermud.server.model.AetherMudSession; import com.syncleus.aethermud.server.communication.ChannelCommunicationUtils; -import com.syncleus.aethermud.storage.WorldStorage; import com.syncleus.aethermud.world.FloorManager; import com.syncleus.aethermud.world.MapMatrix; import com.syncleus.aethermud.world.MapsManager; @@ -63,7 +62,6 @@ public abstract class Command extends SimpleChannelUpstreamHandler { public Optional<MapMatrix> mapMatrix = Optional.empty(); public Optional<Coords> currentRoomCoords = Optional.empty(); public List<String> originalMessageParts; - public WorldStorage worldExporter; public String rootCommand; protected Command(GameManager gameManager, List<String> validTriggers, String description, String correctUsage) { @@ -81,7 +79,6 @@ public abstract class Command extends SimpleChannelUpstreamHandler { this.entityManager = gameManager.getEntityManager(); this.playerManager = gameManager.getPlayerManager(); this.channelUtils = gameManager.getChannelUtils(); - this.worldExporter = new WorldStorage(roomManager, mapsManager, floorManager, entityManager, gameManager); this.lootManager = gameManager.getLootManager(); this.roles = roles; } diff --git a/src/main/java/com/syncleus/aethermud/command/commands/admin/BuildCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/admin/BuildCommand.java index e103b2fe6871c94d747c4b42eebca8f64d587bdf..98b48ba453e42c8d127759279c93d71d25a1294e 100644 --- a/src/main/java/com/syncleus/aethermud/command/commands/admin/BuildCommand.java +++ b/src/main/java/com/syncleus/aethermud/command/commands/admin/BuildCommand.java @@ -19,7 +19,7 @@ import com.syncleus.aethermud.command.commands.Command; import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.player.PlayerMovement; import com.syncleus.aethermud.player.PlayerRole; -import com.syncleus.aethermud.storage.WorldStorage; +import com.syncleus.aethermud.storage.AetherMudStorage; import com.syncleus.aethermud.world.MapMatrix; import com.google.common.collect.Lists; import com.google.common.collect.Sets; @@ -225,7 +225,7 @@ public class BuildCommand extends Command { private void addNewRoomAndFloorAndMovePlayer(Room newRoom, FloorModel newFloorModel, Optional<RemoteExit> returnRemoteExit) { entityManager.addEntity(newRoom); - Set<RoomModel> roomModels = Sets.newHashSet(newRoom).stream().map(WorldStorage.buildRoomModelsFromRooms()).collect(Collectors.toSet()); + Set<RoomModel> roomModels = Sets.newHashSet(newRoom).stream().map(AetherMudStorage.buildRoomModelsFromRooms()).collect(Collectors.toSet()); newFloorModel.setRoomModels(roomModels); floorManager.addFloor(newFloorModel.getId(), newFloorModel.getName()); MapMatrix matrixFromCsv = MapMatrix.createMatrixFromCsv(newFloorModel.getRawMatrixCsv()); diff --git a/src/main/java/com/syncleus/aethermud/command/commands/admin/LoadWorldCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/admin/LoadWorldCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..148eddb8d5d0dc9cd1a1c90e9984fe0266a6607c --- /dev/null +++ b/src/main/java/com/syncleus/aethermud/command/commands/admin/LoadWorldCommand.java @@ -0,0 +1,126 @@ +/** + * Copyright 2017 - 2018 Syncleus, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.syncleus.aethermud.command.commands.admin; + +import com.syncleus.aethermud.command.commands.Command; +import com.syncleus.aethermud.core.GameManager; +import com.syncleus.aethermud.npc.Npc; +import com.syncleus.aethermud.player.PlayerRole; +import com.syncleus.aethermud.spawner.SpawnRule; +import com.syncleus.aethermud.storage.AetherMudStorage; +import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; +import com.syncleus.aethermud.storage.graphdb.model.NpcData; +import com.google.common.collect.Sets; +import com.syncleus.aethermud.world.model.WorldModel; +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.util.EntityUtils; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.MessageEvent; + +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + +public class LoadWorldCommand extends Command { + + final static List<String> validTriggers = Arrays.asList("loadworld"); + final static String description = "Load a World using JSON over http"; + final static String correctUsage = "loadworld <http url with json for world>"; + final static Set<PlayerRole> roles = Sets.newHashSet(PlayerRole.ADMIN); + + public LoadWorldCommand(GameManager gameManager) { + super(gameManager, validTriggers, description, correctUsage, roles); + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { + execCommand(ctx, e, () -> { + + if (originalMessageParts.size() <= 1) { + write("Please specify a http url." + "\r\n"); + return; + } + + originalMessageParts.remove(0); + + + String worldJsonHttpUrl = originalMessageParts.get(0); + if (!isValidURL(worldJsonHttpUrl)) { + write("Invalid HTTP address." + "\r\n"); + return; + } + + HttpGet httpGet = new HttpGet(worldJsonHttpUrl); + + HttpClient httpclient = gameManager.getHttpclient(); + + HttpResponse httpResponse = httpclient.execute(httpGet); + + HttpEntity entity = httpResponse.getEntity(); + + if (entity == null) { + write("Error retrieving JSON url." + "\r\n"); + return; + } + + String worldJson = EntityUtils.toString(entity); + + WorldModel world = null; + try { + world = gameManager.getGson().fromJson(worldJson, WorldModel.class); + } catch (Exception ex) { + write("Retrieved JSON file is malformed. " + ex.getLocalizedMessage() + "\r\n"); + return; + } + httpGet.reset(); + + try( GraphStorageFactory.AetherMudTx tx = this.gameManager.getGraphStorageFactory().beginTransaction() ) { + AetherMudStorage storage = tx.getStorage(); + storage.loadWorld( roomManager, mapsManager, entityManager, gameManager, world); + tx.success(); + } + + }); + } + + public boolean isValidURL(String url) { + URL u = null; + try { + u = new URL(url); + } catch (MalformedURLException e) { + return false; + } + try { + u.toURI(); + } catch (URISyntaxException e) { + return false; + } + return true; + } + +} + + + diff --git a/src/main/java/com/syncleus/aethermud/command/commands/admin/SaveWorldCommand.java b/src/main/java/com/syncleus/aethermud/command/commands/admin/SaveWorldCommand.java index aa5aac732acd5c63601be569bb9cf30967b454ed..15c6b42c40aa7fb26139c4ec401b0b2b93daa37f 100644 --- a/src/main/java/com/syncleus/aethermud/command/commands/admin/SaveWorldCommand.java +++ b/src/main/java/com/syncleus/aethermud/command/commands/admin/SaveWorldCommand.java @@ -19,6 +19,7 @@ import com.syncleus.aethermud.command.commands.Command; import com.syncleus.aethermud.core.GameManager; import com.syncleus.aethermud.player.PlayerRole; import com.google.common.collect.Sets; +import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.MessageEvent; @@ -40,7 +41,10 @@ public class SaveWorldCommand extends Command { @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { execCommandThreadSafe(ctx, e, SaveWorldCommand.class, () -> { - worldExporter.saveWorld(); + try( GraphStorageFactory.AetherMudTx tx = this.gameManager.getGraphStorageFactory().beginTransaction() ) { + tx.getStorage().saveWorld(roomManager, mapsManager, floorManager); + tx.success(); + } write("World saved."); }); } diff --git a/src/main/java/com/syncleus/aethermud/configuration/ConfigureCommands.java b/src/main/java/com/syncleus/aethermud/configuration/ConfigureCommands.java index f6810727a0ec28107d8d2c9e6eb2c47bdef5e55b..bc838b20ac6ef9bf31921216d2cc3a29706caf64 100644 --- a/src/main/java/com/syncleus/aethermud/configuration/ConfigureCommands.java +++ b/src/main/java/com/syncleus/aethermud/configuration/ConfigureCommands.java @@ -120,6 +120,7 @@ public class ConfigureCommands { commandRegistry.addCommand(new LoadNpcCommand(gameManager)); commandRegistry.addCommand(new LoadItemCommand(gameManager)); commandRegistry.addCommand(new LoadMerchantCommand(gameManager)); + commandRegistry.addCommand(new LoadWorldCommand(gameManager)); commandRegistry.addCommand(new RestartCommand(gameManager)); commandRegistry.addCommand(new GiveHealthCommand(gameManager)); commandRegistry.addCommand(new GraphStatusCommand(gameManager)); diff --git a/src/main/java/com/syncleus/aethermud/storage/AetherMudStorage.java b/src/main/java/com/syncleus/aethermud/storage/AetherMudStorage.java index 8cb5840f5f71af71e43c6ceb7df1f0b3bb0a14ca..477b5214b7ea73a6f73f15f20de160a4ae308d7b 100644 --- a/src/main/java/com/syncleus/aethermud/storage/AetherMudStorage.java +++ b/src/main/java/com/syncleus/aethermud/storage/AetherMudStorage.java @@ -17,15 +17,21 @@ package com.syncleus.aethermud.storage; import com.syncleus.aethermud.core.GameManager; +import com.syncleus.aethermud.entity.EntityManager; import com.syncleus.aethermud.items.Item; import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.merchant.Merchant; import com.syncleus.aethermud.npc.NpcSpawn; import com.syncleus.aethermud.storage.graphdb.model.*; +import com.syncleus.aethermud.world.FloorManager; +import com.syncleus.aethermud.world.MapsManager; +import com.syncleus.aethermud.world.RoomManager; +import com.syncleus.aethermud.world.model.*; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.function.Function; public interface AetherMudStorage { @@ -66,4 +72,31 @@ public interface AetherMudStorage { Optional<MerchantData> getMerchantData(String internalName); MerchantData newMerchantData(); + + void saveWorld(RoomManager roomManager, MapsManager mapsManager, FloorManager floorManager); + + void loadWorld(MapsManager mapsManager, EntityManager entityManager, GameManager gameManager); + + void loadWorld(RoomManager roomManager, MapsManager mapsManager, EntityManager entityManager, GameManager gameManager, WorldModel worldModel); + + static Function<Room, RoomModel> buildRoomModelsFromRooms() { + return room -> { + RoomModelBuilder roomModelBuilder = new RoomModelBuilder(); + for (RemoteExit remoteExit : room.getEnterExits()) { + roomModelBuilder.addEnterExitName(remoteExit.getRoomId(), remoteExit.getExitDetail()); + } + roomModelBuilder.setRoomDescription(room.getRoomDescription()); + roomModelBuilder.setRoomTitle(room.getRoomTitle()); + roomModelBuilder.setRoomId(room.getRoomId()); + roomModelBuilder.setRoomTags(room.getRoomTags()); + roomModelBuilder.setFloorId(room.getFloorId()); + for (Area area : room.getAreas()) { + roomModelBuilder.addAreaName(area.getName()); + } + for (Map.Entry<String, String> notable : room.getNotables().entrySet()) { + roomModelBuilder.addNotable(notable.getKey(), notable.getValue()); + } + return roomModelBuilder.build(); + }; + } } diff --git a/src/main/java/com/syncleus/aethermud/storage/WorldStorage.java b/src/main/java/com/syncleus/aethermud/storage/WorldStorage.java deleted file mode 100644 index ede7cc010d79cba9205f933a3d1094f6c2d25007..0000000000000000000000000000000000000000 --- a/src/main/java/com/syncleus/aethermud/storage/WorldStorage.java +++ /dev/null @@ -1,224 +0,0 @@ -/** - * Copyright 2017 - 2018 Syncleus, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.syncleus.aethermud.storage; - -import com.syncleus.aethermud.core.GameManager; -import com.syncleus.aethermud.core.SentryManager; -import com.syncleus.aethermud.entity.EntityManager; -import com.syncleus.aethermud.world.FloorManager; -import com.syncleus.aethermud.world.MapMatrix; -import com.syncleus.aethermud.world.MapsManager; -import com.syncleus.aethermud.world.RoomManager; -import com.google.common.collect.Sets; -import com.google.common.io.Files; -import com.google.gson.GsonBuilder; -import com.syncleus.aethermud.world.model.*; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.*; -import java.util.function.Function; - -public class WorldStorage { - - private final static String WORLD_DIR = "world/"; - - private final RoomManager roomManager; - private final MapsManager mapsManager; - private final FloorManager floorManager; - private final EntityManager entityManager; - private final GameManager gameManager; - - public WorldStorage(RoomManager roomManager, MapsManager mapsManager, FloorManager floorManager, EntityManager entityManager, GameManager gameManager) { - this.roomManager = roomManager; - this.mapsManager = mapsManager; - this.floorManager = floorManager; - this.entityManager = entityManager; - this.gameManager = gameManager; - } - - public void saveWorld() { - WorldModel worldModel = new WorldModel(); - Set<FloorModel> floors = Sets.newHashSet(); - Set<Integer> floorIds = floorManager.getFloorIds(); - for (Integer floorId : floorIds) { - floors.add(generateFloorModel(floorId, mapsManager.getFloorMatrixMaps().get(floorId))); - } - worldModel.setFloorModelList(floors); - - String worldJson = new GsonBuilder().setPrettyPrinting().create().toJson(worldModel, WorldModel.class); - try { - Files.write(worldJson.getBytes(), new File(WORLD_DIR + "world.json")); - } catch (IOException e) { - SentryManager.logSentry(this.getClass(), e, "Save world problem!"); - e.printStackTrace(); - } - } - - private FloorModel generateFloorModel(Integer floorId, MapMatrix mapMatrix) { - Set<Room> rooms = roomManager.getRoomsByFloorId(floorId); - FloorModel floorModel = new FloorModel(); - floorModel.setId(floorId); - floorModel.setRawMatrixCsv(mapMatrix.getCsv()); - floorModel.setRoomModels((new HashSet<RoomModel>())); - floorModel.setName(floorManager.getName(floorId)); - rooms.stream() - .map(buildRoomModelsFromRooms()) - .forEach(roomModel -> floorModel.getRoomModels() - .add(roomModel)); - return floorModel; - } - - public static Function<Room, RoomModel> buildRoomModelsFromRooms() { - return room -> { - RoomModelBuilder roomModelBuilder = new RoomModelBuilder(); - for (RemoteExit remoteExit : room.getEnterExits()) { - roomModelBuilder.addEnterExitName(remoteExit.getRoomId(), remoteExit.getExitDetail()); - } - roomModelBuilder.setRoomDescription(room.getRoomDescription()); - roomModelBuilder.setRoomTitle(room.getRoomTitle()); - roomModelBuilder.setRoomId(room.getRoomId()); - roomModelBuilder.setRoomTags(room.getRoomTags()); - roomModelBuilder.setFloorId(room.getFloorId()); - for (Area area : room.getAreas()) { - roomModelBuilder.addAreaName(area.getName()); - } - for (Map.Entry<String, String> notable : room.getNotables().entrySet()) { - roomModelBuilder.addNotable(notable.getKey(), notable.getValue()); - } - return roomModelBuilder.build(); - }; - } - - public Function<RoomModel, BasicRoom> getBasicRoom(final MapMatrix mapMatrix) { - return roomModel -> { - BasicRoomBuilder basicRoomBuilder = new BasicRoomBuilder(gameManager) - .setRoomId(roomModel.getRoomId()) - .setFloorId(roomModel.getFloorId()) - .setRoomDescription(roomModel.getRoomDescription()) - .setRoomTitle(roomModel.getRoomTitle()); - - for (String tag : roomModel.getRoomTags()) { - basicRoomBuilder.addTag(tag); - } - for (String areaName : roomModel.getAreaNames()) { - Area byName = Area.getByName(areaName); - if (byName != null) { - basicRoomBuilder.addArea(byName); - } - } - Map<String, String> enterExitNames = roomModel.getEnterExitNames(); - if (enterExitNames != null) { - for (Map.Entry<String, String> next : enterExitNames.entrySet()) { - RemoteExit remoteExit = new RemoteExit(RemoteExit.Direction.ENTER, Integer.parseInt(next.getKey()), next.getValue()); - basicRoomBuilder.addEnterExit(remoteExit); - mapMatrix.addRemote(roomModel.getRoomId(), remoteExit); - } - } - Map<String, String> notables = roomModel.getNotables(); - if (notables != null) { - for (Map.Entry<String, String> next : notables.entrySet()) { - basicRoomBuilder.addNotable(next.getKey(), next.getValue()); - } - } - configureExits(basicRoomBuilder, mapMatrix, roomModel.getRoomId()); - return basicRoomBuilder.createBasicRoom(); - }; - } - - private void configureExits(BasicRoomBuilder basicRoomBuilder, MapMatrix mapMatrix, int roomId) { - Integer north = mapMatrix.getNorthernExit(roomId); - if (north > 0) { - basicRoomBuilder.setNorthId(Optional.of(north)); - } - Integer east = mapMatrix.getEasternExit(roomId); - if (east > 0) { - basicRoomBuilder.setEastId(Optional.of(east)); - } - Integer south = mapMatrix.getSouthernExit(roomId); - if (south > 0) { - basicRoomBuilder.setSouthId(Optional.of(south)); - } - Integer west = mapMatrix.getWesternExit(roomId); - if (west > 0) { - basicRoomBuilder.setWestId(Optional.of(west)); - } - if (mapMatrix.getRemotes().containsKey(roomId)) { - for (RemoteExit exit : mapMatrix.getRemotes().get(roomId)) { - if (exit.getDirection().equals(RemoteExit.Direction.UP)) { - basicRoomBuilder.setUpId(Optional.of(exit.getRoomId())); - } else if (exit.getDirection().equals(RemoteExit.Direction.DOWN)) { - basicRoomBuilder.setDownId(Optional.of(exit.getRoomId())); - } - } - } - } - - private void buildFloor(FloorModel floorModel) { - MapMatrix matrixFromCsv = MapMatrix.createMatrixFromCsv(floorModel.getRawMatrixCsv()); - Set<Room> rooms = Sets.newHashSet(); - if (floorModel.getRoomModels() == null || floorModel.getRoomModels().size() == 0) { - Iterator<List<Integer>> rows = matrixFromCsv.getRows(); - while (rows.hasNext()) { - List<Integer> row = rows.next(); - for (Integer roomId : row) { - if (roomId.equals(0)) { - continue; - } - BasicRoomBuilder basicRoomBuilder = new BasicRoomBuilder(gameManager); - basicRoomBuilder.setFloorId(floorModel.getId()); - basicRoomBuilder.setRoomId(roomId); - basicRoomBuilder.setRoomTitle("This is a blank title."); - basicRoomBuilder.setRoomDescription("This is a blank Description.\nWords should go here, ideally."); - configureExits(basicRoomBuilder, matrixFromCsv, roomId); - rooms.add(basicRoomBuilder.createBasicRoom()); - } - } - for (Room r : rooms) { - entityManager.addEntity(r); - } - floorManager.addFloor(floorModel.getId(), floorModel.getName()); - mapsManager.addFloorMatrix(floorModel.getId(), matrixFromCsv); - return; - } - floorModel.getRoomModels().stream().map(getBasicRoom(matrixFromCsv)).forEach(entityManager::addEntity); - floorManager.addFloor(floorModel.getId(), floorModel.getName()); - mapsManager.addFloorMatrix(floorModel.getId(), matrixFromCsv); - } - - public void readWorldFromDisk() throws FileNotFoundException { - WorldModel worldModel = new GsonBuilder().create().fromJson(Files.newReader(new File(("world/world.json")), Charset.defaultCharset()), WorldModel.class); - worldModel.getFloorModelList() - .forEach(this::buildFloor); - } - - public void buildTestworld() { - WorldModel worldModel = new GsonBuilder().create().fromJson("{\n" + - " \"floorModelList\": [\n" + - " {\n" + - " \"name\": \"main\",\n" + - " \"id\": 0,\n" + - " \"rawMatrixCsv\": \"0,1\"\n" + - "}]\n" + - "}", WorldModel.class); - for (FloorModel next : worldModel.getFloorModelList()) { - buildFloor(next); - } - } - -} diff --git a/src/main/java/com/syncleus/aethermud/storage/graphdb/GraphDbAetherMudStorage.java b/src/main/java/com/syncleus/aethermud/storage/graphdb/GraphDbAetherMudStorage.java index f515c05be5d1b26e12778bde7650992901580190..af7066eb9f508d588c8c69ea4a4edfcb87aa0263 100644 --- a/src/main/java/com/syncleus/aethermud/storage/graphdb/GraphDbAetherMudStorage.java +++ b/src/main/java/com/syncleus/aethermud/storage/graphdb/GraphDbAetherMudStorage.java @@ -17,7 +17,10 @@ package com.syncleus.aethermud.storage.graphdb; import com.google.common.collect.Interner; import com.google.common.collect.Interners; +import com.google.common.collect.Sets; +import com.google.gson.GsonBuilder; import com.syncleus.aethermud.core.GameManager; +import com.syncleus.aethermud.entity.EntityManager; import com.syncleus.aethermud.items.Item; import com.syncleus.aethermud.items.ItemInstance; import com.syncleus.aethermud.merchant.Merchant; @@ -26,12 +29,18 @@ import com.syncleus.aethermud.npc.NpcSpawn; import com.syncleus.aethermud.storage.AetherMudStorage; import com.syncleus.aethermud.storage.GraphInfo; import com.syncleus.aethermud.storage.graphdb.model.*; +import com.syncleus.aethermud.world.FloorManager; +import com.syncleus.aethermud.world.MapMatrix; +import com.syncleus.aethermud.world.MapsManager; +import com.syncleus.aethermud.world.RoomManager; +import com.syncleus.aethermud.world.model.*; import com.syncleus.ferma.VertexFrame; import com.syncleus.ferma.WrappedFramedGraph; import org.apache.log4j.Logger; import org.apache.tinkerpop.gremlin.structure.Graph; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; public class GraphDbAetherMudStorage implements AetherMudStorage { @@ -194,4 +203,163 @@ public class GraphDbAetherMudStorage implements AetherMudStorage { public MerchantData newMerchantData() { return framedGraph.addFramedVertex(MerchantData.class); } + + @Override + public void loadWorld(RoomManager roomManager, MapsManager mapsManager, EntityManager entityManager, GameManager gameManager, WorldModel worldModel) { + for( FloorModel floorModel : worldModel.getFloorModelList()) + this.buildFloor(mapsManager, entityManager, gameManager, floorModel); + this.saveWorld(roomManager, mapsManager, gameManager.getFloorManager()); + } + + @Override + public void loadWorld( MapsManager mapsManager, EntityManager entityManager, GameManager gameManager) { + WorldModelData data = framedGraph.traverse((g) -> framedGraph.getTypeResolver().hasType(g.V(), WorldModelData.class)).nextOrDefault(WorldModelData.class,null); + if( data != null) { + WorldModel worldModel = WorldModelData.copyWorldModel(data); + for( FloorModel floorModel : worldModel.getFloorModelList()) + this.buildFloor(mapsManager, entityManager, gameManager, floorModel); + } else { + this.buildEmptyWorld(mapsManager, entityManager, gameManager); + } + } + + @Override + public void saveWorld(RoomManager roomManager, MapsManager mapsManager, FloorManager floorManager) { + WorldModel worldModel = new WorldModel(); + Set<FloorModel> floors = Sets.newHashSet(); + Set<Integer> floorIds = floorManager.getFloorIds(); + for (Integer floorId : floorIds) { + floors.add(generateFloorModel(roomManager, floorManager, floorId, mapsManager.getFloorMatrixMaps().get(floorId))); + } + worldModel.setFloorModelList(floors); + + WorldModelData data = framedGraph.traverse((g) -> framedGraph.getTypeResolver().hasType(g.V(), WorldModelData.class)).nextOrDefault(WorldModelData.class,null); + if( data == null ) + data = framedGraph.addFramedVertex(WorldModelData.class); + WorldModelData.copyWorldModel(data, worldModel); + } + + private FloorModel generateFloorModel(RoomManager roomManager, FloorManager floorManager, Integer floorId, MapMatrix mapMatrix) { + Set<Room> rooms = roomManager.getRoomsByFloorId(floorId); + FloorModel floorModel = new FloorModel(); + floorModel.setId(floorId); + floorModel.setRawMatrixCsv(mapMatrix.getCsv()); + floorModel.setRoomModels((new HashSet<RoomModel>())); + floorModel.setName(floorManager.getName(floorId)); + rooms.stream() + .map(AetherMudStorage.buildRoomModelsFromRooms()) + .forEach(roomModel -> floorModel.getRoomModels() + .add(roomModel)); + return floorModel; + } + + public Function<RoomModel, BasicRoom> getBasicRoom(GameManager gameManager, final MapMatrix mapMatrix) { + return roomModel -> { + BasicRoomBuilder basicRoomBuilder = new BasicRoomBuilder(gameManager) + .setRoomId(roomModel.getRoomId()) + .setFloorId(roomModel.getFloorId()) + .setRoomDescription(roomModel.getRoomDescription()) + .setRoomTitle(roomModel.getRoomTitle()); + + for (String tag : roomModel.getRoomTags()) { + basicRoomBuilder.addTag(tag); + } + for (String areaName : roomModel.getAreaNames()) { + Area byName = Area.getByName(areaName); + if (byName != null) { + basicRoomBuilder.addArea(byName); + } + } + Map<String, String> enterExitNames = roomModel.getEnterExitNames(); + if (enterExitNames != null) { + for (Map.Entry<String, String> next : enterExitNames.entrySet()) { + RemoteExit remoteExit = new RemoteExit(RemoteExit.Direction.ENTER, Integer.parseInt(next.getKey()), next.getValue()); + basicRoomBuilder.addEnterExit(remoteExit); + mapMatrix.addRemote(roomModel.getRoomId(), remoteExit); + } + } + Map<String, String> notables = roomModel.getNotables(); + if (notables != null) { + for (Map.Entry<String, String> next : notables.entrySet()) { + basicRoomBuilder.addNotable(next.getKey(), next.getValue()); + } + } + configureExits(basicRoomBuilder, mapMatrix, roomModel.getRoomId()); + return basicRoomBuilder.createBasicRoom(); + }; + } + + private void configureExits(BasicRoomBuilder basicRoomBuilder, MapMatrix mapMatrix, int roomId) { + Integer north = mapMatrix.getNorthernExit(roomId); + if (north > 0) { + basicRoomBuilder.setNorthId(Optional.of(north)); + } + Integer east = mapMatrix.getEasternExit(roomId); + if (east > 0) { + basicRoomBuilder.setEastId(Optional.of(east)); + } + Integer south = mapMatrix.getSouthernExit(roomId); + if (south > 0) { + basicRoomBuilder.setSouthId(Optional.of(south)); + } + Integer west = mapMatrix.getWesternExit(roomId); + if (west > 0) { + basicRoomBuilder.setWestId(Optional.of(west)); + } + if (mapMatrix.getRemotes().containsKey(roomId)) { + for (RemoteExit exit : mapMatrix.getRemotes().get(roomId)) { + if (exit.getDirection().equals(RemoteExit.Direction.UP)) { + basicRoomBuilder.setUpId(Optional.of(exit.getRoomId())); + } else if (exit.getDirection().equals(RemoteExit.Direction.DOWN)) { + basicRoomBuilder.setDownId(Optional.of(exit.getRoomId())); + } + } + } + } + + private void buildFloor(MapsManager mapsManager, EntityManager entityManager, GameManager gameManager, FloorModel floorModel) { + MapMatrix matrixFromCsv = MapMatrix.createMatrixFromCsv(floorModel.getRawMatrixCsv()); + Set<Room> rooms = Sets.newHashSet(); + if (floorModel.getRoomModels() == null || floorModel.getRoomModels().size() == 0) { + Iterator<List<Integer>> rows = matrixFromCsv.getRows(); + while (rows.hasNext()) { + List<Integer> row = rows.next(); + for (Integer roomId : row) { + if (roomId.equals(0)) { + continue; + } + BasicRoomBuilder basicRoomBuilder = new BasicRoomBuilder(gameManager); + basicRoomBuilder.setFloorId(floorModel.getId()); + basicRoomBuilder.setRoomId(roomId); + basicRoomBuilder.setRoomTitle("This is a blank title."); + basicRoomBuilder.setRoomDescription("This is a blank Description.\nWords should go here, ideally."); + configureExits(basicRoomBuilder, matrixFromCsv, roomId); + rooms.add(basicRoomBuilder.createBasicRoom()); + } + } + for (Room r : rooms) { + entityManager.addEntity(r); + } + gameManager.getFloorManager().addFloor(floorModel.getId(), floorModel.getName()); + mapsManager.addFloorMatrix(floorModel.getId(), matrixFromCsv); + return; + } + floorModel.getRoomModels().stream().map(getBasicRoom(gameManager, matrixFromCsv)).forEach(entityManager::addEntity); + gameManager.getFloorManager().addFloor(floorModel.getId(), floorModel.getName()); + mapsManager.addFloorMatrix(floorModel.getId(), matrixFromCsv); + } + + private void buildEmptyWorld(MapsManager mapsManager, EntityManager entityManager, GameManager gameManager) { + WorldModel worldModel = new GsonBuilder().create().fromJson("{\n" + + " \"floorModelList\": [\n" + + " {\n" + + " \"name\": \"main\",\n" + + " \"id\": 0,\n" + + " \"rawMatrixCsv\": \"0,1\"\n" + + "}]\n" + + "}", WorldModel.class); + for (FloorModel next : worldModel.getFloorModelList()) { + buildFloor(mapsManager, entityManager, gameManager, next); + } + } } diff --git a/src/test/java/com/syncleus/aethermud/player/combatsimuation/NpcTestHarness.java b/src/test/java/com/syncleus/aethermud/player/combatsimuation/NpcTestHarness.java index 077739b09eb7fba4616c21f78a809236cbd589de..44ceb5a7103ff5143e4ff8a78c5b1fbfd1f73d03 100644 --- a/src/test/java/com/syncleus/aethermud/player/combatsimuation/NpcTestHarness.java +++ b/src/test/java/com/syncleus/aethermud/player/combatsimuation/NpcTestHarness.java @@ -30,7 +30,6 @@ import com.syncleus.aethermud.server.communication.ChannelCommunicationUtils; import com.syncleus.aethermud.stats.DefaultStats; import com.syncleus.aethermud.stats.Levels; import com.syncleus.aethermud.stats.experience.Experience; -import com.syncleus.aethermud.storage.WorldStorage; import com.syncleus.aethermud.storage.graphdb.GraphStorageFactory; import com.syncleus.aethermud.storage.graphdb.model.PlayerData; import com.syncleus.aethermud.world.MapsManager; @@ -345,8 +344,10 @@ public class NpcTestHarness { MapsManager mapsManager = new MapsManager(aetherMudConfiguration, roomManager); EntityManager entityManager = new EntityManager(storageFactory, roomManager, playerManager); GameManager gameManager = new GameManager(storageFactory, aetherMudConfiguration, roomManager, playerManager, entityManager, mapsManager, channelUtils, HttpClients.createDefault()); - WorldStorage worldExporter = new WorldStorage(roomManager, mapsManager, gameManager.getFloorManager(), entityManager, gameManager); - worldExporter.buildTestworld(); + try( GraphStorageFactory.AetherMudTx tx = gameManager.getGraphStorageFactory().beginTransaction() ) { + tx.getStorage().loadWorld(mapsManager, entityManager, gameManager); + tx.success(); + } ConfigureCommands.configure(gameManager); this.entityManager = entityManager; this.gameManager = gameManager;