First implementation of dynamic chunk loading. Super buggy, WIP

This commit is contained in:
OLEGSHA 2020-12-28 11:26:44 +03:00
parent eaea6fdad9
commit cde854346c
18 changed files with 365 additions and 182 deletions

View File

@ -107,15 +107,15 @@ implements GenericChunk<
return data; return data;
} }
public void markForUpdate() { public synchronized void markForUpdate() {
this.needsUpdate = true; this.needsUpdate = true;
} }
public boolean needsUpdate() { public synchronized boolean needsUpdate() {
return needsUpdate; return needsUpdate;
} }
public void render(ShapeRenderHelper renderer) { public synchronized void render(ShapeRenderHelper renderer) {
if (model == null || needsUpdate()) { if (model == null || needsUpdate()) {
buildModel(); buildModel();
} }

View File

@ -49,7 +49,8 @@ implements GenericWorld<
private final WorldData data; private final WorldData data;
private final Map<ChunkData, ChunkRender> chunks = new HashMap<>(); private final Map<ChunkData, ChunkRender> chunks =
Collections.synchronizedMap(new HashMap<>());
private final Map<EntityData, EntityRenderable> entityModels = private final Map<EntityData, EntityRenderable> entityModels =
Collections.synchronizedMap(new WeakHashMap<>()); Collections.synchronizedMap(new WeakHashMap<>());
@ -94,23 +95,18 @@ implements GenericWorld<
} }
public void render(ShapeRenderHelper renderer) { public void render(ShapeRenderHelper renderer) {
for (ChunkRender chunk : getChunks()) { getChunks().forEach(chunk -> chunk.render(renderer));
chunk.render(renderer);
}
renderEntities(renderer); renderEntities(renderer);
} }
private void renderEntities(ShapeRenderHelper renderer) { private void renderEntities(ShapeRenderHelper renderer) {
FaceCulling.push(false); FaceCulling.push(false);
for (ChunkRender chunk : getChunks()) { getData().forEachEntity(entity -> {
chunk.getData().forEachEntity(entity -> { renderer.pushTransform().translate(entity.getPosition());
renderer.pushTransform().translate(entity.getPosition()); getEntityRenderable(entity).render(renderer);
getEntityRenderable(entity).render(renderer); renderer.popTransform();
renderer.popTransform(); });
});
}
FaceCulling.pop(); FaceCulling.pop();
} }

View File

@ -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;
}
}

View File

@ -9,12 +9,16 @@ import ru.windcorp.progressia.common.io.ChunkIO;
import ru.windcorp.progressia.common.util.DataBuffer; import ru.windcorp.progressia.common.util.DataBuffer;
import ru.windcorp.progressia.common.util.crash.CrashReports; 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 DataBuffer data = new DataBuffer();
private final Vec3i position = new Vec3i(); private final Vec3i position = new Vec3i();
public PacketSendChunk() {
this("Core:SendChunk");
}
public PacketLoadChunk(String id) { protected PacketSendChunk(String id) {
super(id); super(id);
} }

View File

@ -43,7 +43,7 @@ implements GenericWorld<
TileDataStack, TileDataStack,
ChunkData, ChunkData,
EntityData EntityData
>{ > {
private final ChunkMap<ChunkData> chunksByPos = new LongBasedChunkMap<>( private final ChunkMap<ChunkData> chunksByPos = new LongBasedChunkMap<>(
new TSynchronizedLongObjectMap<>(new TLongObjectHashMap<>(), this) new TSynchronizedLongObjectMap<>(new TLongObjectHashMap<>(), this)
@ -87,7 +87,7 @@ implements GenericWorld<
} }
public void tmp_generate() { public void tmp_generate() {
final int size = 10; final int size = 1;
Vec3i cursor = new Vec3i(0, 0, 0); Vec3i cursor = new Vec3i(0, 0, 0);
for (cursor.x = -(size / 2); cursor.x <= (size / 2); ++cursor.x) { for (cursor.x = -(size / 2); cursor.x <= (size / 2); ++cursor.x) {

View File

@ -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() {}
}

View File

@ -118,7 +118,9 @@ public interface GenericWorld<
*/ */
default void forEachEntity(Consumer<? super E> action) { default void forEachEntity(Consumer<? super E> 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<? super E> action) { default void forEachEntityIn(Vec3i min, Vec3i max, Consumer<? super E> action) {

View File

@ -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<Collection<? extends ChunkLoader>> 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));
}
}

View File

@ -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<Player, PlayerVision> 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;
}
}

View File

@ -18,6 +18,8 @@ public class Player extends PlayerData implements ChunkLoader {
super(entity); super(entity);
this.server = server; this.server = server;
this.client = client; this.client = client;
client.setPlayer(this);
} }
public Server getServer() { 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.y = -iRadius; cursor.y <= +iRadius; ++cursor.y) {
for (cursor.z = -iRadius; cursor.z <= +iRadius; ++cursor.z) { for (cursor.z = -iRadius; cursor.z <= +iRadius; ++cursor.z) {
if (cursor.x * cursor.x + cursor.y * cursor.y + cursor.z * cursor.z <= radius) { if (cursor.x * cursor.x + cursor.y * cursor.y + cursor.z * cursor.z <= radius) {
cursor.add(start); cursor.add(start);
chunkConsumer.accept(cursor); chunkConsumer.accept(cursor);
cursor.sub(start); cursor.sub(start);

View File

@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; 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.util.crash.CrashReports;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.test.TestContent; import ru.windcorp.progressia.test.TestContent;
@ -29,7 +31,13 @@ public class PlayerManager {
public EntityData conjurePlayerEntity(String login) { public EntityData conjurePlayerEntity(String login) {
// TODO Live up to the name // TODO Live up to the name
if (TestContent.PLAYER_LOGIN.equals(login)) { 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); return getServer().getWorld().getData().getEntity(TestContent.PLAYER_ENTITY_ID);
} else { } else {
CrashReports.report(null, "Unknown login %s, javahorse stupid", login); CrashReports.report(null, "Unknown login %s, javahorse stupid", login);

View File

@ -29,8 +29,9 @@ public class Server {
private final ServerThread serverThread; private final ServerThread serverThread;
private final ClientManager clientManager = new ClientManager(this); private final ClientManager clientManager;
private final PlayerManager playerManager = new PlayerManager(this); private final PlayerManager playerManager;
private final ChunkManager chunkManager;
private final TaskQueue taskQueue = new TaskQueue(this::isServerThread); private final TaskQueue taskQueue = new TaskQueue(this::isServerThread);
@ -39,8 +40,13 @@ public class Server {
public Server(WorldData world) { public Server(WorldData world) {
this.world = new WorldLogic(world, this); this.world = new WorldLogic(world, this);
this.serverThread = new ServerThread(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(this::scheduleChunkTicks);
schedule(chunkManager::tick);
} }
/** /**
@ -64,6 +70,10 @@ public class Server {
return playerManager; return playerManager;
} }
public ChunkManager getChunkManager() {
return chunkManager;
}
/** /**
* Checks if this thread is the main thread of this server. * Checks if this thread is the main thread of this server.
* @return {@code true} iff the invocation occurs in server main thread * @return {@code true} iff the invocation occurs in server main thread
@ -160,7 +170,7 @@ public class Server {
} }
public float getLoadDistance(Player player) { public float getLoadDistance(Player player) {
return Units.get(100.0f, "m"); return Units.get(10.0f, "m");
} }
/** /**

View File

@ -1,6 +1,5 @@
package ru.windcorp.progressia.server.comms; package ru.windcorp.progressia.server.comms;
import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -11,10 +10,6 @@ import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.map.hash.TIntObjectHashMap;
import ru.windcorp.progressia.common.comms.CommsChannel.State; import ru.windcorp.progressia.common.comms.CommsChannel.State;
import ru.windcorp.progressia.common.comms.packets.Packet; 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.PacketSetLocalPlayer;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.server.Player; import ru.windcorp.progressia.server.Player;
@ -62,30 +57,16 @@ public class ClientManager {
private void addClientPlayer(ClientPlayer client) { private void addClientPlayer(ClientPlayer client) {
String login = client.getLogin(); String login = client.getLogin();
EntityData entity = getServer().getPlayerManager().conjurePlayerEntity(login);
Player player = new Player(entity, getServer(), client); EntityData entity;
synchronized (getServer().getWorld().getData()) {
getServer().getPlayerManager().getPlayers().add(player); entity = getServer().getPlayerManager().conjurePlayerEntity(login);
for (ChunkData chunk : server.getWorld().getData().getChunks()) {
if (!client.canSeeChunk(chunk.getPosition())) {
continue;
}
PacketLoadChunk packet = new PacketLoadChunk("Core:LoadChunk"); Player player = new Player(entity, getServer(), client);
packet.getPosition().set(
chunk.getPosition().x,
chunk.getPosition().y,
chunk.getPosition().z
);
try { getServer().getPlayerManager().getPlayers().add(player);
ChunkIO.save(chunk, packet.getData().getOutputStream());
} catch (IOException e) { getServer().getChunkManager().sendChunk(player, entity.getChunkCoords(null));
CrashReports.report(e, "ClientManager fjcked up. javahorse stupid");
}
client.sendPacket(packet);
} }
PacketSetLocalPlayer packet = new PacketSetLocalPlayer(); PacketSetLocalPlayer packet = new PacketSetLocalPlayer();
@ -119,7 +100,7 @@ public class ClientManager {
getClients().forEach(c -> { getClients().forEach(c -> {
if (c.getState() != State.CONNECTED) return; if (c.getState() != State.CONNECTED) return;
if (!(c instanceof ClientPlayer)) return; if (!(c instanceof ClientPlayer)) return;
if (!((ClientPlayer) c).canSeeChunk(chunkPos)) return; if (!((ClientPlayer) c).isChunkVisible(chunkPos)) return;
c.sendPacket(packet); c.sendPacket(packet);
}); });
} }
@ -133,7 +114,7 @@ public class ClientManager {
getClients().forEach(c -> { getClients().forEach(c -> {
if (c.getState() != State.CONNECTED) return; if (c.getState() != State.CONNECTED) return;
if (!(c instanceof ClientPlayer)) return; if (!(c instanceof ClientPlayer)) return;
if (!((ClientPlayer) c).canSeeEntity(entityId)) return; if (!((ClientPlayer) c).isChunkVisible(entityId)) return;
c.sendPacket(packet); c.sendPacket(packet);
}); });
} }

View File

@ -1,20 +1,32 @@
package ru.windcorp.progressia.server.comms; package ru.windcorp.progressia.server.comms;
import glm.vec._3.i.Vec3i; 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) { public ClientPlayer(int id) {
super(id); super(id);
} }
public abstract String getLogin(); public Player getPlayer() {
return player;
public boolean canSeeChunk(Vec3i chunkPos) {
return true;
} }
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; return true;
} }

View File

@ -15,7 +15,6 @@ import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.world.block.BlockLogic; import ru.windcorp.progressia.server.world.block.BlockLogic;
import ru.windcorp.progressia.server.world.tile.TileLogic; import ru.windcorp.progressia.server.world.tile.TileLogic;
import ru.windcorp.progressia.server.world.tile.TileLogicStack; import ru.windcorp.progressia.server.world.tile.TileLogicStack;
import ru.windcorp.progressia.test.TestChunkSender;
public class WorldLogic public class WorldLogic
implements GenericWorld< implements GenericWorld<
@ -48,7 +47,6 @@ implements GenericWorld<
}); });
data.addListener(ChunkDataListeners.createAdder(new UpdateTriggerer(server))); data.addListener(ChunkDataListeners.createAdder(new UpdateTriggerer(server)));
data.addListener(new TestChunkSender(server));
} }
@Override @Override

View File

@ -2,34 +2,29 @@ package ru.windcorp.progressia.test;
import java.io.IOException; 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.io.ChunkIO;
import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.CrashReports;
import ru.windcorp.progressia.common.world.ChunkData; import ru.windcorp.progressia.common.world.ChunkData;
import ru.windcorp.progressia.common.world.PacketLoadChunk; import ru.windcorp.progressia.common.world.PacketRevokeChunk;
import ru.windcorp.progressia.common.world.PacketSetLocalPlayer; import ru.windcorp.progressia.common.world.PacketSendChunk;
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.server.Server; 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 static void sendChunk(Server server, ClientPlayer receiver, Vec3i chunkPos) {
ChunkData chunk = server.getWorld().getData().getChunk(chunkPos);
public TestChunkSender(Server server) {
this.server = server;
}
@Override
public void onChunkLoaded(WorldData world, ChunkData chunk) {
PacketLoadChunk packet = new PacketLoadChunk("Core:LoadChunk");
packet.getPosition().set( if (chunk == null) {
chunk.getPosition().x, throw new IllegalStateException(String.format(
chunk.getPosition().y, "Chunk (%d; %d; %d) is not loaded, cannot send",
chunk.getPosition().z chunkPos.x, chunkPos.y, chunkPos.z
); ));
}
PacketSendChunk packet = new PacketSendChunk();
packet.getPosition().set(chunkPos.x, chunkPos.y, chunkPos.z);
try { try {
ChunkIO.save(chunk, packet.getData().getOutputStream()); ChunkIO.save(chunk, packet.getData().getOutputStream());
@ -37,22 +32,13 @@ public class TestChunkSender implements WorldDataListener {
CrashReports.report(e, "TestChunkSender fjcked up. javahorse stupid"); CrashReports.report(e, "TestChunkSender fjcked up. javahorse stupid");
} }
server.getClientManager().broadcastLocal(packet, chunk.getPosition()); receiver.sendPacket(packet);
tmp_sendPlayerIfPossible(world, chunk);
} }
private void tmp_sendPlayerIfPossible(WorldData world, ChunkData chunk) { public static void revokeChunk(ClientPlayer receiver, Vec3i chunkPos) {
EntityData e = world.getEntity(TestContent.PLAYER_ENTITY_ID); PacketRevokeChunk packet = new PacketRevokeChunk();
if (e == null) return; packet.set(chunkPos);
receiver.sendPacket(packet);
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);
}
} }
} }

View File

@ -346,10 +346,10 @@ public class TestContent {
)); ));
chunk.getEntities().add(player); chunk.getEntities().add(player);
EntityData statie = EntityDataRegistry.getInstance().create("Test:Statie"); // EntityData statie = EntityDataRegistry.getInstance().create("Test:Statie");
statie.setEntityId(STATIE_ENTITY_ID); // statie.setEntityId(STATIE_ENTITY_ID);
statie.setPosition(new Vec3(0, 15, 16)); // statie.setPosition(new Vec3(0, 15, 16));
chunk.getEntities().add(statie); // chunk.getEntities().add(statie);
} }
} }

View File

@ -17,6 +17,7 @@ import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
import ru.windcorp.progressia.common.Units; import ru.windcorp.progressia.common.Units;
import ru.windcorp.progressia.common.util.FloatMathUtils; import ru.windcorp.progressia.common.util.FloatMathUtils;
import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.EntityData;
import ru.windcorp.progressia.server.ServerState;
public class TestPlayerControls { public class TestPlayerControls {
@ -96,6 +97,13 @@ public class TestPlayerControls {
} }
player.getVelocity().set(change); 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) { public void handleInput(Input input) {