diff --git a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterPanel.java b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterPanel.java index 219ae9c8e..897ba7271 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterPanel.java +++ b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterPanel.java @@ -31,6 +31,16 @@ public class BlockEntityMatterPanel extends BlockEntityMattery implements IMatte private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.matter_panel"); + private final ArrayList listeners = new ArrayList<>(); + + public void attachMenu(MatterPanelMenu menu) { + listeners.add(menu); + } + + public void deatachMenu(MatterPanelMenu menu) { + listeners.remove(menu); + } + @Override protected Component getDefaultDisplayName() { return NAME; @@ -137,7 +147,7 @@ public class BlockEntityMatterPanel extends BlockEntityMattery implements IMatte if (!simulate) { var newer = task.shrinkRequired(1); tasks.put(entry.getKey(), newer); - + listeners.forEach(menu -> menu.taskUpdated(newer)); grid.onMatterTaskUpdated(newer, task); } @@ -165,11 +175,18 @@ public class BlockEntityMatterPanel extends BlockEntityMattery implements IMatte if (grid != null) grid.onMatterTaskCreated(task); + + MatterTask finalGet_task1 = get_task; + listeners.forEach(menu -> menu.taskRemoved(finalGet_task1)); } else { tasks.put(task.id(), get_task); - if (grid != null) + if (grid != null) { grid.onMatterTaskUpdated(get_task, old_task); + } + + MatterTask finalGet_task = get_task; + listeners.forEach(menu -> menu.taskUpdated(finalGet_task)); } return true; @@ -210,6 +227,24 @@ public class BlockEntityMatterPanel extends BlockEntityMattery implements IMatte return tasks.get(id); } + public void removeTask(UUID id) { + var task = tasks.get(id); + + if (task == null) + return; + + tasks.remove(id); + + if (grid != null) + grid.onMatterTaskRemoved(task); + + listeners.forEach(menu -> menu.taskRemoved(task)); + } + + public void removeTask(PatternState state) { + removeTask(state.id()); + } + public MatterTask addTask(PatternState state, int how_much) { var task = new MatterTask(UUID.randomUUID(), state.id(), state.item(), 0, 0, how_much); tasks.put(task.id(), task); @@ -217,6 +252,8 @@ public class BlockEntityMatterPanel extends BlockEntityMattery implements IMatte if (grid != null) grid.onMatterTaskCreated(task); + listeners.forEach(menu -> menu.taskUpdated(task)); + return task; } diff --git a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterReplicator.java b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterReplicator.java index 0b24d33c3..00819c4e0 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterReplicator.java +++ b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterReplicator.java @@ -69,11 +69,11 @@ public class BlockEntityMatterReplicator extends BlockEntityMatteryPoweredWorker @Override protected MachineJobStatus onJobFinish(MachineJob job) { if (!regular_slots.addItem(job.stack()).isEmpty()) { - if (grid != null) { - grid.notifyTaskCompletion(MatterTask.deserializeNBT(job.data().get("task"))); - } + return new MachineJobStatus(false, 20); + } - return new MachineJobStatus(false); + if (grid != null) { + grid.notifyTaskCompletion(MatterTask.deserializeNBT(job.data().get("task"))); } return new MachineJobStatus(); diff --git a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMattery.java b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMattery.java index d161290fc..8029d2136 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMattery.java +++ b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMattery.java @@ -16,6 +16,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; import javax.annotation.Nullable; +import java.util.UUID; public abstract class BlockEntityMattery extends BlockEntity implements MenuProvider { protected Component display_name; diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/MatterTask.java b/src/main/java/ru/dbotthepony/mc/otm/capability/MatterTask.java index 80a167a95..7cdb79b7d 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/MatterTask.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/MatterTask.java @@ -6,6 +6,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.registries.ForgeRegistry; import net.minecraftforge.registries.RegistryManager; @@ -25,6 +26,19 @@ public record MatterTask(@Nonnull UUID id, @Nullable UUID pattern, @Nonnull Item this.required = Math.max(0, required); } + @Override + public int hashCode() { + return id.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof MatterTask obj1) + return obj1.id.equals(id); + + return false; + } + public ItemStack stack() { return new ItemStack(item, 1); } @@ -72,7 +86,7 @@ public record MatterTask(@Nonnull UUID id, @Nullable UUID pattern, @Nonnull Item if (nbt instanceof CompoundTag tag) { Item get_item = RegistryManager.ACTIVE.getRegistry(Item.class).getValue(new ResourceLocation(tag.getString("item"))); - if (get_item != null) { + if (get_item != null && get_item != Items.AIR) { long a = tag.getLong("pattern_u"); long b = tag.getLong("pattern_l"); @@ -110,4 +124,20 @@ public record MatterTask(@Nonnull UUID id, @Nullable UUID pattern, @Nonnull Item buffer.writeInt(finished); buffer.writeInt(required); } + + @Nullable + public static MatterTask read(FriendlyByteBuf buffer) { + var id = new UUID(buffer.readLong(), buffer.readLong()); + var pattern = buffer.readBoolean() ? new UUID(buffer.readLong(), buffer.readLong()) : null; + var item = ((ForgeRegistry) RegistryManager.ACTIVE.getRegistry(Item.class)).getValue(buffer.readInt()); + + if (item == null) + return null; + + var in_progress = buffer.readInt(); + var finished = buffer.readInt(); + var required = buffer.readInt(); + + return new MatterTask(id, pattern, item, in_progress, finished, required); + } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/matter/MatterGrid.java b/src/main/java/ru/dbotthepony/mc/otm/matter/MatterGrid.java index ab02f4552..d2847c614 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/matter/MatterGrid.java +++ b/src/main/java/ru/dbotthepony/mc/otm/matter/MatterGrid.java @@ -46,7 +46,7 @@ public class MatterGrid implements IMatterGridListener { var set = discovering_neighbours.get(event.world); - if (set != null && set.size() != 0) { + if (set != null) { ArrayList> invalid = new ArrayList<>(); for (Supplier cell : set) { diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/MatterPanelMenu.java b/src/main/java/ru/dbotthepony/mc/otm/menu/MatterPanelMenu.java index a10c2ba44..0609cc0f4 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/MatterPanelMenu.java +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/MatterPanelMenu.java @@ -8,12 +8,17 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters; import ru.dbotthepony.mc.otm.Registry; import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterPanel; import ru.dbotthepony.mc.otm.capability.IMatterGridListener; +import ru.dbotthepony.mc.otm.capability.MatterTask; import ru.dbotthepony.mc.otm.capability.PatternState; import ru.dbotthepony.mc.otm.matter.MatterGrid; +import ru.dbotthepony.mc.otm.network.CancelMatterTaskPacket; +import ru.dbotthepony.mc.otm.network.MatterTaskPacket; import ru.dbotthepony.mc.otm.network.MatteryNetworking; import ru.dbotthepony.mc.otm.network.PatternGridPacket; import java.util.ArrayList; +import java.util.UUID; +import java.util.function.Consumer; public class MatterPanelMenu extends MatteryMenu implements IMatterGridListener { public MatterPanelMenu(int p_38852_, Inventory inventory) { @@ -29,6 +34,7 @@ public class MatterPanelMenu extends MatteryMenu implements IMatterGridListener if (tile != null) { grid = tile.getMatterGrid(); + tile.attachMenu(this); if (grid != null) { grid.attach(this); @@ -36,8 +42,17 @@ public class MatterPanelMenu extends MatteryMenu implements IMatterGridListener } } + public void taskUpdated(MatterTask task) { + sendNetwork(new MatterTaskPacket(true, task)); + } + + public void taskRemoved(MatterTask task) { + sendNetwork(new MatterTaskPacket(false, task)); + } + // client code public ArrayList patterns = new ArrayList<>(); + public ArrayList tasks = new ArrayList<>(); public int changeset = 0; public void networkPatternsUpdated(PatternState[] patterns) { @@ -62,6 +77,42 @@ public class MatterPanelMenu extends MatteryMenu implements IMatterGridListener } } + public void networkTasksUpdated(MatterTask[] tasks) { + changeset++; + + for (var task : tasks) { + var index_of = this.tasks.indexOf(task); + + if (index_of != -1) { + this.tasks.set(index_of, task); + } else { + this.tasks.add(task); + } + + if (watcher_update != null) + watcher_update.accept(task); + } + } + + public void networkTasksRemoved(MatterTask[] tasks) { + changeset++; + + for (var task : tasks) { + this.tasks.remove(task); + + if (watcher_delete != null) + watcher_delete.accept(task); + } + } + + private Consumer watcher_delete; + private Consumer watcher_update; + + public void networkTaskWatcher(Consumer watcher_update, Consumer watcher_delete) { + this.watcher_delete = watcher_delete; + this.watcher_update = watcher_update; + } + // server code public void requestReplication(ServerPlayer ply, PatternState state, int how_much) { if (tile == null) @@ -82,19 +133,30 @@ public class MatterPanelMenu extends MatteryMenu implements IMatterGridListener tile.addTask(state, how_much); } + public void receiveTaskCancel(ServerPlayer ply, UUID id) { + if (tile == null) + return; + + tile.removeTask(id); + } + + public void requestTaskCancel(UUID id) { + MatteryNetworking.CHANNEL.sendToServer(new CancelMatterTaskPacket(id)); + } + @Override public void onPatternAdded(PatternState state) { - sendNetwork(new PatternGridPacket(containerId, true, state)); + sendNetwork(new PatternGridPacket(true, state)); } @Override public void onPatternRemoved(PatternState state) { - sendNetwork(new PatternGridPacket(containerId, false, state)); + sendNetwork(new PatternGridPacket(false, state)); } @Override public void onPatternUpdated(PatternState new_state, PatternState old_state) { - sendNetwork(new PatternGridPacket(containerId, true, new_state)); + sendNetwork(new PatternGridPacket(true, new_state)); } private boolean initial_send = false; @@ -103,6 +165,9 @@ public class MatterPanelMenu extends MatteryMenu implements IMatterGridListener public void removed(Player p_38940_) { super.removed(p_38940_); + if (tile != null) + tile.deatachMenu(this); + if (grid != null) grid.detach(this); } @@ -130,8 +195,10 @@ public class MatterPanelMenu extends MatteryMenu implements IMatterGridListener if (grid != null) { initial_send = true; - sendNetwork(new PatternGridPacket(containerId, true, grid.getStoredPatterns().toArray(new PatternState[0]))); + sendNetwork(new PatternGridPacket(true, grid.getStoredPatterns().toArray(new PatternState[0]))); } + + sendNetwork(new MatterTaskPacket(true, tile.getAllTasks().toArray(new MatterTask[0]))); } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/CancelMatterTaskPacket.java b/src/main/java/ru/dbotthepony/mc/otm/network/CancelMatterTaskPacket.java new file mode 100644 index 000000000..2e3bd4eb9 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/network/CancelMatterTaskPacket.java @@ -0,0 +1,42 @@ +package ru.dbotthepony.mc.otm.network; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fmllegacy.network.NetworkEvent; +import ru.dbotthepony.mc.otm.capability.MatterTask; +import ru.dbotthepony.mc.otm.menu.MatterPanelMenu; + +import java.util.UUID; +import java.util.function.Supplier; + +public record CancelMatterTaskPacket(UUID id) { + public CancelMatterTaskPacket(UUID id) { + this.id = id; + } + + public CancelMatterTaskPacket(MatterTask task) { + this(task.id()); + } + + public void write(FriendlyByteBuf buffer) { + buffer.writeLong(id.getMostSignificantBits()); + buffer.writeLong(id.getLeastSignificantBits()); + } + + public void play(Supplier context) { + context.get().setPacketHandled(true); + + context.get().enqueueWork(() -> { + var player = context.get().getSender(); + + if (player.containerMenu instanceof MatterPanelMenu menu) { + menu.receiveTaskCancel(player, id); + } + }); + } + + public static CancelMatterTaskPacket read(FriendlyByteBuf buffer) { + return new CancelMatterTaskPacket(new UUID(buffer.readLong(), buffer.readLong())); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/MatterTaskPacket.java b/src/main/java/ru/dbotthepony/mc/otm/network/MatterTaskPacket.java new file mode 100644 index 000000000..83fb13657 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/network/MatterTaskPacket.java @@ -0,0 +1,53 @@ +package ru.dbotthepony.mc.otm.network; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fmllegacy.network.NetworkEvent; +import ru.dbotthepony.mc.otm.OverdriveThatMatters; +import ru.dbotthepony.mc.otm.capability.MatterTask; +import ru.dbotthepony.mc.otm.capability.PatternState; +import ru.dbotthepony.mc.otm.menu.MatterPanelMenu; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.Objects; +import java.util.function.Supplier; + +@ParametersAreNonnullByDefault +public record MatterTaskPacket(boolean action, MatterTask...state) { + public void write(FriendlyByteBuf buffer) { + buffer.writeBoolean(action); + buffer.writeInt(state.length); + + for (var state1 : state) + state1.write(buffer); + } + + public void play(Supplier context) { + context.get().setPacketHandled(true); + context.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::playClient)); + } + + private void playClient() { + if (Minecraft.getInstance().player.containerMenu instanceof MatterPanelMenu menu) { + if (action) + menu.networkTasksUpdated(state); + else + menu.networkTasksRemoved(state); + } else { + OverdriveThatMatters.LOGGER.error("Receive task state list, but no valid container is open / open container is not MatterPanelMenu!"); + } + } + + public static MatterTaskPacket read(FriendlyByteBuf buffer) { + boolean action = buffer.readBoolean(); + int amount = buffer.readInt(); + var list = new MatterTask[amount]; + + for (int i = 0; i < amount; i++) + list[i] = Objects.requireNonNull(MatterTask.read(buffer)); + + return new MatterTaskPacket(action, list); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java b/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java index 58dda7508..24f392de1 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java +++ b/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java @@ -39,6 +39,24 @@ public class MatteryNetworking { Optional.of(NetworkDirection.PLAY_TO_CLIENT) ); + CHANNEL.registerMessage( + next_network_id++, + MatterTaskPacket.class, + MatterTaskPacket::write, + MatterTaskPacket::read, + MatterTaskPacket::play, + Optional.of(NetworkDirection.PLAY_TO_CLIENT) + ); + + CHANNEL.registerMessage( + next_network_id++, + CancelMatterTaskPacket.class, + CancelMatterTaskPacket::write, + CancelMatterTaskPacket::read, + CancelMatterTaskPacket::play, + Optional.of(NetworkDirection.PLAY_TO_SERVER) + ); + CHANNEL.registerMessage( next_network_id++, PatternReplicationRequestPacket.class, diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/PatternGridPacket.java b/src/main/java/ru/dbotthepony/mc/otm/network/PatternGridPacket.java index dca0fa571..d67a848d8 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/network/PatternGridPacket.java +++ b/src/main/java/ru/dbotthepony/mc/otm/network/PatternGridPacket.java @@ -14,9 +14,8 @@ import java.util.Objects; import java.util.function.Supplier; @ParametersAreNonnullByDefault -public record PatternGridPacket(int container_id, boolean action, PatternState ...state) { +public record PatternGridPacket(boolean action, PatternState ...state) { public void write(FriendlyByteBuf buffer) { - buffer.writeInt(container_id); buffer.writeBoolean(action); buffer.writeInt(state.length); @@ -31,11 +30,6 @@ public record PatternGridPacket(int container_id, boolean action, PatternState . private void playClient() { if (Minecraft.getInstance().player.containerMenu instanceof MatterPanelMenu menu) { - if (menu.containerId != container_id) { - OverdriveThatMatters.LOGGER.error("Receive pattern state list for {}, but current container has id of {}!", container_id, menu.containerId); - return; - } - if (action) menu.networkPatternsUpdated(state); else @@ -44,11 +38,10 @@ public record PatternGridPacket(int container_id, boolean action, PatternState . return; } - OverdriveThatMatters.LOGGER.error("Receive pattern state list for {}, but no valid container is open!", container_id); + OverdriveThatMatters.LOGGER.error("Receive pattern state list, but no valid container is open / container is not MatterPanelMenu!"); } public static PatternGridPacket read(FriendlyByteBuf buffer) { - int container_id = buffer.readInt(); boolean action = buffer.readBoolean(); int amount = buffer.readInt(); var list = new PatternState[amount]; @@ -56,6 +49,6 @@ public record PatternGridPacket(int container_id, boolean action, PatternState . for (int i = 0; i < amount; i++) list[i] = Objects.requireNonNull(PatternState.read(buffer)); - return new PatternGridPacket(container_id, action, list); + return new PatternGridPacket(action, list); } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/PatternReplicationRequestPacket.java b/src/main/java/ru/dbotthepony/mc/otm/network/PatternReplicationRequestPacket.java index db0606ae3..62885cd54 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/network/PatternReplicationRequestPacket.java +++ b/src/main/java/ru/dbotthepony/mc/otm/network/PatternReplicationRequestPacket.java @@ -27,10 +27,8 @@ public record PatternReplicationRequestPacket(PatternState state, int how_much) var ply = context.get().getSender(); - if (!(ply.containerMenu instanceof MatterPanelMenu menu)) - return; - - menu.requestReplication(ply, state, how_much); + if (ply.containerMenu instanceof MatterPanelMenu menu) + menu.requestReplication(ply, state, how_much); }); } diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/MatterPanelScreen.java b/src/main/java/ru/dbotthepony/mc/otm/screen/MatterPanelScreen.java index 463708ca9..56e348793 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/MatterPanelScreen.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/MatterPanelScreen.java @@ -7,12 +7,16 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; import ru.dbotthepony.mc.otm.OverdriveThatMatters; +import ru.dbotthepony.mc.otm.capability.MatterTask; import ru.dbotthepony.mc.otm.capability.PatternState; import ru.dbotthepony.mc.otm.menu.MatterPanelMenu; import ru.dbotthepony.mc.otm.network.MatteryNetworking; @@ -28,6 +32,8 @@ public class MatterPanelScreen extends MatteryScreen { private static final int modal_width = 213; private static final int modal_height = 110; + private boolean open_task_list = false; + protected static final ResourceLocation CONTAINER = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/matter_panel.png"); protected ResourceLocation CONTAINER_BACKGROUND() { @@ -41,10 +47,22 @@ public class MatterPanelScreen extends MatteryScreen { imageHeight = 187; titleLabelY = 5; + + p_97741_.networkTaskWatcher(task -> { + if (open_task != null && open_task.equals(task)) { + open_task = task; + } + }, task -> { + if (open_task != null && open_task.equals(task)) { + closeTask(); + } + }); } private PatternState open_pattern; + private MatterTask open_task; private EditBox input_amount; + private Button inc_8; private Button inc_64; private Button inc_256; @@ -53,12 +71,16 @@ public class MatterPanelScreen extends MatteryScreen { private Button dec_64; private Button dec_256; - private Button send; - private Button cancel; + private Button send_modal; + private Button cancel_modal; + + private Button cancel_task; + private Button close_task; private PatternState hovered_pattern; + private MatterTask hovered_task; - private double dragger_position = 0; + private double scroller_position = 0; @Override protected void init() { @@ -67,6 +89,7 @@ public class MatterPanelScreen extends MatteryScreen { int x = (width - modal_width) / 2; int y = (height - modal_height) / 2; + // окно на создание запроса int top_level = 15; int button_width = 40; int right = 5 + button_width; @@ -101,10 +124,10 @@ public class MatterPanelScreen extends MatteryScreen { top_level += 24; right = 5 + button_width; - cancel = new Button(x + modal_width - right, y + top_level, button_width, 20, new TranslatableComponent("otm.container.matter_panel.cancel"), (btn) -> closePattern()); + cancel_modal = new Button(x + modal_width - right, y + top_level, button_width, 20, new TranslatableComponent("otm.container.matter_panel.cancel"), (btn) -> closePattern()); right += 2 + button_width; - send = new Button(x + modal_width - right, y + top_level, button_width, 20, new TranslatableComponent("otm.container.matter_panel.send"), (btn) -> onSend()); + send_modal = new Button(x + modal_width - right, y + top_level, button_width, 20, new TranslatableComponent("otm.container.matter_panel.send"), (btn) -> onSend()); inc_8.visible = false; inc_64.visible = false; @@ -114,8 +137,8 @@ public class MatterPanelScreen extends MatteryScreen { dec_64.visible = false; dec_256.visible = false; - send.visible = false; - cancel.visible = false; + send_modal.visible = false; + cancel_modal.visible = false; addWidget(input_amount); addWidget(inc_8); @@ -124,8 +147,24 @@ public class MatterPanelScreen extends MatteryScreen { addWidget(dec_8); addWidget(dec_64); addWidget(dec_256); - addWidget(send); - addWidget(cancel); + addWidget(send_modal); + addWidget(cancel_modal); + + // окно на отмену запроса + right = 5 + button_width; + top_level = modal_height - 8 - 20; + + close_task = new Button(x + modal_width - right, y + top_level, button_width, 20, new TranslatableComponent("otm.container.matter_panel.close"), (btn) -> closeTask()); + + button_width = 90; + right += 2 + button_width; + cancel_task = new Button(x + modal_width - right, y + top_level, button_width, 20, new TranslatableComponent("otm.container.matter_panel.cancel_task"), (btn) -> cancelTask()); + + close_task.visible = false; + cancel_task.visible = false; + + addWidget(close_task); + addWidget(cancel_task); } private void onChangeAmountPress(int amount) { @@ -164,14 +203,33 @@ public class MatterPanelScreen extends MatteryScreen { inc_64.visible = false; inc_256.visible = false; - send.visible = false; - cancel.visible = false; + send_modal.visible = false; + cancel_modal.visible = false; dec_8.visible = false; dec_64.visible = false; dec_256.visible = false; } + private void openTask(MatterTask task) { + open_task = task; + + close_task.visible = true; + cancel_task.visible = true; + } + + private void closeTask() { + open_task = null; + + close_task.visible = false; + cancel_task.visible = false; + } + + private void cancelTask() { + menu.requestTaskCancel(open_task.id()); + closeTask(); + } + @Override protected void containerTick() { super.containerTick(); @@ -182,7 +240,17 @@ public class MatterPanelScreen extends MatteryScreen { @Override public void resize(Minecraft p_96575_, int p_96576_, int p_96577_) { var input_amount = this.input_amount; + super.resize(p_96575_, p_96576_, p_96577_); + + if (open_task != null) { + openTask(open_task); + } + + if (open_pattern != null) { + openPattern(open_pattern); + } + if (input_amount != null) { this.input_amount.setValue(input_amount.getValue()); } @@ -209,8 +277,16 @@ public class MatterPanelScreen extends MatteryScreen { dec_256.render(stack, mouseX, mouseY, p_98421_); dec_8.render(stack, mouseX, mouseY, p_98421_); - send.render(stack, mouseX, mouseY, p_98421_); - cancel.render(stack, mouseX, mouseY, p_98421_); + send_modal.render(stack, mouseX, mouseY, p_98421_); + cancel_modal.render(stack, mouseX, mouseY, p_98421_); + + RenderSystem.depthFunc(GL_LESS); + } else if (open_task != null) { + RenderSystem.enableDepthTest(); + RenderSystem.depthFunc(GL_ALWAYS); + + cancel_task.render(stack, mouseX, mouseY, p_98421_); + close_task.render(stack, mouseX, mouseY, p_98421_); RenderSystem.depthFunc(GL_LESS); } @@ -226,6 +302,11 @@ public class MatterPanelScreen extends MatteryScreen { if (hovered_pattern != null) { get_list.add(new TranslatableComponent("otm.item.pattern.research", String.format("%.2f", hovered_pattern.research_percent() * 100d)).withStyle(ChatFormatting.AQUA)); + } else if (hovered_task != null) { + get_list.add(new TranslatableComponent("otm.gui.matter_task.total", hovered_task.total()).withStyle(ChatFormatting.GRAY)); + get_list.add(new TranslatableComponent("otm.gui.matter_task.required", hovered_task.required()).withStyle(ChatFormatting.GRAY)); + get_list.add(new TranslatableComponent("otm.gui.matter_task.in_progress", hovered_task.in_progress()).withStyle(ChatFormatting.GRAY)); + get_list.add(new TranslatableComponent("otm.gui.matter_task.finished", hovered_task.finished()).withStyle(ChatFormatting.GRAY)); } return get_list; @@ -244,6 +325,9 @@ public class MatterPanelScreen extends MatteryScreen { } else if (hovered_pattern != null) { this.renderTooltip(pose, new ItemStack(hovered_pattern.item(), 1), mouseX, mouseY); return; + } else if (hovered_task != null) { + this.renderTooltip(pose, new ItemStack(hovered_task.item(), hovered_task.total()), mouseX, mouseY); + return; } super.renderTooltip(pose, mouseX, mouseY); @@ -252,7 +336,7 @@ public class MatterPanelScreen extends MatteryScreen { private void openPattern(PatternState state) { open_pattern = state; input_amount.setValue("1"); - input_amount.setFocus(true); + // input_amount.setFocus(true); // bugged scrolling = false; input_amount.visible = true; @@ -264,26 +348,67 @@ public class MatterPanelScreen extends MatteryScreen { dec_64.visible = true; dec_256.visible = true; - send.visible = true; - cancel.visible = true; + send_modal.visible = true; + cancel_modal.visible = true; + } + + private double scroller_position_regular = 0; + private double scroller_position_tasks = 0; + + private void openTaskList() { + open_task_list = true; + scroller_position_regular = scroller_position; + scroller_position = scroller_position_tasks; + + } + + private void closeTaskList() { + open_task_list = false; + scroller_position_tasks = scroller_position; + scroller_position = scroller_position_regular; } @Override public boolean mouseClicked(double mouse_x, double mouse_y, int p_97750_) { - if (hovered_pattern != null && open_pattern == null) { - openPattern(hovered_pattern); - return true; + if (open_task == null && open_pattern == null) { + if (hovered_pattern != null) { + openPattern(hovered_pattern); + return true; + } else if (hovered_task != null) { + openTask(hovered_task); + return true; + } } - double div_scroll = menu.patterns.size() < 1 ? 1 : menu.patterns.size() - 1; + int button_x = leftPos + 157; + int button_y = topPos + 20 + (int) ((scroller_position / maxScroll()) * 145); + int button_width = 12; + int button_height = 15; - int scroll_x = leftPos + 157; - int scroll_y = topPos + 20 + (int) ((dragger_position / maxScroll()) * 145); + scrolling = maxScroll() > 0 && mouse_x >= button_x && button_x + button_width >= mouse_x && mouse_y >= button_y && button_y + button_height >= mouse_y; - if (maxScroll() > 0 && mouse_x >= scroll_x && scroll_x + 12 >= mouse_x && mouse_y >= scroll_y && scroll_y + 15 >= mouse_y) { - scrolling = true; - } else { - scrolling = false; + if (open_task == null && open_pattern == null) { + if (open_task_list) { + button_x = leftPos; + button_y = topPos - 28; + button_width = 28; + button_height = 30; + + if (mouse_x >= button_x && button_x + button_width >= mouse_x && mouse_y >= button_y && button_y + button_height >= mouse_y) { + closeTaskList(); + Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + } + } else { + button_x = leftPos + 28; + button_y = topPos - 28; + button_width = 28; + button_height = 30; + + if (mouse_x >= button_x && button_x + button_width >= mouse_x && mouse_y >= button_y && button_y + button_height >= mouse_y) { + openTaskList(); + Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + } + } } return super.mouseClicked(mouse_x, mouse_y, p_97750_); @@ -305,7 +430,7 @@ public class MatterPanelScreen extends MatteryScreen { return true; } - dragger_position = Math.max(0, Math.min(maxScroll(), dragger_position - scroll)); + scroller_position = Math.max(0, Math.min(maxScroll(), scroller_position - scroll)); return true; } @@ -314,11 +439,11 @@ public class MatterPanelScreen extends MatteryScreen { public boolean mouseDragged(double mouse_x, double mouse_y, int flag, double drag_x, double drag_y) { if (scrolling && maxScroll() > 0) { if (mouse_y < topPos + 20) { - dragger_position = 0; + scroller_position = 0; } else if (mouse_y > topPos + 20 + 160) { - dragger_position = maxScroll(); + scroller_position = maxScroll(); } else { - dragger_position = maxScroll() * (mouse_y - topPos - 20) / 160d; + scroller_position = maxScroll() * (mouse_y - topPos - 20) / 160d; } } @@ -328,6 +453,14 @@ public class MatterPanelScreen extends MatteryScreen { private boolean scrolling = false; private int maxScroll() { + if (open_task_list) { + if (menu.tasks.size() < 16) { + return 0; + } + + return (int) Math.floor(menu.tasks.size() / 8d - 2d); + } + if (menu.patterns.size() < 16) { return 0; } @@ -337,6 +470,18 @@ public class MatterPanelScreen extends MatteryScreen { @Override protected void renderBg(PoseStack pose, float p_97788_, int mouseX, int mouseY) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, CONTAINER_BACKGROUND()); + + if (open_task_list) { + // список паттернов + blit(pose, leftPos, topPos - 28, 176, 65, 28, 30); + } else { + // список задач + blit(pose, leftPos + 28, topPos - 28, 204, 65, 28, 30); + } + super.renderBg(pose, p_97788_, mouseX, mouseY); RenderSystem.setShader(GameRenderer::getPositionTexShader); @@ -345,17 +490,26 @@ public class MatterPanelScreen extends MatteryScreen { if (maxScroll() > 0) { if (scrolling) { - blit(pose, leftPos + 157, topPos + 20 + (int) ((dragger_position / maxScroll()) * 145), 188, 0, 12, 15); + blit(pose, leftPos + 157, topPos + 20 + (int) ((scroller_position / maxScroll()) * 145), 188, 0, 12, 15); } else { - blit(pose, leftPos + 157, topPos + 20 + (int) ((dragger_position / maxScroll()) * 145), 176, 0, 12, 15); + blit(pose, leftPos + 157, topPos + 20 + (int) ((scroller_position / maxScroll()) * 145), 176, 0, 12, 15); } } else { blit(pose, leftPos + 157, topPos + 20, 176, 0, 12, 15); } + if (open_task_list) { + // список задач + blit(pose, leftPos + 28, topPos - 28, 204, 33, 28, 32); + } else { + // список паттернов + blit(pose, leftPos, topPos - 28, 176, 33, 28, 32); + } + this.font.draw(pose, this.title, (float) (leftPos + this.titleLabelX), (float) (topPos + this.titleLabelY), 4210752); hovered_pattern = null; + hovered_task = null; int cells_width = 8; int cells_height = 9; @@ -367,34 +521,63 @@ public class MatterPanelScreen extends MatteryScreen { RenderSystem.enableDepthTest(); - for (int index = ((int) dragger_position) * 9; index < menu.patterns.size(); index++) { - var state = menu.patterns.get(index); - var itemstack = new ItemStack(state.item(), 1); + if (open_task_list) { + for (int index = ((int) scroller_position) * 9; index < menu.tasks.size(); index++) { + var state = menu.tasks.get(index); + var itemstack = new ItemStack(state.item(), Math.max(1, state.required())); - // player, itemstack, x, y, ?????????? - this.itemRenderer.renderAndDecorateItem(this.minecraft.player, itemstack, render_x, render_y, -1); - // font, itemstack, x, y, string - this.itemRenderer.renderGuiItemDecorations(this.font, itemstack, render_x, render_y, null); + // player, itemstack, x, y, ?????????? + this.itemRenderer.renderAndDecorateItem(this.minecraft.player, itemstack, render_x, render_y, -1); + // font, itemstack, x, y, string + this.itemRenderer.renderGuiItemDecorations(this.font, itemstack, render_x, render_y, null); - if (hovered_pattern == null && mouseX >= render_x && mouseX <= render_x + 16 && mouseY >= render_y && mouseY <= render_y + 16) { - hovered_pattern = state; + if (hovered_task == null && mouseX >= render_x && mouseX <= render_x + 16 && mouseY >= render_y && mouseY <= render_y + 16) { + hovered_task = state; + } + + cell_x++; + render_x += 18; + + if (cell_x >= cells_width) { + render_x = leftPos + 10; + render_y += 18; + cell_x = 0; + cell_y++; + + if (cell_y >= cells_height) + break; + } } + } else { + for (int index = ((int) scroller_position) * 9; index < menu.patterns.size(); index++) { + var state = menu.patterns.get(index); + var itemstack = new ItemStack(state.item(), 1); - cell_x++; - render_x += 18; + // player, itemstack, x, y, ?????????? + this.itemRenderer.renderAndDecorateItem(this.minecraft.player, itemstack, render_x, render_y, -1); + // font, itemstack, x, y, string + this.itemRenderer.renderGuiItemDecorations(this.font, itemstack, render_x, render_y, null); - if (cell_x >= cells_width) { - render_x = leftPos + 10; - render_y += 18; - cell_x = 0; - cell_y++; + if (hovered_pattern == null && mouseX >= render_x && mouseX <= render_x + 16 && mouseY >= render_y && mouseY <= render_y + 16) { + hovered_pattern = state; + } - if (cell_y >= cells_height) - break; + cell_x++; + render_x += 18; + + if (cell_x >= cells_width) { + render_x = leftPos + 10; + render_y += 18; + cell_x = 0; + cell_y++; + + if (cell_y >= cells_height) + break; + } } } - if (open_pattern != null) { + if (open_pattern != null || open_task != null) { RenderSystem.depthFunc(GL_ALWAYS); this.renderBackground(pose); @@ -417,18 +600,43 @@ public class MatterPanelScreen extends MatteryScreen { this.blit(pose, x, y + dy, 0, 197, modal_width, 4); - this.blit(pose, x + 6, input_amount.y, 176, 15, 18, 18); + if (open_pattern != null) { + // фон слота + this.blit(pose, x + 6, input_amount.y, 176, 15, 18, 18); + } else { + this.blit(pose, x + 6, y + 19, 176, 15, 18, 18); + } - var itemstack = new ItemStack(open_pattern.item(), 1); + ItemStack itemstack; + + if (open_pattern != null) { + itemstack = new ItemStack(open_pattern.item(), 1); + } else { + itemstack = new ItemStack(open_task.item(), 1); + } RenderSystem.enableDepthTest(); - // player, itemstack, x, y, ?????????? - this.itemRenderer.renderAndDecorateItem(this.minecraft.player, itemstack, x + 7, input_amount.y + 1, 100); - // font, itemstack, x, y, string - this.itemRenderer.renderGuiItemDecorations(this.font, itemstack, 0, 0, null); - this.font.draw(pose, new TranslatableComponent("otm.container.matter_panel.label"), (float) (x + 6), (float) (y + 5), 4210752); - this.font.draw(pose, new TranslatableComponent("otm.item.pattern.line", itemstack.getDisplayName(), String.format("%.2f", open_pattern.research_percent() * 100d)), (float) (x + 6), (float) (cancel.y), ChatFormatting.AQUA.getColor()); + if (open_pattern != null) { + // player, itemstack, x, y, ?????????? + this.itemRenderer.renderAndDecorateItem(this.minecraft.player, itemstack, x + 7, input_amount.y + 1, 100); + // font, itemstack, x, y, string + this.itemRenderer.renderGuiItemDecorations(this.font, itemstack, x + 7, input_amount.y + 1, null); + } else { + // player, itemstack, x, y, ?????????? + this.itemRenderer.renderAndDecorateItem(this.minecraft.player, itemstack, x + 7, y + 20, 100); + // font, itemstack, x, y, string + // this.itemRenderer.renderGuiItemDecorations(this.font, itemstack, x + 7, input_amount.y + 1, null); + } + + if (open_pattern != null) { + this.font.draw(pose, new TranslatableComponent("otm.container.matter_panel.label"), (float) (x + 6), (float) (y + 5), 4210752); + this.font.draw(pose, new TranslatableComponent("otm.item.pattern.line", itemstack.getDisplayName(), String.format("%.2f", open_pattern.research_percent() * 100d)), (float) (x + 6), (float) (cancel_modal.y), ChatFormatting.AQUA.getColor()); + } else { + this.font.draw(pose, new TranslatableComponent("otm.container.matter_panel.task"), (float) (x + 6), (float) (y + 5), 4210752); + this.font.draw(pose, new TranslatableComponent("otm.container.matter_panel.task_line", itemstack.getDisplayName(), open_task.in_progress(), open_task.finished(), open_task.total()), (float) (x + 27), (float) (y + 20), 4210752); + this.font.draw(pose, new TextComponent(open_task.id().toString().substring(0, 8) + "..."), (float) (x + 27), (float) (y + 30), 4210752); + } RenderSystem.depthFunc(GL_LESS); } diff --git a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json index 411294ded..603f083db 100644 --- a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json +++ b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json @@ -29,6 +29,11 @@ "otm.item.matter.infinite": "Stored matter: Infinity / Infinity", "otm.item.matter.normal": "Stored matter: %s / %s", + "otm.gui.matter_task.total": "Total: %s", + "otm.gui.matter_task.required": "Left to be done: %s", + "otm.gui.matter_task.in_progress": "In progress: %s", + "otm.gui.matter_task.finished": "Finished: %s", + "otm.suffix.merge": "%s %s", "otm.suffix.kilo": "%s k%s", @@ -66,8 +71,12 @@ "otm.container.matter_panel.increase_by": "+%s", "otm.container.matter_panel.decrease_by": "-%s", "otm.container.matter_panel.send": "Send", + "otm.container.matter_panel.close": "Close", + "otm.container.matter_panel.cancel_task": "Cancel task", "otm.container.matter_panel.cancel": "Cancel", "otm.container.matter_panel.label": "Replication request", + "otm.container.matter_panel.task": "Ongoing replication task", + "otm.container.matter_panel.task_line": "%s: %s | %s / %s", "item.overdrive_that_matters.pill_android": "Android pill", "item.overdrive_that_matters.pill_humane": "Humane pill", diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/matter_panel.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/matter_panel.png index 58546a545..c32d1892d 100644 Binary files a/src/main/resources/assets/overdrive_that_matters/textures/gui/matter_panel.png and b/src/main/resources/assets/overdrive_that_matters/textures/gui/matter_panel.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/matter_panel.xcf b/src/main/resources/assets/overdrive_that_matters/textures/gui/matter_panel.xcf index 2bfbeef51..5c393a8ae 100644 Binary files a/src/main/resources/assets/overdrive_that_matters/textures/gui/matter_panel.xcf and b/src/main/resources/assets/overdrive_that_matters/textures/gui/matter_panel.xcf differ