diff --git a/src/main/java/com/flowpowered/api/component/AbstractObserver.java b/src/main/java/com/flowpowered/api/component/AbstractObserver.java index 5a22859..a9f1acd 100644 --- a/src/main/java/com/flowpowered/api/component/AbstractObserver.java +++ b/src/main/java/com/flowpowered/api/component/AbstractObserver.java @@ -185,6 +185,10 @@ protected void updateObserver() { observingChunks.set(observing); } + public Set getObservingChunks() { + return observingChunks.get(); + } + public abstract void copySnapshot(); protected abstract void startObserving(ImmutableSet observing); diff --git a/src/main/java/com/flowpowered/api/component/PlayerObserveChunksComponent.java b/src/main/java/com/flowpowered/api/component/entity/PlayerObserveChunksComponent.java similarity index 50% rename from src/main/java/com/flowpowered/api/component/PlayerObserveChunksComponent.java rename to src/main/java/com/flowpowered/api/component/entity/PlayerObserveChunksComponent.java index 19391db..d909389 100644 --- a/src/main/java/com/flowpowered/api/component/PlayerObserveChunksComponent.java +++ b/src/main/java/com/flowpowered/api/component/entity/PlayerObserveChunksComponent.java @@ -21,18 +21,52 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.flowpowered.api.component; +package com.flowpowered.api.component.entity; + +import java.util.Set; + +import com.flowpowered.api.component.Component; +import com.flowpowered.api.entity.Entity; +import com.flowpowered.api.event.EntityStartObservingChunksEvent; +import com.flowpowered.api.event.EntityStopObservingChunksEvent; +import com.flowpowered.api.geo.reference.ChunkReference; +import com.flowpowered.api.player.Player; +import com.flowpowered.events.EventHandler; public class PlayerObserveChunksComponent extends Component { + private Player controller; @Override public void onTick(float dt) { - throw new UnsupportedOperationException("Not supported yet."); } @Override public boolean canTick() { - throw new UnsupportedOperationException("Not supported yet."); + return false; + } + + public void setController(Player player) { + Set chunks = ((Entity) getOwner()).getObserver().getObservingChunks(); + if (this.controller != null) { + controller.getNetwork().removeChunks(chunks); + } + this.controller = player; + if (this.controller != null) { + controller.getNetwork().addChunks(chunks); + } } + @EventHandler + public void onObserve(EntityStartObservingChunksEvent e) { + if (e.getObserver().equals(getOwner()) && controller != null) { + controller.getNetwork().addChunks(e.getObserved()); + } + } + + @EventHandler + public void onStopObserve(EntityStopObservingChunksEvent e) { + if (e.getObserver().equals(getOwner()) && controller != null) { + controller.getNetwork().removeChunks(e.getObserved()); + } + } } diff --git a/src/main/java/com/flowpowered/api/player/PlayerNetwork.java b/src/main/java/com/flowpowered/api/player/PlayerNetwork.java index 2a47c44..a16249b 100644 --- a/src/main/java/com/flowpowered/api/player/PlayerNetwork.java +++ b/src/main/java/com/flowpowered/api/player/PlayerNetwork.java @@ -27,8 +27,8 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; import com.flowpowered.api.Client; import com.flowpowered.api.geo.LoadOption; @@ -58,8 +58,8 @@ public class PlayerNetwork { * Chunks that have been sent to the client */ private final Set activeChunks = new LinkedHashSet<>(); - private final Set chunkSendQueue = new LinkedHashSet<>(); - private final Set chunkFreeQueue = new LinkedHashSet<>(); + private final ConcurrentLinkedQueue chunkSendQueue = new ConcurrentLinkedQueue<>(); + private final ConcurrentLinkedQueue chunkFreeQueue = new ConcurrentLinkedQueue<>(); protected volatile Transform previousTransform = Transform.INVALID; private final AtomicReference rm = new AtomicReference<>(NullRepositionManager.INSTANCE); @@ -92,17 +92,15 @@ public void setRepositionManager(RepositionManager rm) { } } - public void addChunks(Set chunks) { - chunkSendQueue.addAll(chunks.stream().map(ChunkReference::new).collect( - Collectors.toList())); + public void addChunks(Set chunks) { + chunkSendQueue.addAll(chunks); } - public void removeChunks(Set toRemove) { - for (Chunk chunk : toRemove) { - ChunkReference ref = new ChunkReference(chunk); + public void removeChunks(Set toRemove) { + toRemove.stream().forEach((ref) -> { chunkFreeQueue.add(ref); chunks.remove(ref); - } + }); } public void preSnapshotRun(Transform transform) { @@ -117,6 +115,9 @@ public void preSnapshotRun(Transform transform) { // We will sync old chunks, but not new ones Set toSync = new LinkedHashSet<>(activeChunks); + sendPositionUpdates(transform); + previousTransform = transform; + // Now send new chunks int chunksSentThisTick = 0; @@ -135,8 +136,7 @@ public void preSnapshotRun(Transform transform) { previousTransform = transform; // Update the active chunks - for (Iterator it = toSync.iterator(); it.hasNext();) { - ChunkReference ref = it.next(); + for (ChunkReference ref : toSync) { Chunk chunk = ref.get(); // If it was unloaded, we have to free it // We don't remove it from our chunks though diff --git a/src/main/java/com/flowpowered/engine/FlowClientImpl.java b/src/main/java/com/flowpowered/engine/FlowClientImpl.java index 10dd176..1892d1e 100644 --- a/src/main/java/com/flowpowered/engine/FlowClientImpl.java +++ b/src/main/java/com/flowpowered/engine/FlowClientImpl.java @@ -59,7 +59,7 @@ public void onAdd() { MaterialRegistry.setupClient(); } // TEST CODE - FlowServerWorld world = new FlowServerWorld(engine, "TestWorld", null); + FlowServerWorld world = new FlowServerWorld(engine, "fallback", null); engine.getWorldManager().addWorld(world); world.getThread().start(); client.connect(new InetSocketAddress(engine.getArgs().server, engine.getArgs().port)); diff --git a/src/main/java/com/flowpowered/engine/network/FlowNetworkClient.java b/src/main/java/com/flowpowered/engine/network/FlowNetworkClient.java index 9665a78..00f2b7c 100644 --- a/src/main/java/com/flowpowered/engine/network/FlowNetworkClient.java +++ b/src/main/java/com/flowpowered/engine/network/FlowNetworkClient.java @@ -26,6 +26,7 @@ import java.util.concurrent.atomic.AtomicReference; import com.flowpowered.engine.FlowEngine; +import com.flowpowered.engine.player.FlowPlayer; import com.flowpowered.networking.NetworkClient; import com.flowpowered.networking.session.Session; @@ -44,6 +45,7 @@ public Session newSession(Channel c) { if (!session.compareAndSet(null, new FlowSession(engine, c))) { throw new IllegalStateException("Two sessions created on the client!"); } + session.get().setPlayer(new FlowPlayer(session.get(), "Flowy")); return session.get(); } diff --git a/src/main/java/com/flowpowered/engine/network/handler/ChunkDataHandler.java b/src/main/java/com/flowpowered/engine/network/handler/ChunkDataHandler.java index f28c90f..a8d757e 100644 --- a/src/main/java/com/flowpowered/engine/network/handler/ChunkDataHandler.java +++ b/src/main/java/com/flowpowered/engine/network/handler/ChunkDataHandler.java @@ -34,7 +34,7 @@ public class ChunkDataHandler extends FlowMessageHandler { public void handleClient(FlowSession session, ChunkDataMessage message) { FlowClient client = session.getEngine().get(FlowClient.class); // TODO: allow adding chunks to other worlds - FlowWorld world = (FlowWorld) client.getSession().getPlayer().getTransformProvider().getTransform().getPosition().getWorld().get(); + FlowWorld world = (FlowWorld) client.getTransform().getPosition().getWorld().refresh(session.getEngine().getWorldManager()); if (message.isUnload()) { world.setChunk(message.getX(), message.getY(), message.getZ(), null); } else {