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 6ab3852..1796977 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientManager.java @@ -5,6 +5,7 @@ import java.util.Collection; import java.util.Collections; import java.util.concurrent.atomic.AtomicInteger; +import glm.vec._3.i.Vec3i; import gnu.trove.TCollections; import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; @@ -68,6 +69,10 @@ public class ClientManager { getServer().getPlayerManager().getPlayers().add(player); for (ChunkData chunk : server.getWorld().getData().getChunks()) { + if (!client.canSeeChunk(chunk.getPosition())) { + continue; + } + PacketLoadChunk packet = new PacketLoadChunk("Core:LoadChunk"); packet.getPosition().set( chunk.getPosition().x, @@ -91,7 +96,11 @@ public class ClientManager { clientsById.remove(client.getId()); } - public void broadcastGamePacket(Packet packet) { + /** + * Sends the provided packet to all connected player clients. + * @param packet the packet to broadcast + */ + public void broadcastToAllPlayers(Packet packet) { getClients().forEach(c -> { if (c.getState() != State.CONNECTED) return; if (!(c instanceof ClientPlayer)) return; @@ -99,6 +108,34 @@ public class ClientManager { }); } + /** + * Sends the provided packet to all connected player clients that can see the chunk identified by {@code chunkPos}. + * @param packet the packet to broadcast + * @param chunkPos the chunk coordinates of the chunk that must be visible + */ + public void broadcastLocal(Packet packet, Vec3i chunkPos) { + getClients().forEach(c -> { + if (c.getState() != State.CONNECTED) return; + if (!(c instanceof ClientPlayer)) return; + if (!((ClientPlayer) c).canSeeChunk(chunkPos)) return; + c.sendPacket(packet); + }); + } + + /** + * Sends the provided packet to all connected player clients that can see the entity identified by {@code entityId}. + * @param packet the packet to broadcast + * @param entityId the ID of the entity that must be visible + */ + public void broadcastLocal(Packet packet, long entityId) { + getClients().forEach(c -> { + if (c.getState() != State.CONNECTED) return; + if (!(c instanceof ClientPlayer)) return; + if (!((ClientPlayer) c).canSeeEntity(entityId)) return; + c.sendPacket(packet); + }); + } + public Collection getClients() { return clients; } 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 3eb14e1..d49addd 100644 --- a/src/main/java/ru/windcorp/progressia/server/comms/ClientPlayer.java +++ b/src/main/java/ru/windcorp/progressia/server/comms/ClientPlayer.java @@ -1,5 +1,8 @@ package ru.windcorp.progressia.server.comms; +import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.test.TestContent; + public abstract class ClientPlayer extends Client { public ClientPlayer(int id) { @@ -7,5 +10,13 @@ public abstract class ClientPlayer extends Client { } public abstract String getLogin(); + + public boolean canSeeChunk(Vec3i chunkPos) { + return true; + } + + public boolean canSeeEntity(long entityId) { + return entityId == TestContent.PLAYER_ENTITY_ID; + } } diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/AddTile.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/AddTile.java index 4402999..28d4558 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/AddTile.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/AddTile.java @@ -45,6 +45,12 @@ class AddTile extends CachedWorldChange { Coordinates.convertInWorldToChunk(blockInWorld, output); } + @Override + protected Vec3i getAffectedChunk(Vec3i output) { + getRelevantChunk(output); + return output; + } + @Override public void dispose() { super.dispose(); diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedWorldChange.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedWorldChange.java index be587f8..ee965c7 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedWorldChange.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/CachedWorldChange.java @@ -2,7 +2,9 @@ package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; +import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.common.comms.packets.PacketWorldChange; +import ru.windcorp.progressia.common.util.Vectors; import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.server.Server; @@ -24,7 +26,21 @@ public abstract class CachedWorldChange extends CachedChange { @Override public void affect(Server server) { affectCommon(server.getWorld().getData()); - server.getClientManager().broadcastGamePacket(packet); + + Vec3i v = Vectors.grab3i(); + Vec3i chunkPos = getAffectedChunk(v); + + if (chunkPos == null) { + server.getClientManager().broadcastToAllPlayers(packet); + } else { + server.getClientManager().broadcastLocal(packet, chunkPos); + } + + Vectors.release(chunkPos); + } + + protected Vec3i getAffectedChunk(Vec3i output) { + return null; } /** diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/ChangeEntity.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/ChangeEntity.java index f671914..651bc83 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/ChangeEntity.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/ChangeEntity.java @@ -50,7 +50,7 @@ class ChangeEntity extends CachedChange { CrashReports.report(e, "Could not write entity %s", entity); } - server.getClientManager().broadcastGamePacket(packet); + server.getClientManager().broadcastLocal(packet, entity.getChunkCoords(null)); } @Override diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/RemoveTile.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/RemoveTile.java index 7601a83..d33f80f 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/RemoveTile.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/RemoveTile.java @@ -40,5 +40,11 @@ class RemoveTile extends CachedWorldChange { public void getRelevantChunk(Vec3i output) { Coordinates.convertInWorldToChunk(blockInWorld, output); } + + @Override + protected Vec3i getAffectedChunk(Vec3i output) { + getRelevantChunk(output); + return output; + } } \ No newline at end of file diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/SetBlock.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/SetBlock.java index f34694c..44329ac 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/SetBlock.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/SetBlock.java @@ -36,6 +36,12 @@ class SetBlock extends CachedWorldChange { Coordinates.convertInWorldToChunk(blockInWorld, output); } + @Override + protected Vec3i getAffectedChunk(Vec3i output) { + getRelevantChunk(output); + return output; + } + @Override public void dispose() { super.dispose(); diff --git a/src/main/java/ru/windcorp/progressia/test/TestChunkSender.java b/src/main/java/ru/windcorp/progressia/test/TestChunkSender.java index 672db8f..801c3d8 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestChunkSender.java +++ b/src/main/java/ru/windcorp/progressia/test/TestChunkSender.java @@ -37,7 +37,7 @@ public class TestChunkSender implements WorldDataListener { CrashReports.report(e, "TestChunkSender fjcked up. javahorse stupid"); } - server.getClientManager().broadcastGamePacket(packet); + server.getClientManager().broadcastLocal(packet, chunk.getPosition()); tmp_sendPlayerIfPossible(world, chunk); } @@ -48,7 +48,7 @@ public class TestChunkSender implements WorldDataListener { 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); - server.getClientManager().broadcastGamePacket(new PacketSetLocalPlayer(e.getEntityId())); + server.getClientManager().broadcastToAllPlayers(new PacketSetLocalPlayer(e.getEntityId())); } }