diff --git a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java index 9c512c5..94af7f8 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/ChunkRender.java @@ -107,15 +107,15 @@ implements GenericChunk< return data; } - public void markForUpdate() { + public synchronized void markForUpdate() { this.needsUpdate = true; } - public boolean needsUpdate() { + public synchronized boolean needsUpdate() { return needsUpdate; } - public void render(ShapeRenderHelper renderer) { + public synchronized void render(ShapeRenderHelper renderer) { if (model == null || needsUpdate()) { buildModel(); } diff --git a/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java b/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java index 71acda9..14f99d4 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/WorldRender.java @@ -49,7 +49,8 @@ implements GenericWorld< private final WorldData data; - private final Map chunks = new HashMap<>(); + private final Map chunks = + Collections.synchronizedMap(new HashMap<>()); private final Map entityModels = Collections.synchronizedMap(new WeakHashMap<>()); @@ -94,23 +95,18 @@ implements GenericWorld< } public void render(ShapeRenderHelper renderer) { - for (ChunkRender chunk : getChunks()) { - chunk.render(renderer); - } - + getChunks().forEach(chunk -> chunk.render(renderer)); renderEntities(renderer); } private void renderEntities(ShapeRenderHelper renderer) { FaceCulling.push(false); - for (ChunkRender chunk : getChunks()) { - chunk.getData().forEachEntity(entity -> { - renderer.pushTransform().translate(entity.getPosition()); - getEntityRenderable(entity).render(renderer); - renderer.popTransform(); - }); - } + getData().forEachEntity(entity -> { + renderer.pushTransform().translate(entity.getPosition()); + getEntityRenderable(entity).render(renderer); + renderer.popTransform(); + }); FaceCulling.pop(); } diff --git a/src/main/java/ru/windcorp/progressia/common/world/PacketRevokeChunk.java b/src/main/java/ru/windcorp/progressia/common/world/PacketRevokeChunk.java new file mode 100644 index 0000000..e923259 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/world/PacketRevokeChunk.java @@ -0,0 +1,56 @@ +package ru.windcorp.progressia.common.world; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +import glm.vec._3.i.Vec3i; + +public class PacketRevokeChunk extends PacketChunkChange { + + private final Vec3i position = new Vec3i(); + + public PacketRevokeChunk() { + this("Core:RevokeChunk"); + } + + protected PacketRevokeChunk(String id) { + super(id); + } + + public void set(Vec3i chunkPos) { + this.position.set(chunkPos.x, chunkPos.y, chunkPos.z); + } + + @Override + public void read(DataInput input) throws IOException { + this.position.set(input.readInt(), input.readInt(), input.readInt()); + } + + @Override + public void write(DataOutput output) throws IOException { + output.writeInt(this.position.x); + output.writeInt(this.position.y); + output.writeInt(this.position.z); + } + + @Override + public void apply(WorldData world) { + synchronized (world) { + ChunkData chunk = world.getChunk(position); + if (chunk != null) { + world.removeChunk(chunk); + } + } + } + + @Override + public void getAffectedChunk(Vec3i output) { + output.set(getPosition().x, getPosition().y, getPosition().z); + } + + public Vec3i getPosition() { + return position; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/world/PacketLoadChunk.java b/src/main/java/ru/windcorp/progressia/common/world/PacketSendChunk.java similarity index 90% rename from src/main/java/ru/windcorp/progressia/common/world/PacketLoadChunk.java rename to src/main/java/ru/windcorp/progressia/common/world/PacketSendChunk.java index 74a9e3b..a0fe418 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/PacketLoadChunk.java +++ b/src/main/java/ru/windcorp/progressia/common/world/PacketSendChunk.java @@ -9,12 +9,16 @@ import ru.windcorp.progressia.common.io.ChunkIO; import ru.windcorp.progressia.common.util.DataBuffer; import ru.windcorp.progressia.common.util.crash.CrashReports; -public class PacketLoadChunk extends PacketChunkChange { +public class PacketSendChunk extends PacketChunkChange { private final DataBuffer data = new DataBuffer(); private final Vec3i position = new Vec3i(); + + public PacketSendChunk() { + this("Core:SendChunk"); + } - public PacketLoadChunk(String id) { + protected PacketSendChunk(String id) { super(id); } diff --git a/src/main/java/ru/windcorp/progressia/common/world/WorldData.java b/src/main/java/ru/windcorp/progressia/common/world/WorldData.java index 01b7c1b..d96eaca 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/WorldData.java +++ b/src/main/java/ru/windcorp/progressia/common/world/WorldData.java @@ -43,7 +43,7 @@ implements GenericWorld< TileDataStack, ChunkData, EntityData ->{ +> { private final ChunkMap chunksByPos = new LongBasedChunkMap<>( new TSynchronizedLongObjectMap<>(new TLongObjectHashMap<>(), this) @@ -87,7 +87,7 @@ implements GenericWorld< } public void tmp_generate() { - final int size = 10; + final int size = 1; Vec3i cursor = new Vec3i(0, 0, 0); for (cursor.x = -(size / 2); cursor.x <= (size / 2); ++cursor.x) { diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkSets.java b/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkSets.java new file mode 100644 index 0000000..ba959cc --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/ChunkSets.java @@ -0,0 +1,22 @@ +package ru.windcorp.progressia.common.world.generic; + +import gnu.trove.impl.sync.TSynchronizedLongSet; +import gnu.trove.set.hash.TLongHashSet; + +public class ChunkSets { + + public static ChunkSet newHashSet() { + return new LongBasedChunkSet(new TLongHashSet()); + } + + public static ChunkSet newSyncHashSet(Object mutex) { + return new LongBasedChunkSet(new TSynchronizedLongSet(new TLongHashSet(), mutex)); + } + + public static ChunkSet newSyncHashSet() { + return new LongBasedChunkSet(new TSynchronizedLongSet(new TLongHashSet())); + } + + private ChunkSets() {} + +} diff --git a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericWorld.java b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericWorld.java index 79746ed..54d13af 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/generic/GenericWorld.java +++ b/src/main/java/ru/windcorp/progressia/common/world/generic/GenericWorld.java @@ -118,7 +118,9 @@ public interface GenericWorld< */ default void forEachEntity(Consumer action) { - getEntities().forEach(action); + synchronized (this) { // TODO HORRIBLY MUTILATE THE CORPSE OF TROVE4J so that gnu.trove.impl.sync.SynchronizedCollection.forEach is synchronized + getEntities().forEach(action); + } } default void forEachEntityIn(Vec3i min, Vec3i max, Consumer action) { diff --git a/src/main/java/ru/windcorp/progressia/server/ChunkLoadManager.java b/src/main/java/ru/windcorp/progressia/server/ChunkLoadManager.java deleted file mode 100644 index 1b2c539..0000000 --- a/src/main/java/ru/windcorp/progressia/server/ChunkLoadManager.java +++ /dev/null @@ -1,83 +0,0 @@ -package ru.windcorp.progressia.server; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; - -import glm.vec._3.i.Vec3i; -import gnu.trove.set.hash.TLongHashSet; -import ru.windcorp.progressia.common.world.ChunkData; -import ru.windcorp.progressia.common.world.generic.ChunkSet; -import ru.windcorp.progressia.common.world.generic.LongBasedChunkSet; -import ru.windcorp.progressia.test.TestContent; - -public class ChunkLoadManager { - - private final Server server; - - private final Collection> allChunkLoaders = - Collections.synchronizedCollection(new ArrayList<>()); - - private final ChunkSet requested = new LongBasedChunkSet(new TLongHashSet()); - private final ChunkSet toLoad = new LongBasedChunkSet(new TLongHashSet()); - private final ChunkSet toUnload = new LongBasedChunkSet(new TLongHashSet()); - - public ChunkLoadManager(Server server) { - this.server = server; - allChunkLoaders.add(server.getPlayerManager().getPlayers()); - } - - public void tick() { - gatherRequests(); - updateQueues(); - processQueues(); - } - - private void gatherRequests() { - requested.clear(); - - allChunkLoaders.forEach(collection -> { - collection.forEach(this::gatherRequests); - }); - } - - private void gatherRequests(ChunkLoader loader) { - loader.requestChunksToLoad(requested::add); - } - - private void updateQueues() { - ChunkSet loaded = getServer().getWorld().getData().getLoadedChunks(); - - toLoad.clear(); - toLoad.addAll(requested); - toLoad.removeAll(loaded); - - toUnload.clear(); - toUnload.addAll(loaded); - toUnload.removeAll(requested); - } - - private void processQueues() { - toUnload.forEach(this::unloadChunk); - toLoad.forEach(this::loadChunk); - } - - public Server getServer() { - return server; - } - - public void loadChunk(Vec3i pos) { - - ChunkData chunk = new ChunkData(pos, getServer().getWorld().getData()); - TestContent.generateChunk(chunk); - getServer().getWorld().getData().addChunk(chunk); - - } - - public void unloadChunk(Vec3i pos) { - - getServer().getWorld().getData().removeChunk(getServer().getWorld().getData().getChunk(pos)); - - } - -} diff --git a/src/main/java/ru/windcorp/progressia/server/ChunkManager.java b/src/main/java/ru/windcorp/progressia/server/ChunkManager.java new file mode 100644 index 0000000..10a1c38 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/server/ChunkManager.java @@ -0,0 +1,180 @@ +package ru.windcorp.progressia.server; + +import java.util.Collections; +import java.util.Map; +import java.util.WeakHashMap; + +import org.apache.logging.log4j.LogManager; + +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.world.ChunkData; +import ru.windcorp.progressia.common.world.WorldData; +import ru.windcorp.progressia.common.world.generic.ChunkSet; +import ru.windcorp.progressia.common.world.generic.ChunkSets; +import ru.windcorp.progressia.test.TestChunkSender; +import ru.windcorp.progressia.test.TestContent; + +public class ChunkManager { + + private class PlayerVision { + + private final ChunkSet visible = ChunkSets.newSyncHashSet(); + private final ChunkSet requested = ChunkSets.newHashSet(); + private final ChunkSet toSend = ChunkSets.newHashSet(); + private final ChunkSet toRevoke = ChunkSets.newHashSet(); + + public boolean isChunkVisible(Vec3i chunkPos) { + return visible.contains(chunkPos); + } + + public void gatherRequests(Player player) { + requested.clear(); + player.requestChunksToLoad(requested::add); + } + + public void updateQueues(Player player) { + toSend.clear(); + toSend.addAll(requested); + toSend.removeAll(visible); + toSend.retainAll(loaded); + + toRevoke.clear(); + toRevoke.addAll(visible); + toRevoke.removeIf(v -> loaded.contains(v) && requested.contains(v)); + } + + public void processQueues(Player player) { + toRevoke.forEach(chunkPos -> revokeChunk(player, chunkPos)); + toRevoke.clear(); + + toSend.forEach(chunkPos -> sendChunk(player, chunkPos)); + toSend.clear(); + } + + } + + private final Server server; + + private final ChunkSet loaded; + private final ChunkSet requested = ChunkSets.newHashSet(); + private final ChunkSet toLoad = ChunkSets.newHashSet(); + private final ChunkSet toUnload = ChunkSets.newHashSet(); + + // TODO replace with a normal Map managed by some sort of PlayerListener, weak maps are weak + private final Map visions = Collections.synchronizedMap(new WeakHashMap<>()); + + public ChunkManager(Server server) { + this.server = server; + this.loaded = server.getWorld().getData().getLoadedChunks(); + } + + public void tick() { + synchronized (getServer().getWorld().getData()) { + synchronized (visions) { + gatherRequests(); + updateQueues(); + processQueues(); + } + } + } + + private void gatherRequests() { + requested.clear(); + + server.getPlayerManager().getPlayers().forEach(p -> { + PlayerVision vision = getVision(p, true); + vision.gatherRequests(p); + requested.addAll(vision.requested); + }); + } + + private void updateQueues() { + toLoad.clear(); + toLoad.addAll(requested); + toLoad.removeAll(loaded); + + toUnload.clear(); + toUnload.addAll(loaded); + toUnload.removeAll(requested); + + visions.forEach((p, v) -> { + v.updateQueues(p); + }); + } + + private void processQueues() { + toUnload.forEach(this::unloadChunk); + toUnload.clear(); + toLoad.forEach(this::loadChunk); + toLoad.clear(); + + visions.forEach((p, v) -> { + v.processQueues(p); + }); + } + + private PlayerVision getVision(Player player, boolean createIfMissing) { + return createIfMissing ? visions.computeIfAbsent(player, k -> new PlayerVision()) : visions.get(player); + } + + public void loadChunk(Vec3i chunkPos) { + + LogManager.getLogger().info("Loading {} {} {}", chunkPos.x, chunkPos.y, chunkPos.z); + + WorldData world = getServer().getWorld().getData(); + + ChunkData chunk = new ChunkData(chunkPos, world); + TestContent.generateChunk(chunk); + world.addChunk(chunk); + + } + + public void unloadChunk(Vec3i chunkPos) { + + LogManager.getLogger().info("Unloading {} {} {}", chunkPos.x, chunkPos.y, chunkPos.z); + + WorldData world = getServer().getWorld().getData(); + + ChunkData chunk = world.getChunk(chunkPos); + if (chunk == null) { + throw new IllegalStateException(String.format( + "Chunk (%d; %d; %d) not loaded, cannot unload", + chunkPos.x, chunkPos.y, chunkPos.z + )); + } + world.removeChunk(chunk); + + } + + public void sendChunk(Player player, Vec3i chunkPos) { + LogManager.getLogger().info("Sending {} {} {}", chunkPos.x, chunkPos.y, chunkPos.z); + TestChunkSender.sendChunk(server, player.getClient(), chunkPos); + + getVision(player, true).visible.add(chunkPos); + } + + public void revokeChunk(Player player, Vec3i chunkPos) { + LogManager.getLogger().info("Revoking {} {} {}", chunkPos.x, chunkPos.y, chunkPos.z); + TestChunkSender.revokeChunk(player.getClient(), chunkPos); + + PlayerVision vision = getVision(player, false); + if (vision != null) { + vision.visible.remove(chunkPos); + } + } + + public boolean isChunkVisible(Vec3i chunkPos, Player player) { + PlayerVision vision = getVision(player, false); + + if (vision == null) { + return false; + } + + return vision.isChunkVisible(chunkPos); + } + + public Server getServer() { + return server; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/server/Player.java b/src/main/java/ru/windcorp/progressia/server/Player.java index 8a6001e..2e4da82 100644 --- a/src/main/java/ru/windcorp/progressia/server/Player.java +++ b/src/main/java/ru/windcorp/progressia/server/Player.java @@ -18,6 +18,8 @@ public class Player extends PlayerData implements ChunkLoader { super(entity); this.server = server; this.client = client; + + client.setPlayer(this); } public Server getServer() { @@ -43,6 +45,7 @@ public class Player extends PlayerData implements ChunkLoader { for (cursor.y = -iRadius; cursor.y <= +iRadius; ++cursor.y) { for (cursor.z = -iRadius; cursor.z <= +iRadius; ++cursor.z) { if (cursor.x * cursor.x + cursor.y * cursor.y + cursor.z * cursor.z <= radius) { + cursor.add(start); chunkConsumer.accept(cursor); cursor.sub(start); diff --git a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java index d32b7ea..b1a6425 100644 --- a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java +++ b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.test.TestContent; @@ -29,7 +31,13 @@ public class PlayerManager { public EntityData conjurePlayerEntity(String login) { // TODO Live up to the name if (TestContent.PLAYER_LOGIN.equals(login)) { - // TODO load appropriate chunks + + Vec3i chunkPos = Vectors.ZERO_3i; + + if (getServer().getWorld().getChunk(chunkPos) == null) { + getServer().getChunkManager().loadChunk(chunkPos); + } + return getServer().getWorld().getData().getEntity(TestContent.PLAYER_ENTITY_ID); } else { CrashReports.report(null, "Unknown login %s, javahorse stupid", login); diff --git a/src/main/java/ru/windcorp/progressia/server/Server.java b/src/main/java/ru/windcorp/progressia/server/Server.java index ac59f00..158639a 100644 --- a/src/main/java/ru/windcorp/progressia/server/Server.java +++ b/src/main/java/ru/windcorp/progressia/server/Server.java @@ -29,8 +29,9 @@ public class Server { private final ServerThread serverThread; - private final ClientManager clientManager = new ClientManager(this); - private final PlayerManager playerManager = new PlayerManager(this); + private final ClientManager clientManager; + private final PlayerManager playerManager; + private final ChunkManager chunkManager; private final TaskQueue taskQueue = new TaskQueue(this::isServerThread); @@ -39,8 +40,13 @@ public class Server { public Server(WorldData world) { this.world = new WorldLogic(world, this); this.serverThread = new ServerThread(this); + + this.clientManager = new ClientManager(this); + this.playerManager = new PlayerManager(this); + this.chunkManager = new ChunkManager(this); schedule(this::scheduleChunkTicks); + schedule(chunkManager::tick); } /** @@ -64,6 +70,10 @@ public class Server { return playerManager; } + public ChunkManager getChunkManager() { + return chunkManager; + } + /** * Checks if this thread is the main thread of this server. * @return {@code true} iff the invocation occurs in server main thread @@ -160,7 +170,7 @@ public class Server { } public float getLoadDistance(Player player) { - return Units.get(100.0f, "m"); + return Units.get(10.0f, "m"); } /** diff --git a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java index 54510ad..65b3221 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java @@ -1,6 +1,5 @@ package ru.windcorp.progressia.server.comms; -import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.concurrent.atomic.AtomicInteger; @@ -11,10 +10,6 @@ import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; import ru.windcorp.progressia.common.comms.CommsChannel.State; import ru.windcorp.progressia.common.comms.packets.Packet; -import ru.windcorp.progressia.common.io.ChunkIO; -import ru.windcorp.progressia.common.util.crash.CrashReports; -import ru.windcorp.progressia.common.world.ChunkData; -import ru.windcorp.progressia.common.world.PacketLoadChunk; import ru.windcorp.progressia.common.world.PacketSetLocalPlayer; import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.server.Player; @@ -62,30 +57,16 @@ public class ClientManager { private void addClientPlayer(ClientPlayer client) { String login = client.getLogin(); - EntityData entity = getServer().getPlayerManager().conjurePlayerEntity(login); - Player player = new Player(entity, getServer(), client); - - getServer().getPlayerManager().getPlayers().add(player); - - for (ChunkData chunk : server.getWorld().getData().getChunks()) { - if (!client.canSeeChunk(chunk.getPosition())) { - continue; - } + EntityData entity; + synchronized (getServer().getWorld().getData()) { + entity = getServer().getPlayerManager().conjurePlayerEntity(login); - PacketLoadChunk packet = new PacketLoadChunk("Core:LoadChunk"); - packet.getPosition().set( - chunk.getPosition().x, - chunk.getPosition().y, - chunk.getPosition().z - ); + Player player = new Player(entity, getServer(), client); - try { - ChunkIO.save(chunk, packet.getData().getOutputStream()); - } catch (IOException e) { - CrashReports.report(e, "ClientManager fjcked up. javahorse stupid"); - } - client.sendPacket(packet); + getServer().getPlayerManager().getPlayers().add(player); + + getServer().getChunkManager().sendChunk(player, entity.getChunkCoords(null)); } PacketSetLocalPlayer packet = new PacketSetLocalPlayer(); @@ -119,7 +100,7 @@ public class ClientManager { getClients().forEach(c -> { if (c.getState() != State.CONNECTED) return; if (!(c instanceof ClientPlayer)) return; - if (!((ClientPlayer) c).canSeeChunk(chunkPos)) return; + if (!((ClientPlayer) c).isChunkVisible(chunkPos)) return; c.sendPacket(packet); }); } @@ -133,7 +114,7 @@ public class ClientManager { getClients().forEach(c -> { if (c.getState() != State.CONNECTED) return; if (!(c instanceof ClientPlayer)) return; - if (!((ClientPlayer) c).canSeeEntity(entityId)) return; + if (!((ClientPlayer) c).isChunkVisible(entityId)) return; c.sendPacket(packet); }); } diff --git a/src/main/java/ru/windcorp/progressia/server/comms/ClientPlayer.java b/src/main/java/ru/windcorp/progressia/server/comms/ClientPlayer.java index d8271a9..bf7ac28 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientPlayer.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientPlayer.java @@ -1,20 +1,32 @@ package ru.windcorp.progressia.server.comms; import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.server.Player; -public abstract class ClientPlayer extends Client { +public abstract class ClientPlayer extends ClientChat { + + private Player player; public ClientPlayer(int id) { super(id); } - public abstract String getLogin(); - - public boolean canSeeChunk(Vec3i chunkPos) { - return true; + public Player getPlayer() { + return player; } - public boolean canSeeEntity(long entityId) { + public void setPlayer(Player player) { + this.player = player; + } + + public abstract String getLogin(); + + public boolean isChunkVisible(Vec3i chunkPos) { + if (player == null) return false; + return player.getServer().getChunkManager().isChunkVisible(chunkPos, player); + } + + public boolean isChunkVisible(long entityId) { return true; } diff --git a/src/main/java/ru/windcorp/progressia/server/world/WorldLogic.java b/src/main/java/ru/windcorp/progressia/server/world/WorldLogic.java index 0142c08..00aae35 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/WorldLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/WorldLogic.java @@ -15,7 +15,6 @@ import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.block.BlockLogic; import ru.windcorp.progressia.server.world.tile.TileLogic; import ru.windcorp.progressia.server.world.tile.TileLogicStack; -import ru.windcorp.progressia.test.TestChunkSender; public class WorldLogic implements GenericWorld< @@ -48,7 +47,6 @@ implements GenericWorld< }); data.addListener(ChunkDataListeners.createAdder(new UpdateTriggerer(server))); - data.addListener(new TestChunkSender(server)); } @Override diff --git a/src/main/java/ru/windcorp/progressia/test/TestChunkSender.java b/src/main/java/ru/windcorp/progressia/test/TestChunkSender.java index b267206..815fb6d 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestChunkSender.java +++ b/src/main/java/ru/windcorp/progressia/test/TestChunkSender.java @@ -2,34 +2,29 @@ package ru.windcorp.progressia.test; import java.io.IOException; -import glm.Glm; +import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.io.ChunkIO; import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.world.ChunkData; -import ru.windcorp.progressia.common.world.PacketLoadChunk; -import ru.windcorp.progressia.common.world.PacketSetLocalPlayer; -import ru.windcorp.progressia.common.world.WorldData; -import ru.windcorp.progressia.common.world.WorldDataListener; -import ru.windcorp.progressia.common.world.entity.EntityData; +import ru.windcorp.progressia.common.world.PacketRevokeChunk; +import ru.windcorp.progressia.common.world.PacketSendChunk; import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.comms.ClientPlayer; -public class TestChunkSender implements WorldDataListener { +public class TestChunkSender { - private final Server server; - - public TestChunkSender(Server server) { - this.server = server; - } - - @Override - public void onChunkLoaded(WorldData world, ChunkData chunk) { - PacketLoadChunk packet = new PacketLoadChunk("Core:LoadChunk"); + public static void sendChunk(Server server, ClientPlayer receiver, Vec3i chunkPos) { + ChunkData chunk = server.getWorld().getData().getChunk(chunkPos); - packet.getPosition().set( - chunk.getPosition().x, - chunk.getPosition().y, - chunk.getPosition().z - ); + if (chunk == null) { + throw new IllegalStateException(String.format( + "Chunk (%d; %d; %d) is not loaded, cannot send", + chunkPos.x, chunkPos.y, chunkPos.z + )); + } + + PacketSendChunk packet = new PacketSendChunk(); + packet.getPosition().set(chunkPos.x, chunkPos.y, chunkPos.z); try { ChunkIO.save(chunk, packet.getData().getOutputStream()); @@ -37,22 +32,13 @@ public class TestChunkSender implements WorldDataListener { CrashReports.report(e, "TestChunkSender fjcked up. javahorse stupid"); } - server.getClientManager().broadcastLocal(packet, chunk.getPosition()); - - tmp_sendPlayerIfPossible(world, chunk); + receiver.sendPacket(packet); } - private void tmp_sendPlayerIfPossible(WorldData world, ChunkData chunk) { - EntityData e = world.getEntity(TestContent.PLAYER_ENTITY_ID); - if (e == null) return; - - if (Glm.equals(e.getChunkCoords(null), chunk.getPosition())) { - System.out.printf("TestChunkSender: player found in (%d; %d; %d)\n", e.getChunkCoords(null).x, e.getChunkCoords(null).y, e.getChunkCoords(null).z); - - PacketSetLocalPlayer packet = new PacketSetLocalPlayer(); - packet.set(e.getEntityId()); - server.getClientManager().broadcastToAllPlayers(packet); - } + public static void revokeChunk(ClientPlayer receiver, Vec3i chunkPos) { + PacketRevokeChunk packet = new PacketRevokeChunk(); + packet.set(chunkPos); + receiver.sendPacket(packet); } } diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index 6f64561..517df5f 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -346,10 +346,10 @@ public class TestContent { )); chunk.getEntities().add(player); - EntityData statie = EntityDataRegistry.getInstance().create("Test:Statie"); - statie.setEntityId(STATIE_ENTITY_ID); - statie.setPosition(new Vec3(0, 15, 16)); - chunk.getEntities().add(statie); +// EntityData statie = EntityDataRegistry.getInstance().create("Test:Statie"); +// statie.setEntityId(STATIE_ENTITY_ID); +// statie.setPosition(new Vec3(0, 15, 16)); +// chunk.getEntities().add(statie); } } diff --git a/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java b/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java index 74fc33c..1c67c7c 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java +++ b/src/main/java/ru/windcorp/progressia/test/TestPlayerControls.java @@ -17,6 +17,7 @@ import ru.windcorp.progressia.client.graphics.world.LocalPlayer; import ru.windcorp.progressia.common.Units; import ru.windcorp.progressia.common.util.FloatMathUtils; import ru.windcorp.progressia.common.world.entity.EntityData; +import ru.windcorp.progressia.server.ServerState; public class TestPlayerControls { @@ -96,6 +97,13 @@ public class TestPlayerControls { } player.getVelocity().set(change); + + // THIS IS TERRIBLE TEST + EntityData serverEntity = ServerState.getInstance().getWorld().getData().getEntity(TestContent.PLAYER_ENTITY_ID); + if (serverEntity != null) { + serverEntity.setPosition(player.getPosition()); + } + } public void handleInput(Input input) {