diff --git a/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java b/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java index 12756a5b..0d1ddc12 100644 --- a/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java +++ b/src/main/java/electrosphere/engine/loadingthreads/ClientLoading.java @@ -111,6 +111,7 @@ public class ClientLoading { //init camera Globals.playerCamera = CameraEntityUtils.spawnBasicCameraEntity(new Vector3f(0,0,0), new Vector3f(-1,0,0)); + Globals.cameraHandler.setTrackPlayerEntity(false); //initialize the "real" objects simulation initClientSimulation(); //init foliage manager diff --git a/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java b/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java index 02997405..61fd39dc 100644 --- a/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java +++ b/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java @@ -95,6 +95,11 @@ public class TerrainProtocol implements ServerProtocolTemplate { // System.out.println("Received request for chunk " + message.getworldX() + " " + message.getworldY()); Realm realm = Globals.playerManager.getPlayerRealm(connectionHandler.getPlayer()); + if(realm.getServerWorldData().getServerTerrainManager() == null){ + return; + } + + //get the chunk ServerTerrainChunk chunk = realm.getServerWorldData().getServerTerrainManager().getChunk(worldX, worldY, worldZ); // float[][] macroValues = chunk.getMacroValues();//Globals.serverTerrainManager.getRad5MacroValues(message.getworldX(), message.getworldY()); @@ -225,6 +230,10 @@ public class TerrainProtocol implements ServerProtocolTemplate { */ static void sendWorldFluidSubChunk(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ){ Realm realm = Globals.playerManager.getPlayerRealm(connectionHandler.getPlayer()); + + if(realm.getServerWorldData().getServerTerrainManager() == null){ + return; + } // System.out.println("Received request for chunk " + message.getworldX() + " " + message.getworldY()); diff --git a/src/main/java/electrosphere/server/character/PlayerCharacterCreation.java b/src/main/java/electrosphere/server/character/PlayerCharacterCreation.java index f386a844..fecc269a 100644 --- a/src/main/java/electrosphere/server/character/PlayerCharacterCreation.java +++ b/src/main/java/electrosphere/server/character/PlayerCharacterCreation.java @@ -63,13 +63,7 @@ public class PlayerCharacterCreation { // //attach entity to player object LoggerInterface.loggerEngine.INFO("Spawned entity for player. Entity id: " + newPlayerEntity.getId() + " Player id: " + playerObject.getId()); - int playerCharacterId = newPlayerEntity.getId(); - connectionHandler.setPlayerEntityId(playerCharacterId); - CreatureUtils.setControllerPlayerId(newPlayerEntity, connectionHandler.getPlayerId()); - //custom player btrees - addPlayerServerBTrees(newPlayerEntity); - //attach player object to player character - playerObject.setPlayerEntity(newPlayerEntity); + attachEntityToPlayerObject(newPlayerEntity,playerObject,connectionHandler); playerObject.setWorldPos(new Vector3i( realm.getServerWorldData().convertRealToChunkSpace(spawnPoint.x), realm.getServerWorldData().convertRealToChunkSpace(spawnPoint.y), @@ -85,6 +79,20 @@ public class PlayerCharacterCreation { } } + /** + * Attachs an entity to a player object + * @param entity The entity + * @param playerObject The player object + * @param serverConnectionHandler The connection handler + */ + public static void attachEntityToPlayerObject(Entity entity, Player playerObject, ServerConnectionHandler serverConnectionHandler){ + int playerCharacterId = entity.getId(); + serverConnectionHandler.setPlayerEntityId(playerCharacterId); + CreatureUtils.setControllerPlayerId(entity, serverConnectionHandler.getPlayerId()); + //custom player btrees + addPlayerServerBTrees(entity); + } + /** * Adds behavior trees that are unique to players a given entity * @param entity The entity to add to diff --git a/src/test/java/electrosphere/entity/state/equip/ClientEquipStateTests.java b/src/test/java/electrosphere/entity/state/equip/ClientEquipStateTests.java index bfed0028..eb505e23 100644 --- a/src/test/java/electrosphere/entity/state/equip/ClientEquipStateTests.java +++ b/src/test/java/electrosphere/entity/state/equip/ClientEquipStateTests.java @@ -20,6 +20,7 @@ import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.item.ItemUtils; import template.EntityTestTemplate; import testutils.TestEngineUtils; +import testutils.TestViewportUtils; /** * Tests for client side equip state @@ -86,8 +87,7 @@ public class ClientEquipStateTests extends EntityTestTemplate { TestEngineUtils.simulateFrames(1); //spawn entities - CreatureTemplate creatureTemplate = CreatureTemplate.createDefault("human"); - Entity creature = CreatureUtils.serverSpawnBasicCreature(Globals.realmManager.first(), new Vector3d(0,0,0), "human", creatureTemplate); + Globals.playerEntity = TestViewportUtils.spawnPlayerCharacter("human"); //TODO: associate creature with player object created for viewport ItemUtils.serverSpawnBasicItem(Globals.realmManager.first(), new Vector3d(0,0,0), "Katana2H"); diff --git a/src/test/java/testutils/TestViewportUtils.java b/src/test/java/testutils/TestViewportUtils.java new file mode 100644 index 00000000..5fbd301f --- /dev/null +++ b/src/test/java/testutils/TestViewportUtils.java @@ -0,0 +1,69 @@ +package testutils; + +import java.util.concurrent.TimeUnit; + +import org.joml.Vector3d; + +import electrosphere.engine.Globals; +import electrosphere.engine.loadingthreads.LoadingThread; +import electrosphere.entity.Entity; +import electrosphere.entity.types.creature.CreatureTemplate; +import electrosphere.entity.types.creature.CreatureUtils; +import electrosphere.net.NetUtils; +import electrosphere.net.server.ServerConnectionHandler; +import electrosphere.net.server.player.Player; +import electrosphere.server.character.PlayerCharacterCreation; + +/** + * Utilities for testing in the viewport + */ +public class TestViewportUtils { + + //The maximum number of frames to wait before failing the startup routine + public static final int MAX_FRAMES_TO_WAIT = 100; + + /** + * Spawns a creature assigned to the player + * @param creatureType The type of creature to spawn + * @return Returns the player's entity + */ + public static Entity spawnPlayerCharacter(String creatureType){ + //spawn creature + CreatureTemplate creatureTemplate = CreatureTemplate.createDefault(creatureType); + Entity creature = CreatureUtils.serverSpawnBasicCreature(Globals.realmManager.first(), new Vector3d(0,0,0), creatureType, creatureTemplate); + + //get required data + ServerConnectionHandler connectionHandler = Globals.server.getFirstConnection(); + Player playerObj = Globals.playerManager.getFirstPlayer(); + + //attach + PlayerCharacterCreation.attachEntityToPlayerObject(creature, playerObj, connectionHandler); + //must manually send packet because the player is added to the viewport before the entity is created + //in the real flow, the entity is created, then the player is sent + playerObj.addMessage(NetUtils.createSetCreatureControllerIdEntityMessage(creature)); + + //wait for player to spawn + int frames = 0; + while(Globals.playerEntity == null){ + TestEngineUtils.simulateFrames(1); + try { + TimeUnit.MILLISECONDS.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } + frames++; + if(frames > MAX_FRAMES_TO_WAIT){ + String errorMessage = "Failed to spawn player character!\n" + + "Still running threads are:\n" + ; + for(LoadingThread thread : Globals.threadManager.getLoadingThreads()){ + errorMessage = errorMessage + thread.getType() + "\n"; + } + throw new IllegalStateException(errorMessage); + } + } + + return creature; + } + +}