Skip to content

Commit

Permalink
Off world track storage prototype checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
cam72cam committed Aug 25, 2024
1 parent f646954 commit 1dbfd13
Show file tree
Hide file tree
Showing 24 changed files with 1,521 additions and 247 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package cam72cam.immersiverailroading;

import cam72cam.immersiverailroading.data.RegionPacket;
import cam72cam.immersiverailroading.data.WorldData;
import cam72cam.immersiverailroading.entity.*;
import cam72cam.immersiverailroading.entity.physics.chrono.ServerChronoState;
import cam72cam.immersiverailroading.gui.overlay.GuiBuilder;
Expand All @@ -18,6 +20,7 @@
import cam72cam.immersiverailroading.render.item.*;
import cam72cam.immersiverailroading.render.multiblock.MBBlueprintRender;
import cam72cam.immersiverailroading.render.multiblock.TileMultiblockRender;
import cam72cam.immersiverailroading.render.rail.DataRender;
import cam72cam.immersiverailroading.render.rail.RailPreviewRender;
import cam72cam.immersiverailroading.thirdparty.CompatLoader;
import cam72cam.immersiverailroading.tile.TileMultiblock;
Expand All @@ -32,6 +35,7 @@
import cam72cam.mod.entity.Entity;
import cam72cam.mod.entity.EntityRegistry;
import cam72cam.mod.event.ClientEvents;
import cam72cam.mod.event.CommonEvents;
import cam72cam.mod.input.Keyboard;
import cam72cam.mod.input.Keyboard.KeyCode;
import cam72cam.mod.math.Vec3d;
Expand All @@ -42,6 +46,7 @@
import cam72cam.mod.resource.Identifier;
import cam72cam.mod.sound.Audio;
import cam72cam.mod.text.Command;
import cam72cam.mod.world.World;

import java.util.function.Function;

Expand All @@ -66,6 +71,11 @@ public void commonEvent(ModEvent event) {

switch (event) {
case CONSTRUCT:
CommonEvents.WorldData.SAVE.subscribe(WorldData::save);
CommonEvents.WorldData.LOAD.subscribe(WorldData::load);
CommonEvents.WorldData.UNLOAD.subscribe(WorldData::unload);
World.onTick(WorldData::tick);

EntityRegistry.register(ImmersiveRailroading.instance, CarFreight::new, ImmersiveRailroading.ENTITY_SYNC_DISTANCE);
EntityRegistry.register(ImmersiveRailroading.instance, CarPassenger::new, ImmersiveRailroading.ENTITY_SYNC_DISTANCE);
EntityRegistry.register(ImmersiveRailroading.instance, CarTank::new, ImmersiveRailroading.ENTITY_SYNC_DISTANCE);
Expand All @@ -86,6 +96,7 @@ public void commonEvent(ModEvent event) {
Packet.register(ClientPartDragging.SeatPacket::new, PacketDirection.ClientToServer);
Packet.register(GuiBuilder.ControlChangePacket::new, PacketDirection.ClientToServer);
Packet.register(ItemPaintBrush.PaintBrushPacket::new, PacketDirection.ClientToServer);
Packet.register(RegionPacket::new, PacketDirection.ServerToClient);

ServerChronoState.register();

Expand Down Expand Up @@ -207,6 +218,8 @@ public void postRender(EntityMoveableRollingStock entity, RenderState state, flo
}
});

GlobalRender.registerRender(DataRender::render);

ClientEvents.MOUSE_GUI.subscribe(evt -> {
if (!MinecraftClient.isReady()) {
return true;
Expand Down
124 changes: 124 additions & 0 deletions src/main/java/cam72cam/immersiverailroading/data/Region.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package cam72cam.immersiverailroading.data;

import cam72cam.immersiverailroading.util.RailInfo;
import cam72cam.mod.math.Vec3i;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Region {
private final Map<Vec3i, TrackBlock> trackBlocks;
final List<TrackInfo> trackInfos;
boolean needsWriteToDisk;
boolean modifiedSinceLastTick;

public Region() {
trackBlocks = new HashMap<>();
trackInfos = new ArrayList<>();
}

public Region(ByteBuffer buffer) {
int version = buffer.getInt();
if (version != 1) {
throw new RuntimeException(String.format("Invalid track block data version %d", version));
}

int size = buffer.getInt();
trackBlocks = new HashMap<>(size);
for (int i = 0; i < size; i++) {
int x = buffer.getInt();
int y = buffer.getInt();
int z = buffer.getInt();
trackBlocks.put(new Vec3i(x, y, z), new TrackBlock(buffer));
}

size = buffer.getInt();

trackInfos = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
trackInfos.add(i, TrackInfo.load(i, buffer));
}
}

private int sizeBytes() {
int bytes = 0;
bytes += Integer.BYTES; // version
bytes += Integer.BYTES; // trackBlocks.size()
for (TrackBlock value : trackBlocks.values()) {
bytes += Integer.BYTES * 3; // pos.xyz
bytes += value.sizeBytes(); // trackBlock.write()
}
bytes += Integer.BYTES; // trackInfos.size()
for (TrackInfo trackInfo : trackInfos) {
bytes += TrackInfo.sizeBytes(trackInfo);
}
return bytes;
}

public ByteBuffer write() {
// Could be faster with a CoW, not sure how long this blocking is
synchronized (trackBlocks) {
ByteBuffer buffer = ByteBuffer.allocate(sizeBytes());

buffer.putInt(1); // version
buffer.putInt(trackBlocks.size());
for (Map.Entry<Vec3i, TrackBlock> entry : trackBlocks.entrySet()) {
Vec3i pos = entry.getKey();
buffer.putInt(pos.x);
buffer.putInt(pos.y);
buffer.putInt(pos.z);
entry.getValue().write(buffer);
}
buffer.putInt(trackInfos.size());
for (TrackInfo trackInfo : trackInfos) {
TrackInfo.save(trackInfo, buffer);
}
return buffer;
}
}

public TrackBlock getTrackBlock(Vec3i pos) {
synchronized (trackBlocks) {
return trackBlocks.get(pos);
}
}

public void setTrackBlock(Vec3i pos, TrackBlock block) {
synchronized (trackBlocks) {
trackBlocks.put(pos, block);
needsWriteToDisk = true;
modifiedSinceLastTick = true;
}
}

public TrackInfo getTrackInfo(int info_id) {
synchronized (trackInfos) {
return trackInfos.get(info_id);
}
}

public void updateTrackInfo(TrackInfo info) {
synchronized (trackInfos) {
trackInfos.set(info.id, info);
needsWriteToDisk = true;
modifiedSinceLastTick = true;
}
}

public TrackInfo allocateTrackInfo(RailInfo info, TrackInfo parent) {
synchronized (trackInfos) {
TrackInfo allocated = new TrackInfo(trackInfos.size(), info, parent);
trackInfos.add(allocated);
needsWriteToDisk = true;
modifiedSinceLastTick = true;
return allocated;
}
}

public List<TrackInfo> getTrackInfos() {
return trackInfos;
}
}
35 changes: 35 additions & 0 deletions src/main/java/cam72cam/immersiverailroading/data/RegionPacket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package cam72cam.immersiverailroading.data;

import cam72cam.mod.net.Packet;
import cam72cam.mod.serialization.TagField;
import cam72cam.mod.world.World;

import java.nio.ByteBuffer;
import java.util.Base64;

public class RegionPacket extends Packet {
@TagField
private World world;
@TagField
private long id;
public RegionPacket() {
// Reflection
}
public RegionPacket(World world, long id, Region region) {
this.world = world;
this.id = id;
// This is stupidly inefficient
// TODO LZ4 compress?
this.raw = region.write().array();
}

@Override
protected void handle() {
Region region = new Region(ByteBuffer.wrap(raw));

WorldData data = WorldData.getOrCreate(world);
if (data != null) {
data.regions.put(id, region);
}
}
}
60 changes: 60 additions & 0 deletions src/main/java/cam72cam/immersiverailroading/data/TrackBlock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package cam72cam.immersiverailroading.data;

import java.nio.ByteBuffer;

public class TrackBlock {
TrackBlock replaced;
long info_region;
int info_id;
float bedHeight;
float railHeight;
int snowLayers;

public TrackBlock(ByteBuffer buffer) {
if (buffer.get() == 1) {
replaced = new TrackBlock(buffer);
}
info_region = buffer.getLong();
info_id = buffer.getInt();
bedHeight = buffer.getFloat();
railHeight = buffer.getFloat();
snowLayers = buffer.getInt();
}

public TrackBlock(TrackInfo info, float railHeight, float bedHeight, int snowLayers, TrackBlock replaced) {
this.info_id = info.id;
this.info_region = info.region;
this.railHeight = railHeight;
this.bedHeight = bedHeight;
this.replaced = replaced;
this.snowLayers = snowLayers;
}

public void write(ByteBuffer buffer) {
if (replaced == null) {
buffer.put((byte)0);
} else {
buffer.put((byte)1);
replaced.write(buffer);
}
buffer.putLong(info_region);
buffer.putInt(info_id);
buffer.putFloat(bedHeight);
buffer.putFloat(railHeight);
buffer.putInt(snowLayers);
}

public int sizeBytes() {
int bytes = 0;
bytes += 1; // replaced marker
if (replaced != null) {
bytes += replaced.sizeBytes();
}
bytes += Long.BYTES; // info_region
bytes += Integer.BYTES; // info_id
bytes += Float.BYTES; // bedHeight
bytes += Float.BYTES; // railHeight
bytes += Integer.BYTES; // snowLayers
return bytes;
}
}
Loading

0 comments on commit 1dbfd13

Please sign in to comment.