LZ-#17 - Finish initial implementation
This commit is contained in:
parent
059055044d
commit
7d924f7740
13 changed files with 336 additions and 31 deletions
|
@ -5,7 +5,7 @@ import dev.zontreck.libzontreck.vectors.Vector2i;
|
|||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
|
||||
public interface Vector2<T>
|
||||
public interface Vector2<T> extends Cloneable, Comparable<Vector2<T>>
|
||||
{
|
||||
/**
|
||||
* Converts the current Vector2 representation into a minecraft Vec2
|
||||
|
|
|
@ -7,7 +7,7 @@ import net.minecraft.core.Vec3i;
|
|||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public interface Vector3<T>
|
||||
public interface Vector3<T> extends Cloneable, Comparable<Vector3<T>>
|
||||
{
|
||||
/**
|
||||
* Converts the current Vector3 representation into a minecraft Vec3
|
||||
|
|
|
@ -11,7 +11,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
|||
|
||||
import java.util.Random;
|
||||
|
||||
public class BlockRestoreRunner implements Runnable
|
||||
class BlockRestoreRunner implements Runnable
|
||||
{
|
||||
public BlockRestoreRunner(BlockRestoreQueue queue)
|
||||
{
|
||||
|
|
|
@ -25,6 +25,7 @@ public class PrimitiveBlock
|
|||
this.level = level;
|
||||
this.blockState = blockState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias method
|
||||
* @see SavedBlock#serialize()
|
||||
|
@ -67,4 +68,13 @@ public class PrimitiveBlock
|
|||
} else return false;
|
||||
}else return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the PrimitiveBlock into a new instance
|
||||
* @return
|
||||
*/
|
||||
public PrimitiveBlock copy()
|
||||
{
|
||||
return savedBlock.clone().getBlockPrimitive();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package dev.zontreck.libzontreck.memory.world;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
public class SaveDataCoordinates
|
||||
{
|
||||
public int X;
|
||||
public int Z;
|
||||
|
||||
public SaveDataCoordinates(BlockPos pos)
|
||||
{
|
||||
int X = pos.getX() >> 4 >> 5;
|
||||
int Z = pos.getZ() >> 4 >> 5;
|
||||
}
|
||||
|
||||
public String getFileName()
|
||||
{
|
||||
return "r." + X + "." + Z + ".dat";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
package dev.zontreck.libzontreck.memory.world;
|
||||
|
||||
import dev.zontreck.libzontreck.LibZontreck;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class SaveDataFactory
|
||||
{
|
||||
static Map<String, SaveData> datas = new HashMap<>();
|
||||
|
||||
protected static boolean hasSaveDataInstance(SaveDataFile file)
|
||||
{
|
||||
return datas.containsKey(file.getSaveDataPath().toString());
|
||||
}
|
||||
|
||||
protected static SaveData getSaveDataInstance(SaveDataFile file)
|
||||
{
|
||||
return datas.get(file.getSaveDataPath().toString());
|
||||
}
|
||||
|
||||
public static Builder builder()
|
||||
{
|
||||
return new Builder();
|
||||
}
|
||||
static class Builder
|
||||
{
|
||||
private String modID = "minecraft";
|
||||
private String levelName;
|
||||
private String queueID;
|
||||
private boolean DBMode;
|
||||
private BlockPos position;
|
||||
|
||||
public Builder withDimension(Level level)
|
||||
{
|
||||
ResourceLocation lv = level.dimension().location();
|
||||
this.modID = lv.getNamespace();
|
||||
this.levelName = lv.getPath();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withQueueID(BlockRestoreQueue queue)
|
||||
{
|
||||
queueID = queue.getRestoreQueueName();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withDatabaseMode()
|
||||
{
|
||||
DBMode=true;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withPosition(BlockPos pos)
|
||||
{
|
||||
position = pos;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public SaveDataFile build()
|
||||
{
|
||||
return new SaveDataFile(modID, levelName, queueID, DBMode, position);
|
||||
}
|
||||
}
|
||||
|
||||
static class SaveDataFile
|
||||
{
|
||||
String mod;
|
||||
String dimension;
|
||||
String queue;
|
||||
boolean database;
|
||||
BlockPos position;
|
||||
|
||||
public SaveDataFile(String modID, String levelName, String queueID, boolean DBMode, BlockPos pos)
|
||||
{
|
||||
mod = modID;
|
||||
dimension = levelName;
|
||||
queue = queueID;
|
||||
database = DBMode;
|
||||
position = pos;
|
||||
}
|
||||
|
||||
public Path getSaveDataPath()
|
||||
{
|
||||
Path path = LibZontreck.BASE_CONFIG.resolve("block_snapshots");
|
||||
if(mod != null) path = path.resolve(mod);
|
||||
if(dimension != null) path = path.resolve(dimension);
|
||||
if(queue != null) path = path.resolve(queue);
|
||||
|
||||
path.toFile().mkdirs();
|
||||
|
||||
SaveDataCoordinates coordinates = new SaveDataCoordinates(position);
|
||||
path = path.resolve(coordinates.getFileName());
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the save data, or initializes a new instance.
|
||||
* <p></p>
|
||||
* Additionally, this will check for a pre-existing POJO instance and return if it exists.
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public SaveData getInstance() throws IOException {
|
||||
if(SaveDataFactory.hasSaveDataInstance(this)) return SaveDataFactory.getSaveDataInstance(this);
|
||||
Path data = getSaveDataPath();
|
||||
if(data.toFile().exists())
|
||||
{
|
||||
CompoundTag tag = NbtIo.read(data.toFile());
|
||||
|
||||
return SaveData.deserialize(tag, this);
|
||||
} else {
|
||||
|
||||
return new SaveData(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class SaveData {
|
||||
SaveDataFile myFile;
|
||||
public static final String TAG_SAVED_BLOCKS = "sb";
|
||||
|
||||
public List<SavedBlock> blocks = new ArrayList<>();
|
||||
|
||||
public SaveData(SaveDataFile file)
|
||||
{
|
||||
myFile = file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a NBT Tag and reconstruct the SaveData POJO
|
||||
* @param tag
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
public static SaveData deserialize(CompoundTag tag, SaveDataFile file) {
|
||||
SaveData data = new SaveData(file);
|
||||
ListTag lst = tag.getList(TAG_SAVED_BLOCKS, ListTag.TAG_COMPOUND);
|
||||
for(Tag xTag : lst)
|
||||
{
|
||||
if(xTag instanceof CompoundTag ct)
|
||||
{
|
||||
SavedBlock sb = SavedBlock.deserialize(ct);
|
||||
data.blocks.add(sb);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the current save data to NBT
|
||||
* @return
|
||||
*/
|
||||
public CompoundTag serialize()
|
||||
{
|
||||
CompoundTag tag = new CompoundTag();
|
||||
ListTag lst = new ListTag();
|
||||
for(SavedBlock block : blocks)
|
||||
{
|
||||
lst.add(block.serialize());
|
||||
}
|
||||
|
||||
tag.put(TAG_SAVED_BLOCKS, lst);
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports a full queue to the save data file.
|
||||
* ! WARNING ! This method will overwrite the SaveDataFile's Queue ID
|
||||
* @param queue Queue to import
|
||||
* @return The current SaveData instance
|
||||
*/
|
||||
public SaveData importQueue(BlockRestoreQueue queue)
|
||||
{
|
||||
for(PrimitiveBlock blk : queue.getQueue())
|
||||
{
|
||||
blocks.add(blk.savedBlock);
|
||||
}
|
||||
|
||||
myFile.queue = queue.getRestoreQueueName();
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import net.minecraft.world.level.Level;
|
|||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class SavedBlock
|
||||
public class SavedBlock implements Cloneable
|
||||
{
|
||||
private CompoundTag blockState;
|
||||
private CompoundTag blockEntity;
|
||||
|
@ -93,4 +93,20 @@ public class SavedBlock
|
|||
return new PrimitiveBlock(this, state.getBlock(), state, blockEntity, position.Position.asBlockPos(), level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavedBlock clone() {
|
||||
try {
|
||||
SavedBlock clone = (SavedBlock) super.clone();
|
||||
if(blockEntity != null)
|
||||
clone.blockEntity = blockEntity.copy();
|
||||
if(blockState != null)
|
||||
clone.blockState = blockState.copy();
|
||||
if(position != null)
|
||||
clone.position = position.clone();
|
||||
|
||||
return clone;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import dev.zontreck.libzontreck.util.PositionUtil;
|
|||
import dev.zontreck.libzontreck.vectors.Vector3i;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -14,41 +15,22 @@ public class SortedBlockQueue extends BlockRestoreQueue
|
|||
public String getRestoreQueueName() {
|
||||
return "SortedBlockQueue";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDirtyQueue(boolean blockAdded) {
|
||||
if(blockAdded) {
|
||||
// Perform sorting
|
||||
|
||||
List<PrimitiveBlock> queue = getQueue();
|
||||
List<Vector3> positions = new ArrayList<>();
|
||||
List<PrimitiveBlock> retQueue = new ArrayList<>(queue.size());
|
||||
|
||||
Iterator<PrimitiveBlock> it = queue.iterator();
|
||||
// Sort the queue based on block positions
|
||||
queue.sort(Comparator.comparing(block -> new Vector3i(block.position)));
|
||||
|
||||
while(it.hasNext()) {
|
||||
PrimitiveBlock blk = it.next();
|
||||
positions.add(new Vector3i(blk.position));
|
||||
}
|
||||
|
||||
positions = PositionUtil.sortAscending(positions);
|
||||
|
||||
List<PrimitiveBlock> retQueue = new ArrayList<>();
|
||||
|
||||
it = queue.iterator();
|
||||
for(Vector3 pos : positions) {
|
||||
it = queue.iterator();
|
||||
while(it.hasNext()) {
|
||||
PrimitiveBlock blk = it.next();
|
||||
if(blk.position.equals(pos.asBlockPos())) {
|
||||
retQueue.add(blk);
|
||||
it.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Add blocks in sorted order to the new queue
|
||||
for (PrimitiveBlock blk : queue) {
|
||||
retQueue.add(blk.copy()); // Copy block if necessary
|
||||
}
|
||||
|
||||
setQueueNoNotify(retQueue);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package dev.zontreck.libzontreck.vectors;
|
|||
import dev.zontreck.libzontreck.api.Vector2;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Vector2f implements Vector2<Float>
|
||||
{
|
||||
|
@ -182,4 +183,18 @@ public class Vector2f implements Vector2<Float>
|
|||
public Float getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull Vector2<Float> other) {
|
||||
if(other instanceof Vector2f v2f){
|
||||
|
||||
// Compare x coordinates first
|
||||
int cmp = Float.compare(this.x, v2f.x);
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
// If x coordinates are equal, compare y coordinates
|
||||
return Float.compare(this.y, v2f.y);
|
||||
} else return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package dev.zontreck.libzontreck.vectors;
|
|||
import dev.zontreck.libzontreck.api.Vector2;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Vector2i implements Vector2<Integer>
|
||||
{
|
||||
|
@ -195,4 +196,18 @@ public class Vector2i implements Vector2<Integer>
|
|||
public Integer getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull Vector2<Integer> other) {
|
||||
if(other instanceof Vector2i v2i){
|
||||
|
||||
// Compare x coordinates first
|
||||
int cmp = Integer.compare(this.x, v2i.x);
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
// If x coordinates are equal, compare y coordinates
|
||||
return Integer.compare(this.y, v2i.y);
|
||||
} else return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Vector3d implements Vector3<Double>
|
||||
{
|
||||
|
@ -234,4 +235,19 @@ public class Vector3d implements Vector3<Double>
|
|||
public Double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull Vector3<Double> doubleVector3) {
|
||||
if(doubleVector3 instanceof Vector3d v3d)
|
||||
{
|
||||
int Ycomp = Double.compare(y, v3d.y);
|
||||
if(Ycomp!=0)return Ycomp;
|
||||
int Zcomp = Double.compare(z, v3d.z);
|
||||
if(Zcomp!=0)return Zcomp;
|
||||
int Xcomp = Double.compare(x, v3d.x);
|
||||
if(Xcomp!=0)return Xcomp;
|
||||
|
||||
return 0;
|
||||
} else return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -227,4 +228,19 @@ public class Vector3i implements Vector3<Integer>
|
|||
public Integer getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull Vector3<Integer> integerVector3) {
|
||||
if(integerVector3 instanceof Vector3i v3i)
|
||||
{
|
||||
int Ycomp = Integer.compare(y, v3i.y);
|
||||
if(Ycomp!=0)return Ycomp;
|
||||
int Zcomp = Integer.compare(z, v3i.z);
|
||||
if(Zcomp!=0)return Zcomp;
|
||||
int Xcomp = Integer.compare(x, v3i.x);
|
||||
if(Xcomp!=0)return Xcomp;
|
||||
|
||||
return 0;
|
||||
} else return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,14 @@ import dev.zontreck.libzontreck.LibZontreck;
|
|||
import dev.zontreck.libzontreck.exceptions.InvalidDeserialization;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.network.protocol.game.ClientboundMoveEntityPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
||||
|
||||
public class WorldPosition {
|
||||
public class WorldPosition implements Cloneable
|
||||
{
|
||||
|
||||
public Vector3d Position;
|
||||
public String Dimension;
|
||||
|
@ -125,4 +127,16 @@ public class WorldPosition {
|
|||
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldPosition clone() {
|
||||
try {
|
||||
WorldPosition clone = (WorldPosition) super.clone();
|
||||
if(Position != null)
|
||||
clone.Position = Position.Clone();
|
||||
return clone;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue