diff --git a/src/main/java/com/vulpeus/kyoyu/Kyoyu.java b/src/main/java/com/vulpeus/kyoyu/Kyoyu.java index f66477d..cff53b9 100644 --- a/src/main/java/com/vulpeus/kyoyu/Kyoyu.java +++ b/src/main/java/com/vulpeus/kyoyu/Kyoyu.java @@ -1,8 +1,20 @@ package com.vulpeus.kyoyu; +import com.vulpeus.kyoyu.placement.KyoyuPlacement; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; public class Kyoyu { public static final String MOD_ID = "kyoyu"; @@ -53,4 +65,45 @@ private String serverVersion() { return serverVersion; } } + + private static final Path configsDir = Paths.get("kyoyu"); + + private static KyoyuPlacement readPlacement(Path configPath) { + try { + String json = new String(Files.readAllBytes(configPath), StandardCharsets.UTF_8); + return KyoyuPlacement.fromJson(json); + } catch (IOException e) { + LOGGER.error("Kyoyu.readPlacement: read KyoyuPlacement from {}", configPath); + LOGGER.error(e); + } + return null; + } + + public static KyoyuPlacement findPlacement(UUID uuid) { + + if (uuid == null) return null; + + Path configPath = configsDir.resolve(uuid.toString() + ".json"); + if (!configPath.toFile().exists()) return null; + + return readPlacement(configPath); + } + + public static List getAllPlacement() { + File[] files = configsDir.toFile().listFiles(); + if (files != null) { + return Arrays.stream(files).map(file -> readPlacement(file.toPath())).collect(Collectors.toList()); + } + return null; + } + + public static void savePlacement(KyoyuPlacement kyoyuPlacement) { + Path configPath = configsDir.resolve(kyoyuPlacement.getUuid().toString() + ".json"); + try { + Files.write(configPath, Collections.singletonList(kyoyuPlacement.toJson()), StandardCharsets.UTF_8); + } catch (IOException e) { + LOGGER.error("Kyoyu.savePlacement: save KyoyuPlacement from {}", kyoyuPlacement.getUuid()); + LOGGER.error(e); + } + } } diff --git a/src/main/java/com/vulpeus/kyoyu/client/ISchematicPlacement.java b/src/main/java/com/vulpeus/kyoyu/client/ISchematicPlacement.java new file mode 100644 index 0000000..30bd8d7 --- /dev/null +++ b/src/main/java/com/vulpeus/kyoyu/client/ISchematicPlacement.java @@ -0,0 +1,11 @@ +package com.vulpeus.kyoyu.client; + +import java.util.UUID; + +public interface ISchematicPlacement { + + void kyoyu$setKyoyuId(UUID uuid); + + UUID kyoyu$getKyoyuId(); + +} diff --git a/src/main/java/com/vulpeus/kyoyu/client/LitematicHelper.java b/src/main/java/com/vulpeus/kyoyu/client/LitematicHelper.java new file mode 100644 index 0000000..a54029a --- /dev/null +++ b/src/main/java/com/vulpeus/kyoyu/client/LitematicHelper.java @@ -0,0 +1,38 @@ +package com.vulpeus.kyoyu.client; + +//? if client { +import com.vulpeus.kyoyu.placement.KyoyuPlacement; +import com.vulpeus.kyoyu.placement.KyoyuRegion; +import fi.dy.masa.litematica.data.DataManager; +import fi.dy.masa.litematica.schematic.placement.SchematicPlacement; + +public class LitematicHelper { + + public static void newSchematicPlacementFromKyoyuPlacement(SchematicPlacement schematicPlacement, KyoyuPlacement kyoyuPlacement) { + + changeSchematicPlacementFromKyoyuPlacement(schematicPlacement, kyoyuPlacement); + DataManager.getSchematicPlacementManager().addSchematicPlacement(schematicPlacement, true); + ((ISchematicPlacement) schematicPlacement).kyoyu$setKyoyuId(kyoyuPlacement.getUuid()); + + } + + public static void changeSchematicPlacementFromKyoyuPlacement(SchematicPlacement schematicPlacement, KyoyuPlacement kyoyuPlacement) { + + if (schematicPlacement.isLocked()) { + schematicPlacement.toggleLocked(); + } + + schematicPlacement.setMirror(kyoyuPlacement.getRegion().getMirror(), null); + schematicPlacement.setRotation(kyoyuPlacement.getRegion().getRotation(), null); + for (KyoyuRegion subRegion: kyoyuPlacement.getSubRegions()) { + String subRegionName = subRegion.getName(); + + schematicPlacement.moveSubRegionTo(subRegionName, subRegion.getPos(), null); + schematicPlacement.setSubRegionMirror(subRegionName, subRegion.getMirror(), null); + schematicPlacement.setSubRegionRotation(subRegionName, subRegion.getRotation(), null); + } + schematicPlacement.toggleLocked(); + + } +} +//?} diff --git a/src/main/java/com/vulpeus/kyoyu/client/NetworkHelper.java b/src/main/java/com/vulpeus/kyoyu/client/NetworkHelper.java index f9df68b..8fb6e8c 100644 --- a/src/main/java/com/vulpeus/kyoyu/client/NetworkHelper.java +++ b/src/main/java/com/vulpeus/kyoyu/client/NetworkHelper.java @@ -11,7 +11,7 @@ public class NetworkHelper { public static void openExplorer(List kyoyuPlacementList){ - if (Kyoyu.isClient() && Kyoyu.getClient().isPresent() && GuiUtils.getCurrentScreen() instanceof GuiBase) { + if (Kyoyu.isClient() && Kyoyu.getClient() != null && GuiUtils.getCurrentScreen() instanceof GuiBase) { GuiBase currentGui = (GuiBase) GuiUtils.getCurrentScreen(); GuiBase.openGui(new Explorer_GuiList(currentGui.getParent(), kyoyuPlacementList)); } diff --git a/src/main/java/com/vulpeus/kyoyu/client/gui/Explorer_WidgetListEntry.java b/src/main/java/com/vulpeus/kyoyu/client/gui/Explorer_WidgetListEntry.java index 61910fc..945a867 100644 --- a/src/main/java/com/vulpeus/kyoyu/client/gui/Explorer_WidgetListEntry.java +++ b/src/main/java/com/vulpeus/kyoyu/client/gui/Explorer_WidgetListEntry.java @@ -2,8 +2,8 @@ //? if client { import com.vulpeus.kyoyu.Kyoyu; +import com.vulpeus.kyoyu.client.LitematicHelper; import com.vulpeus.kyoyu.placement.KyoyuPlacement; -import com.vulpeus.kyoyu.placement.KyoyuRegion; import fi.dy.masa.litematica.data.DataManager; import fi.dy.masa.litematica.data.SchematicHolder; import fi.dy.masa.litematica.gui.GuiMaterialList; @@ -18,9 +18,6 @@ import fi.dy.masa.malilib.render.RenderUtils; import fi.dy.masa.malilib.util.GuiUtils; import fi.dy.masa.malilib.util.StringUtils; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; //? if >=1.20 { import net.minecraft.client.gui.GuiGraphics; @@ -162,32 +159,18 @@ void onAction(Explorer_WidgetListEntry entry) { LOAD() { @Override void onAction(Explorer_WidgetListEntry entry) { - String name = entry.kyoyuPlacement.getName(); - BlockPos pos = entry.kyoyuPlacement.getRegion().getPos(); - Mirror mirror = entry.kyoyuPlacement.getRegion().getMirror(); - Rotation rotation = entry.kyoyuPlacement.getRegion().getRotation(); - LitematicaSchematic schematic = SchematicHolder.getInstance().getOrLoad(entry.kyoyuPlacement.getFile()); - SchematicPlacement placement = SchematicPlacement.createFor(schematic, pos, name, true, true); - - if (placement.isLocked()) { - placement.toggleLocked(); - } + SchematicPlacement placement = SchematicPlacement.createFor( + SchematicHolder.getInstance().getOrLoad(entry.kyoyuPlacement.getFile()), + entry.kyoyuPlacement.getRegion().getPos(), + entry.kyoyuPlacement.getName(), + true, + true + ); + LitematicHelper.newSchematicPlacementFromKyoyuPlacement(placement, entry.kyoyuPlacement); - placement.setMirror(mirror, null); - placement.setRotation(rotation, null); - for (KyoyuRegion subRegion: entry.kyoyuPlacement.getSubRegions()) { - String subRegionName = subRegion.getName(); + Kyoyu.savePlacement(entry.kyoyuPlacement); - placement.moveSubRegionTo(subRegionName, subRegion.getPos(), null); - placement.setSubRegionMirror(subRegionName, subRegion.getMirror(), null); - placement.setSubRegionRotation(subRegionName, subRegion.getRotation(), null); - } - placement.toggleLocked(); - - DataManager.getSchematicPlacementManager().addSchematicPlacement(placement, true); - // TODO - // getClient().add(entry.kyoyuPlacement, placement); } }, DOWNLOAD() { diff --git a/src/main/java/com/vulpeus/kyoyu/client/gui/Shere_ButtonActionListener.java b/src/main/java/com/vulpeus/kyoyu/client/gui/Shere_ButtonActionListener.java index 19d0736..346b975 100644 --- a/src/main/java/com/vulpeus/kyoyu/client/gui/Shere_ButtonActionListener.java +++ b/src/main/java/com/vulpeus/kyoyu/client/gui/Shere_ButtonActionListener.java @@ -2,6 +2,7 @@ //? if client { import com.vulpeus.kyoyu.Kyoyu; +import com.vulpeus.kyoyu.client.ISchematicPlacement; import com.vulpeus.kyoyu.net.KyoyuPacketManager; import com.vulpeus.kyoyu.net.packets.PlacementMetaPacket; import com.vulpeus.kyoyu.placement.KyoyuPlacement; @@ -34,9 +35,6 @@ public void actionPerformedWithButton(ButtonBase buttonBase, int i) { buttonBase.setEnabled(false); - // TODO - // `schematicPlacement` add to client registry - File placementFile = schematicPlacement.getSchematicFile(); if (placementFile == null) { // TODO: in memory placement @@ -68,6 +66,9 @@ public void actionPerformedWithButton(ButtonBase buttonBase, int i) { placementFile ); + Kyoyu.savePlacement(kyoyuPlacement); + ((ISchematicPlacement) schematicPlacement).kyoyu$setKyoyuId(kyoyuPlacement.getUuid()); + PlacementMetaPacket placementMetaPacket = new PlacementMetaPacket(kyoyuPlacement); KyoyuPacketManager.sendC2S(placementMetaPacket); } diff --git a/src/main/java/com/vulpeus/kyoyu/client/mixins/litematica/GuiMainMenuMixin.java b/src/main/java/com/vulpeus/kyoyu/client/mixins/litematica/GuiMainMenuMixin.java index 663e0e9..53d8797 100644 --- a/src/main/java/com/vulpeus/kyoyu/client/mixins/litematica/GuiMainMenuMixin.java +++ b/src/main/java/com/vulpeus/kyoyu/client/mixins/litematica/GuiMainMenuMixin.java @@ -26,7 +26,7 @@ public void initGui(CallbackInfo ci) { int y = this.height - 26; ButtonGeneric button = new ButtonGeneric(x, y, width, 20, text); - button.setEnabled(Kyoyu.getClient().isPresent()); + button.setEnabled(Kyoyu.getClient() != null); addButton(button, new LoadExplorer_ButtonActionListener(this)); } } diff --git a/src/main/java/com/vulpeus/kyoyu/client/mixins/litematica/SchematicPlacementMixin.java b/src/main/java/com/vulpeus/kyoyu/client/mixins/litematica/SchematicPlacementMixin.java index ecaa4f4..e128451 100644 --- a/src/main/java/com/vulpeus/kyoyu/client/mixins/litematica/SchematicPlacementMixin.java +++ b/src/main/java/com/vulpeus/kyoyu/client/mixins/litematica/SchematicPlacementMixin.java @@ -1,20 +1,70 @@ package com.vulpeus.kyoyu.client.mixins.litematica; //? if client { +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.vulpeus.kyoyu.Kyoyu; +import com.vulpeus.kyoyu.client.ISchematicPlacement; +import com.vulpeus.kyoyu.client.LitematicHelper; +import com.vulpeus.kyoyu.placement.KyoyuPlacement; import fi.dy.masa.litematica.schematic.placement.SchematicPlacement; import fi.dy.masa.litematica.schematic.placement.SchematicPlacementManager; +import fi.dy.masa.malilib.util.JsonUtils; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.UUID; @Mixin(SchematicPlacement.class) -public class SchematicPlacementMixin { +public class SchematicPlacementMixin implements ISchematicPlacement { + + @Unique + private UUID kyoyu_id; + + @Override + public void kyoyu$setKyoyuId(UUID uuid) { + kyoyu_id = uuid; + } + + @Override + public UUID kyoyu$getKyoyuId() { + return kyoyu_id; + } + @Inject(method = "onModified(Lfi/dy/masa/litematica/schematic/placement/SchematicPlacementManager;)V", at = @At("HEAD"), remap = false) public void onModified(SchematicPlacementManager manager, CallbackInfo ci) { // TODO // attention when connecting server is compatible // if (getClient() != null) } + + @Inject(method = "toJson", at = @At("RETURN"), remap = false) + public void saveToJson(CallbackInfoReturnable cir) { + JsonObject saveData = cir.getReturnValue(); + if (saveData != null) { + saveData.add("kyoyu_id", new JsonPrimitive(kyoyu_id.toString())); + } + } + + @Inject(method = "fromJson", at = @At("RETURN"), remap = false, cancellable = true) + private static void loadFromJson(JsonObject obj, CallbackInfoReturnable cir) { + if (JsonUtils.hasString(obj, "kyoyu_id")) { + SchematicPlacement self = cir.getReturnValue(); + if (self != null) { + UUID uuid = UUID.fromString(obj.get("kyoyu_id").getAsString()); + ((ISchematicPlacement) self).kyoyu$setKyoyuId(uuid); + cir.setReturnValue(null); + + KyoyuPlacement kyoyuPlacement = Kyoyu.findPlacement(uuid); + if (kyoyuPlacement != null) { + LitematicHelper.newSchematicPlacementFromKyoyuPlacement(self, kyoyuPlacement); + } + } + } + } } //?} diff --git a/src/main/java/com/vulpeus/kyoyu/client/mixins/litematica/WidgetSchematicPlacementMixin.java b/src/main/java/com/vulpeus/kyoyu/client/mixins/litematica/WidgetSchematicPlacementMixin.java index a1445fe..5f39c82 100644 --- a/src/main/java/com/vulpeus/kyoyu/client/mixins/litematica/WidgetSchematicPlacementMixin.java +++ b/src/main/java/com/vulpeus/kyoyu/client/mixins/litematica/WidgetSchematicPlacementMixin.java @@ -2,6 +2,7 @@ //? if client { import com.vulpeus.kyoyu.Kyoyu; +import com.vulpeus.kyoyu.client.ISchematicPlacement; import com.vulpeus.kyoyu.client.gui.Shere_ButtonActionListener; import fi.dy.masa.litematica.gui.widgets.WidgetListSchematicPlacements; import fi.dy.masa.litematica.gui.widgets.WidgetSchematicPlacement; @@ -34,7 +35,7 @@ protected WidgetSchematicPlacementMixin(int x, int y, int width, int height, @Nu public void init(int x, int y, int width, int height, boolean isOdd, SchematicPlacement placement, int listIndex, WidgetListSchematicPlacements parent, CallbackInfo ci) { ButtonGeneric shareButton = new ButtonGeneric(buttonsStartX, y + 1, -1, true, "kyoyu.gui.button.share_litematic"); - shareButton.setEnabled(Kyoyu.getClient().isPresent()); + shareButton.setEnabled(Kyoyu.findPlacement(((ISchematicPlacement) placement).kyoyu$getKyoyuId())==null); addButton(shareButton, new Shere_ButtonActionListener(placement)); buttonsStartX = shareButton.getX() - 1; } diff --git a/src/main/java/com/vulpeus/kyoyu/net/packets/LoadExplorerPacket.java b/src/main/java/com/vulpeus/kyoyu/net/packets/LoadExplorerPacket.java index 36b97c2..03c8fb6 100644 --- a/src/main/java/com/vulpeus/kyoyu/net/packets/LoadExplorerPacket.java +++ b/src/main/java/com/vulpeus/kyoyu/net/packets/LoadExplorerPacket.java @@ -7,7 +7,6 @@ import net.minecraft.server.level.ServerPlayer; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; import java.util.List; public class LoadExplorerPacket extends IKyoyuPacket { @@ -42,8 +41,7 @@ public byte[] encode() { @Override public void onServer(ServerPlayer player) { - // TODO: Get Kyoyu Placements - List list = new ArrayList<>(); + List list = Kyoyu.getAllPlacement(); LoadExplorerPacket loadExplorerPacket = new LoadExplorerPacket(list); KyoyuPacketManager.sendS2C(loadExplorerPacket, player); diff --git a/src/main/java/com/vulpeus/kyoyu/net/packets/PlacementMetaPacket.java b/src/main/java/com/vulpeus/kyoyu/net/packets/PlacementMetaPacket.java index e5df95d..ce5e9ae 100644 --- a/src/main/java/com/vulpeus/kyoyu/net/packets/PlacementMetaPacket.java +++ b/src/main/java/com/vulpeus/kyoyu/net/packets/PlacementMetaPacket.java @@ -29,7 +29,15 @@ public byte[] encode() { @Override public void onServer(ServerPlayer player) { Kyoyu.LOGGER.info("New placement by {}", player.getName()); - // TODO: new or modify + KyoyuPlacement preKyoyuPlacement = Kyoyu.findPlacement(kyoyuPlacement.getUuid()); + if (preKyoyuPlacement == null) { + Kyoyu.savePlacement(kyoyuPlacement); + // TODO: New + // if i don't have file, request file download. + } else { + // TODO: Modify + // check diff and update `updater` field + } } @Override diff --git a/src/main/java/com/vulpeus/kyoyu/placement/KyoyuPlacement.java b/src/main/java/com/vulpeus/kyoyu/placement/KyoyuPlacement.java index fc96d42..0342a23 100644 --- a/src/main/java/com/vulpeus/kyoyu/placement/KyoyuPlacement.java +++ b/src/main/java/com/vulpeus/kyoyu/placement/KyoyuPlacement.java @@ -7,9 +7,11 @@ import java.lang.reflect.Type; import java.util.LinkedList; import java.util.List; +import java.util.UUID; public class KyoyuPlacement { + private final UUID uuid; private final KyoyuRegion region; private final List subRegions; private final String ownerName; @@ -18,6 +20,11 @@ public class KyoyuPlacement { private transient File file; public KyoyuPlacement(KyoyuRegion region, List subRegions, String ownerName, String updaterName, File file) { + this(UUID.randomUUID(), region, subRegions, ownerName, updaterName, file); + } + + public KyoyuPlacement(UUID uuid, KyoyuRegion region, List subRegions, String ownerName, String updaterName, File file) { + this.uuid = uuid; this.region = region; this.subRegions = subRegions; this.ownerName = ownerName; @@ -25,6 +32,10 @@ public KyoyuPlacement(KyoyuRegion region, List subRegions, String o this.file = file; } + public UUID getUuid() { + return uuid; + } + public String getName() { return this.region.getName(); }