diff --git a/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b b/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b index beca45b50..9c274278b 100644 --- a/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b +++ b/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b @@ -1,3 +1,3 @@ -// 1.19.2 2025-01-20T07:59:27.474151 Tags for minecraft:item +// 1.19.2 2025-03-15T16:18:50.46663 Tags for minecraft:item de4b4f45ec18b2b1f0db1c36882981042e20ee23 data/advancedperipherals/tags/items/p2p_attunements/cable_p2p_tunnel.json 72eba3b11f69e16c87488f7c4ba7cfdad42c378e data/advancedperipherals/tags/items/smart_glasses.json diff --git a/src/generated/resources/.cache/2db41954e490230d51b10affff25ee2ee27b8d5b b/src/generated/resources/.cache/2db41954e490230d51b10affff25ee2ee27b8d5b index fe56a6ce0..8e30d22ee 100644 --- a/src/generated/resources/.cache/2db41954e490230d51b10affff25ee2ee27b8d5b +++ b/src/generated/resources/.cache/2db41954e490230d51b10affff25ee2ee27b8d5b @@ -1,2 +1,2 @@ -// 1.19.2 2024-05-28T14:53:16.655175 AP POI Type Tags +// 1.19.2 2025-03-15T16:18:50.465796 AP POI Type Tags d3d6b837660a4e213f287ad9d11e12368b90cd8e data/minecraft/tags/point_of_interest_type/acquirable_job_site.json diff --git a/src/generated/resources/.cache/5a761efb7472ef97566e41e81451930a004134bf b/src/generated/resources/.cache/5a761efb7472ef97566e41e81451930a004134bf index bc70b7af4..5483d6bb3 100644 --- a/src/generated/resources/.cache/5a761efb7472ef97566e41e81451930a004134bf +++ b/src/generated/resources/.cache/5a761efb7472ef97566e41e81451930a004134bf @@ -1,4 +1,4 @@ -// 1.19.2 2024-05-28T14:53:16.655476 Turtle Upgrades +// 1.19.2 2025-03-15T16:18:50.466321 Turtle Upgrades b8f19ae0fb5bb898facc08e3787e0f96c8211881 data/advancedperipherals/computercraft/turtle_upgrades/chatty_turtle.json fe98c60e7d61139aacf2d0872873e610aac8a37b data/advancedperipherals/computercraft/turtle_upgrades/chunky_turtle.json ae619da638ad89d7302d832d6c09e2c87401c539 data/advancedperipherals/computercraft/turtle_upgrades/compass_turtle.json diff --git a/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 b/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 index ac730fb60..ca3f6253d 100644 --- a/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 +++ b/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 @@ -1,4 +1,4 @@ -// 1.19.2 2025-01-16T15:46:41.860623 LootTables +// 1.19.2 2025-03-15T16:18:50.465594 LootTables 618b63c020ab64890c8a2d2506dd61cd30259a44 data/advancedperipherals/loot_tables/blocks/block_reader.json 0923665563d05307a7fa7d711a2d7a994a31eb6e data/advancedperipherals/loot_tables/blocks/chat_box.json bf2a80256cfba0bd8c0283d493882e5816882f1f data/advancedperipherals/loot_tables/blocks/colony_integrator.json diff --git a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e index c4a79999b..5b054c33c 100644 --- a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e +++ b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e @@ -1,4 +1,4 @@ -// 1.19.2 2024-05-28T14:53:16.657381 Recipes +// 1.19.2 2025-03-15T16:18:50.466743 Recipes 045608027e4a5ea2d7dee7f402346b8e69f21675 data/advancedperipherals/advancements/recipes/advancedperipheralstab/armor/smart_glasses_netherite.json db2dada2fdf42ca1bbf47f1eb075d1f9de89dfa8 data/advancedperipherals/advancements/recipes/advancedperipheralstab/block_reader.json 77c55e8500be4a344ca563a8bf7642257cdc7b8b data/advancedperipherals/advancements/recipes/advancedperipheralstab/chat_box.json diff --git a/src/generated/resources/.cache/ae219fa7c7d3297c14e454863eac3998a4eab78c b/src/generated/resources/.cache/ae219fa7c7d3297c14e454863eac3998a4eab78c index 5821f3f8a..4a3bf0dbb 100644 --- a/src/generated/resources/.cache/ae219fa7c7d3297c14e454863eac3998a4eab78c +++ b/src/generated/resources/.cache/ae219fa7c7d3297c14e454863eac3998a4eab78c @@ -1,4 +1,4 @@ -// 1.19.2 2025-01-25T19:46:21.23515 Pocket Computer Upgrades +// 1.19.2 2025-03-15T16:18:50.46512 Pocket Computer Upgrades b672635324c0df354e587efc81d0b19a581eae2f data/advancedperipherals/computercraft/pocket_upgrades/chatty_pocket.json 30b8f663613c7ce77048fd69631afcc11a682276 data/advancedperipherals/computercraft/pocket_upgrades/colony_pocket.json 661dc77bd0442bfb2a5ed80cff271071817bb22d data/advancedperipherals/computercraft/pocket_upgrades/distance_pocket.json diff --git a/src/generated/resources/.cache/b8526e444ae7356037f3a813274f6835d1f3dd16 b/src/generated/resources/.cache/b8526e444ae7356037f3a813274f6835d1f3dd16 index 01ccc33ab..005d0e248 100644 --- a/src/generated/resources/.cache/b8526e444ae7356037f3a813274f6835d1f3dd16 +++ b/src/generated/resources/.cache/b8526e444ae7356037f3a813274f6835d1f3dd16 @@ -1,4 +1,4 @@ -// 1.19.2 2024-05-28T14:53:16.658228 Block States: advancedperipherals +// 1.19.2 2025-03-15T16:18:50.466039 Block States: advancedperipherals 5e28ce1be9a6996d982641e5df1fa7162090b8cc assets/advancedperipherals/blockstates/block_reader.json f42bdde60f84fdb312f7cf3b2be461d9c11ebdc8 assets/advancedperipherals/blockstates/chat_box.json 1227aa092fcf1327547ace6ccc9db230e45891b0 assets/advancedperipherals/blockstates/colony_integrator.json diff --git a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 index c804ec644..577e18447 100644 --- a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 +++ b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 @@ -1,2 +1,2 @@ -// 1.19.2 2025-01-25T19:46:21.234203 Languages: en_us -e858500d72e9279f0fe0e8b2d03f94469c8d1f65 assets/advancedperipherals/lang/en_us.json +// 1.19.2 2025-03-15T16:18:50.465918 Languages: en_us +fe52123263b91f49093d74278e8709484e4dfe59 assets/advancedperipherals/lang/en_us.json diff --git a/src/generated/resources/.cache/f95c7003282837dabaa33e3ffceec4e6865b5218 b/src/generated/resources/.cache/f95c7003282837dabaa33e3ffceec4e6865b5218 index 872307de5..032d093dc 100644 --- a/src/generated/resources/.cache/f95c7003282837dabaa33e3ffceec4e6865b5218 +++ b/src/generated/resources/.cache/f95c7003282837dabaa33e3ffceec4e6865b5218 @@ -1,4 +1,4 @@ -// 1.19.2 2025-01-16T15:46:41.859383 Block tags +// 1.19.2 2025-03-15T16:18:50.466493 Block tags e1f71dcb4f9e7e36e29b0ad09d6520dc3adfa4a6 data/forge/tags/blocks/needs_wood_tool.json 03322cd493601129eaad6ba7c2a6d808023dfac1 data/minecraft/tags/blocks/mineable/pickaxe.json 277fe59db076a3eab3c97080531ad345f8ca5f3d data/minecraft/tags/blocks/needs_iron_tool.json diff --git a/src/generated/resources/assets/advancedperipherals/lang/en_us.json b/src/generated/resources/assets/advancedperipherals/lang/en_us.json index 3da1acb77..9a61a7d44 100644 --- a/src/generated/resources/assets/advancedperipherals/lang/en_us.json +++ b/src/generated/resources/assets/advancedperipherals/lang/en_us.json @@ -40,6 +40,7 @@ "item.advancedperipherals.end_automata_core": "End Automata Core", "item.advancedperipherals.hotkey_module": "Hotkey Module", "item.advancedperipherals.husbandry_automata_core": "Husbandry Automata Core", + "item.advancedperipherals.keyboard": "Wireless Keyboard", "item.advancedperipherals.memory_card": "Memory Card", "item.advancedperipherals.nightvision_module": "Night Vision Module", "item.advancedperipherals.overlay_module": "Overlay Module", @@ -49,6 +50,8 @@ "item.advancedperipherals.smart_glasses": "Smart Glasses", "item.advancedperipherals.smart_glasses_interface": "Smart Glasses Interface", "item.advancedperipherals.smart_glasses_netherite": "Netherite reinforced Smart Glasses", + "item.advancedperipherals.tooltip.binding.bound_to": "&7Bound to &b%s&7.", + "item.advancedperipherals.tooltip.binding.bound_to_glasses": "&7Bound to Glasses with id &b%s&7.", "item.advancedperipherals.tooltip.block_reader": "&7Reads nbt data of blocks to interact with blocks which do not have computer support.", "item.advancedperipherals.tooltip.chat_box": "&7Interacts with the ingame chat, can read and write messages.", "item.advancedperipherals.tooltip.chunk_controller": "&7A crafting ingredient for the Chunky Turtle.", @@ -63,7 +66,6 @@ "item.advancedperipherals.tooltip.inventory_manager": "&7This block is able to send or receive specific items from a player inventory.", "item.advancedperipherals.tooltip.me_bridge": "&7The ME Bridge interacts with Applied Energistics to manage your items.", "item.advancedperipherals.tooltip.memory_card": "&7Can save the rights of a player to use it in an inventory manager.", - "item.advancedperipherals.tooltip.memory_card.bound": "&7Bound to &b%s&7.", "item.advancedperipherals.tooltip.nbt_storage": "&7Acts like a storage disk. Can store nbt based data.", "item.advancedperipherals.tooltip.overpowered_end_automata_core": "&7Improved version of the end automata core, that provides some overpowered uses! Be careful, the upgrade is very fragile.", "item.advancedperipherals.tooltip.overpowered_husbandry_automata_core": "&7Improved version of the husbandry automata core, that provides some overpowered uses! Be careful, the upgrade is very fragile.", @@ -84,9 +86,13 @@ "pocket.advancedperipherals.environment_pocket": "Environment", "pocket.advancedperipherals.geoscanner_pocket": "Geo", "pocket.advancedperipherals.player_pocket": "Player Detector", - "text.advancedperipherals.added_player": "Added you to the memory card", "text.advancedperipherals.automata_core.feed_by_player": "You're trying to feed an entity to a soul, but your own body refuses to do this. Maybe something more mechanical can do this?", - "text.advancedperipherals.removed_player": "Cleared the memory card", + "text.advancedperipherals.bind_keyboard": "Bounded the keyboard to %s", + "text.advancedperipherals.bind_memorycard": "Bounded the memory card to you", + "text.advancedperipherals.cleared_keyboard": "Cleared the keyboard", + "text.advancedperipherals.cleared_memorycard": "Cleared the memory card", + "text.advancedperipherals.keyboard.close": "Press ESC to close the Keyboard Screen", + "text.advancedperipherals.keyboard_notbound": "The keyboard it not bound", "text.advancedperipherals.saddle_turtle.dismount_hint": "Controlling %1$s. Press %2$s and %3$s to dismount.", "text.advancedperipherals.smart_glasses.modules": "Modules", "text.advancedperipherals.smart_glasses.peripherals": "Peripherals", diff --git a/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json b/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json index 0578bfe7e..ffd23c4b9 100644 --- a/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json +++ b/src/generated/resources/data/forge/tags/blocks/needs_wood_tool.json @@ -1,6 +1,5 @@ { "values": [ - "advancedperipherals:peripheral_casing", - "advancedperipherals:colony_integrator" + "advancedperipherals:peripheral_casing" ] } \ No newline at end of file diff --git a/src/main/java/de/srendi/advancedperipherals/client/ClientRegistry.java b/src/main/java/de/srendi/advancedperipherals/client/ClientRegistry.java index 27c1f9e51..313cfc884 100644 --- a/src/main/java/de/srendi/advancedperipherals/client/ClientRegistry.java +++ b/src/main/java/de/srendi/advancedperipherals/client/ClientRegistry.java @@ -5,6 +5,7 @@ import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.client.renderer.DistanceDetectorRenderer; import de.srendi.advancedperipherals.client.screens.InventoryManagerScreen; +import de.srendi.advancedperipherals.client.screens.KeyboardScreen; import de.srendi.advancedperipherals.client.screens.SaddleTurtleScreen; import de.srendi.advancedperipherals.client.screens.SmartGlassesScreen; import de.srendi.advancedperipherals.client.smartglasses.OverlayModuleOverlay; @@ -42,6 +43,7 @@ public static void registerModels(ModelEvent.RegisterAdditional event) { @SubscribeEvent public static void onClientSetup(FMLClientSetupEvent event) { MenuScreens.register(APContainerTypes.INVENTORY_MANAGER_CONTAINER.get(), InventoryManagerScreen::new); + MenuScreens.register(APContainerTypes.KEYBOARD_CONTAINER.get(), KeyboardScreen::new); MenuScreens.register(APContainerTypes.SMART_GLASSES_CONTAINER.get(), SmartGlassesScreen::new); ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.CHUNKY_TURTLE.get(), TurtleUpgradeModeller.flatItem()); diff --git a/src/main/java/de/srendi/advancedperipherals/client/ClientWorker.java b/src/main/java/de/srendi/advancedperipherals/client/ClientWorker.java new file mode 100644 index 000000000..f29e94db7 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/ClientWorker.java @@ -0,0 +1,34 @@ +package de.srendi.advancedperipherals.client; + +import de.srendi.advancedperipherals.AdvancedPeripherals; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Mod.EventBusSubscriber(value = Dist.CLIENT, modid = AdvancedPeripherals.MOD_ID) +public class ClientWorker { + + private static final Map tasks = new ConcurrentHashMap<>(); + + /** + * This method will put a task to current tick's end. + * If a task with given identifier is already exists, the task will be replaced. + */ + public static void put(final String id, final Runnable task) { + tasks.put(id, task); + } + + @SubscribeEvent + public static void clientTick(TickEvent.ClientTickEvent event) { + if (event.phase == TickEvent.Phase.END) { + tasks.forEach((id, runnable) -> { + tasks.remove(id, runnable); + runnable.run(); + }); + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/screens/KeyboardScreen.java b/src/main/java/de/srendi/advancedperipherals/client/screens/KeyboardScreen.java new file mode 100644 index 000000000..669a3e068 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/screens/KeyboardScreen.java @@ -0,0 +1,246 @@ +package de.srendi.advancedperipherals.client.screens; + +import com.mojang.blaze3d.platform.InputConstants; +import com.mojang.blaze3d.platform.Window; +import com.mojang.blaze3d.vertex.PoseStack; +import dan200.computercraft.client.gui.ClientInputHandler; +import dan200.computercraft.client.gui.widgets.WidgetTerminal; +import dan200.computercraft.core.terminal.Terminal; +import dan200.computercraft.shared.computer.core.InputHandler; +import de.srendi.advancedperipherals.client.ClientWorker; +import de.srendi.advancedperipherals.common.container.KeyboardContainer; +import de.srendi.advancedperipherals.common.network.APNetworking; +import de.srendi.advancedperipherals.common.network.toserver.KeyboardMouseClickPacket; +import de.srendi.advancedperipherals.common.network.toserver.KeyboardMouseMovePacket; +import de.srendi.advancedperipherals.common.network.toserver.KeyboardMouseScrollPacket; +import net.minecraft.client.KeyMapping; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.MenuAccess; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Inventory; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.glfw.GLFW; + +/** + * A simple screen but without any rendering calls. Used to unlock the mouse so we can freely write stuff + *

+ * We just create a terminal which is used to forward all the key presses and mouse clicks but we don't render it. + */ +public class KeyboardScreen extends Screen implements MenuAccess { + + protected final KeyboardContainer keyboardContainer; + protected final InputHandler input; + private final Terminal terminalData; + private WidgetTerminal terminal; + private MouseState mouseState = MouseState.RELEASED; + private boolean captureMouse; + private boolean regrabingMouse; + private final byte[] lastPosLock = new byte[0]; + private double lastX = 0; + private double lastY = 0; + private double lastScroll = 0; + + public KeyboardScreen(KeyboardContainer keyboardContainer, Inventory inv, Component titleIn) { + super(titleIn); + this.keyboardContainer = keyboardContainer; + this.input = new ClientInputHandler(keyboardContainer); + this.terminalData = new Terminal(0, 0, false); + } + + @Override + public KeyboardContainer getMenu() { + return this.keyboardContainer; + } + + @Override + public void render(@NotNull PoseStack poseStack, int x, int y, float partialTicks) { + super.render(poseStack, x, y, partialTicks); + + Minecraft minecraft = Minecraft.getInstance(); + float scale = 2f; + int screenWidth = minecraft.getWindow().getGuiScaledWidth(); + // Make the text a bit smaller on small screens + if (screenWidth <= 1080) + scale = 1f; + + poseStack.scale(scale, scale, 1); + Component text = Component.translatable("text.advancedperipherals.keyboard.close"); + float textX = (screenWidth / 2f - minecraft.font.width(text) * scale / 2f) / scale; + minecraft.font.drawShadow(poseStack, text, textX, 1, 0xFFFFFF); + } + + @Override + protected void init() { + if (this.isCapturingMouse()) { + this.grabMouse(); + } else { + this.grabMouseWithControl(); + } + this.passEvents = true; + KeyMapping.releaseAll(); + + super.init(); + this.minecraft.keyboardHandler.setSendRepeatsToGui(true); + + this.terminal = addWidget(new WidgetTerminal(terminalData, new ClientInputHandler(this.keyboardContainer), 0, 0)); + this.terminal.visible = false; + this.terminal.active = false; + setFocused(this.terminal); + } + + @Override + public final void removed() { + if (this.regrabingMouse) { + return; + } + super.removed(); + if (this.minecraft.player != null) { + this.keyboardContainer.removed(this.minecraft.player); + } + this.minecraft.keyboardHandler.setSendRepeatsToGui(false); + } + + @Override + public void onClose() { + // Don't allow closing using standard keys like E. Closing using ESCAPE is still possible due to the keyPressed method + } + + @Override + public boolean isPauseScreen() { + return false; + } + + @Override + public void mouseMoved(double x, double y) { + if (this.mouseState != MouseState.CAPTURE) { + return; + } + ClientWorker.put("mouse_move", () -> { + synchronized (this.lastPosLock) { + double dx = x - this.lastX; + double dy = y - this.lastY; + APNetworking.sendToServer(new KeyboardMouseMovePacket(dx, dy)); + this.lastX = x; + this.lastY = y; + } + }); + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + if (this.mouseState != MouseState.CAPTURE) { + return false; + } + APNetworking.sendToServer(new KeyboardMouseClickPacket(button, false)); + return true; + } + + @Override + public boolean mouseReleased(double x, double y, int button) { + if (this.mouseState != MouseState.CAPTURE) { + return false; + } + APNetworking.sendToServer(new KeyboardMouseClickPacket(button, true)); + return true; + } + + @Override + public boolean mouseScrolled(double x, double y, double direction) { + this.lastScroll += direction; + int scrolled = (int) this.lastScroll; + if (scrolled == 0) { + return true; + } + if (this.mouseState == MouseState.CAPTURE) { + ClientWorker.put("mouse_scroll", () -> { + if (this.mouseState != MouseState.CAPTURE) { + return; + } + this.lastScroll -= scrolled; + APNetworking.sendToServer(new KeyboardMouseScrollPacket(scrolled)); + }); + } else { + this.lastScroll -= scrolled; + minecraft.player.getInventory().swapPaint(scrolled); + } + return true; + } + + @Override + public final boolean keyPressed(int key, int scancode, int modifiers) { + if (key == GLFW.GLFW_KEY_ESCAPE) { + if (this.minecraft.player != null) { + this.minecraft.player.closeContainer(); + } else { + super.onClose(); + } + return true; + } + // Forward the tab key to the terminal, rather than moving between controls. + if (key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminal) { + return getFocused().keyPressed(key, scancode, modifiers); + } + + return super.keyPressed(key, scancode, modifiers); + } + + public boolean isCapturingMouse() { + return this.captureMouse; + } + + public void setCaptureMouse(boolean enable) { + this.captureMouse = enable; + if (enable) { + this.grabMouse(); + } else { + this.grabMouseWithControl(); + } + } + + private void grabMouseWithControl() { + if (this.mouseState == MouseState.NORMAL) { + return; + } + this.releaseMouse(); + this.regrabingMouse = true; + this.minecraft.mouseHandler.grabMouse(); + this.regrabingMouse = false; + this.minecraft.screen = this; + this.mouseState = MouseState.NORMAL; + } + + private void grabMouse() { + if (this.minecraft.mouseHandler.isMouseGrabbed()) { + this.minecraft.mouseHandler.releaseMouse(); + } + Window window = this.minecraft.getWindow(); + synchronized (this.lastPosLock) { + this.lastX = window.getScreenWidth() / 2; + this.lastY = window.getScreenHeight() / 2; + InputConstants.grabOrReleaseMouse(window.getWindow(), InputConstants.CURSOR_DISABLED, this.lastX, this.lastY); + } + this.mouseState = MouseState.CAPTURE; + } + + private void releaseMouse() { + if (this.mouseState == MouseState.RELEASED) { + return; + } + if (this.minecraft.mouseHandler.isMouseGrabbed()) { + this.minecraft.mouseHandler.releaseMouse(); + return; + } + Window window = this.minecraft.getWindow(); + synchronized (this.lastPosLock) { + this.lastX = window.getScreenWidth() / 2; + this.lastY = window.getScreenHeight() / 2; + InputConstants.grabOrReleaseMouse(window.getWindow(), InputConstants.CURSOR_NORMAL, this.lastX, this.lastY); + } + this.mouseState = MouseState.RELEASED; + } + + private enum MouseState { + RELEASED, NORMAL, CAPTURE + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/container/KeyboardContainer.java b/src/main/java/de/srendi/advancedperipherals/common/container/KeyboardContainer.java new file mode 100644 index 000000000..06adb95e5 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/container/KeyboardContainer.java @@ -0,0 +1,96 @@ +package de.srendi.advancedperipherals.common.container; + +import dan200.computercraft.shared.computer.core.ServerComputer; +import dan200.computercraft.shared.computer.core.ServerContext; +import dan200.computercraft.shared.computer.menu.ComputerMenu; +import dan200.computercraft.shared.computer.menu.ServerInputHandler; +import dan200.computercraft.shared.computer.menu.ServerInputState; +import dan200.computercraft.shared.computer.terminal.TerminalState; +import de.srendi.advancedperipherals.common.container.base.BaseContainer; +import de.srendi.advancedperipherals.common.items.KeyboardItem; +import de.srendi.advancedperipherals.common.setup.APContainerTypes; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.server.ServerLifecycleHooks; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class KeyboardContainer extends BaseContainer implements ComputerMenu { + + @Nullable + private final ServerInputState input; + private final ItemStack keyboardItem; + @Nullable + private ServerComputer computer; + + public KeyboardContainer(int id, Inventory inventory, BlockPos pos, Level level, ItemStack keyboardItem) { + this(id, inventory, pos, level, keyboardItem, null); + } + + public KeyboardContainer(int id, Inventory inventory, BlockPos pos, Level level, ItemStack keyboardItem, ServerComputer computer) { + super(APContainerTypes.KEYBOARD_CONTAINER.get(), id, inventory, pos, level); + this.keyboardItem = keyboardItem; + + if (level.isClientSide) { + this.input = null; + this.computer = null; + return; + } + this.input = new ServerInputState<>(this); + this.computer = computer; + if (computer != null) { + return; + } + CompoundTag data = keyboardItem.getOrCreateTag(); + if (!data.contains(KeyboardItem.BIND_TAG)) { + return; + } + // Cannot use instance ID here since they will change after reload the block + int computerId = data.getInt(KeyboardItem.BIND_TAG); + for (ServerComputer computr : ServerContext.get(ServerLifecycleHooks.getCurrentServer()).registry().getComputers()) { + if (computr.getID() == computerId) { + this.computer = computr; + break; + } + } + } + + public ItemStack getKeyboardItem() { + return this.keyboardItem; + } + + @Override + public boolean stillValid(@NotNull Player player) { + return true; + } + + @Override + public void removed(Player player) { + super.removed(player); + if (player instanceof ServerPlayer) { + computer.queueEvent("keyboard_closed"); + } + } + + @Nullable + @Override + public ServerComputer getComputer() { + return computer; + } + + @Nullable + @Override + public ServerInputHandler getInput() { + return input; + } + + @Override + public void updateTerminal(TerminalState state) { + + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/container/base/BaseContainer.java b/src/main/java/de/srendi/advancedperipherals/common/container/base/BaseContainer.java index 9d11ca901..bbf106b4e 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/container/base/BaseContainer.java +++ b/src/main/java/de/srendi/advancedperipherals/common/container/base/BaseContainer.java @@ -10,6 +10,7 @@ import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.SlotItemHandler; import net.minecraftforge.items.wrapper.InvWrapper; @@ -23,8 +24,16 @@ public abstract class BaseContainer extends AbstractContainerMenu { protected BaseContainer(@Nullable MenuType type, int id, Inventory inventory, BlockPos pos, Level world) { super(type, id); this.inventory = new InvWrapper(inventory); - if (world != null) - this.tileEntity = (PeripheralBlockEntity) world.getBlockEntity(pos); + if (world != null) { + BlockEntity blockEntity = world.getBlockEntity(pos); + // for player containers, pos is the position of the player + // We don't actual need a block entity for player containers + // But if a player stands for example on a mekanism cable, setting the tileEntity by casting and without a check + // would prevent opening the screen + if (blockEntity instanceof PeripheralBlockEntity peripheralBlockEntity) { + tileEntity = peripheralBlockEntity; + } + } } @Override diff --git a/src/main/java/de/srendi/advancedperipherals/common/data/EnUsLanguageProvider.java b/src/main/java/de/srendi/advancedperipherals/common/data/EnUsLanguageProvider.java index 832cf08be..4b69cd179 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/data/EnUsLanguageProvider.java +++ b/src/main/java/de/srendi/advancedperipherals/common/data/EnUsLanguageProvider.java @@ -44,6 +44,7 @@ private void addItems() { addItem(APItems.CHUNK_CONTROLLER, "Chunk Controller"); addItem(APItems.COMPUTER_TOOL, "Computer Tool"); addItem(APItems.HOTKEY_MODULE, "Hotkey Module"); + addItem(APItems.KEYBOARD, "Wireless Keyboard"); addItem(APItems.MEMORY_CARD, "Memory Card"); addItem(APItems.NIGHT_VISION_MODULE, "Night Vision Module"); addItem(APItems.OVERLAY_MODULE, "Overlay Module"); @@ -147,13 +148,18 @@ private void addTooltips() { addTooltip(APItems.COMPUTER_TOOL.get(), "&7This tool was made to tune our blocks. But for now, it's just a blue useless wrench."); addTooltip(APItems.MEMORY_CARD.get(), "&7Can save the rights of a player to use it in an inventory manager."); - addTooltip("memory_card.bound", "&7Bound to &b%s&7."); + addTooltip("binding.bound_to", "&7Bound to &b%s&7."); + } private void addTexts() { - addText("removed_player", "Cleared the memory card"); - addText("added_player", "Added you to the memory card"); addText("automata_core.feed_by_player", "You're trying to feed an entity to a soul, but your own body refuses to do this. Maybe something more mechanical can do this?"); + addText("keyboard.close", "Press ESC to close the Keyboard Screen"); + addText("cleared_memorycard", "Cleared the memory card"); + addText("bind_memorycard", "Bounded the memory card to you"); + addText("keyboard_notbound", "The keyboard it not bound"); + addText("bind_keyboard", "Bounded the keyboard to %s"); + addText("cleared_keyboard", "Cleared the keyboard"); addText("smart_glasses.peripherals", "Peripherals"); addText("smart_glasses.modules", "Modules"); addText("saddle_turtle.dismount_hint", "Controlling %1$s. Press %2$s and %3$s to dismount."); diff --git a/src/main/java/de/srendi/advancedperipherals/common/items/KeyboardItem.java b/src/main/java/de/srendi/advancedperipherals/common/items/KeyboardItem.java new file mode 100644 index 000000000..cb5045a06 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/items/KeyboardItem.java @@ -0,0 +1,195 @@ +package de.srendi.advancedperipherals.common.items; + +import dan200.computercraft.shared.computer.blocks.TileComputerBase; +import dan200.computercraft.shared.computer.core.ServerComputer; +import de.srendi.advancedperipherals.client.KeyBindings; +import de.srendi.advancedperipherals.common.container.KeyboardContainer; +import de.srendi.advancedperipherals.common.items.base.BaseItem; +import de.srendi.advancedperipherals.common.items.base.IInventoryItem; +import de.srendi.advancedperipherals.common.network.APNetworking; +import de.srendi.advancedperipherals.common.network.toserver.GlassesHotkeyPacket; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleItem; +import de.srendi.advancedperipherals.common.smartglasses.modules.keyboard.KeyboardModule; +import de.srendi.advancedperipherals.common.util.EnumColor; +import de.srendi.advancedperipherals.common.util.SideHelper; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class KeyboardItem extends BaseItem implements IInventoryItem, IModuleItem { + + public static final String BIND_TAG = "bind"; + public static final String OPENING_TAG = "KeyboardOpening"; + + public KeyboardItem() { + super(new Properties().stacksTo(1)); + } + + @Override + public boolean isEnabled() { + return true; + } + + @NotNull + @Override + public InteractionResult useOn(UseOnContext context) { + Player player = context.getPlayer(); + if (player == null) + return InteractionResult.PASS; + + if (SideHelper.isClientPlayer(player)) + return InteractionResult.PASS; + + if (!player.isShiftKeyDown()) + return InteractionResult.PASS; + + BlockEntity entity = context.getLevel().getBlockEntity(context.getClickedPos()); + if (entity instanceof TileComputerBase) { + bind(player, context.getItemInHand(), context.getLevel(), context.getClickedPos()); + } else { + clear(player, context.getItemInHand()); + } + return super.useOn(context); + } + + @Override + public void inventoryTick(ItemStack itemStack, Level level, Entity entity, int inventorySlot, boolean isCurrentItem, @Nullable SmartGlassesAccess access, @Nullable IModule module) { + if (!level.isClientSide()) { + itemStack.removeTagKey(BIND_TAG); + return; + } + if (!(entity instanceof LocalPlayer player)) { + return; + } + boolean pressed = KeyBindings.GLASSES_HOTKEY_KEYBINDING.isDown(); + CompoundTag data = itemStack.getOrCreateTag(); + if (data.getBoolean(OPENING_TAG) == pressed) { + return; + } + data.putBoolean(OPENING_TAG, pressed); + if (!pressed) { + return; + } + if (player.containerMenu instanceof KeyboardContainer openedKeyboard && openedKeyboard.getKeyboardItem().equals(itemStack)) { + return; + } + APNetworking.sendToServer(new GlassesHotkeyPacket("", -1)); + return; + } + + @Override + public InteractionResultHolder use(Level worldIn, Player playerIn, InteractionHand handIn) { + if (playerIn.level.isClientSide()) { + return new InteractionResultHolder<>(InteractionResult.PASS, playerIn.getItemInHand(handIn)); + } + // Used to prevent the menu from opening when we just want to bind/unbind the keyboard + if (playerIn.isShiftKeyDown()) { + return new InteractionResultHolder<>(InteractionResult.PASS, playerIn.getItemInHand(handIn)); + } + CompoundTag data = playerIn.getItemInHand(handIn).getTag(); + if (data == null || !data.contains(BIND_TAG)) { + playerIn.displayClientMessage(EnumColor.buildTextComponent(Component.translatable("text.advancedperipherals.keyboard_notbound")), false); + return new InteractionResultHolder<>(InteractionResult.PASS, playerIn.getItemInHand(handIn)); + } + // Run the super use which handles the IInventoryItem stuff to actually open the container + return super.use(worldIn, playerIn, handIn); + } + + @Override + public void appendHoverText(ItemStack stack, @Nullable Level levelIn, List tooltip, TooltipFlag flagIn) { + super.appendHoverText(stack, levelIn, tooltip, flagIn); + CompoundTag data = stack.getOrCreateTag(); + if (data.contains(BIND_TAG)) { + tooltip.add(EnumColor.buildTextComponent(Component.translatable("item.advancedperipherals.tooltip.binding.bound_to", data.getInt(BIND_TAG)))); + } + } + + private void bind(Player player, ItemStack itemStack, Level world, BlockPos pos) { + CompoundTag data = itemStack.getOrCreateTag(); + data.remove(BIND_TAG); + + if (!(world.getBlockEntity(pos) instanceof TileComputerBase computer)) { + // TODO: should it show bind failed message? + return; + } + + int id = computer.getComputerID(); + if (id < 0) { + // TODO: show computer not initialized error? + return; + } + data.putInt(BIND_TAG, id); + + player.displayClientMessage(EnumColor.buildTextComponent(Component.translatable("text.advancedperipherals.bind_keyboard", pos.toShortString())), true); + } + + private void clear(Player player, ItemStack itemStack) { + CompoundTag data = itemStack.getOrCreateTag(); + data.remove(BIND_TAG); + + player.displayClientMessage(EnumColor.buildTextComponent(Component.translatable("text.advancedperipherals.cleared_keyboard")), true); + } + + @Override + public MenuProvider createContainer(Player playerEntity, ItemStack itemStack) { + return new MenuProvider() { + @NotNull + @Override + public Component getDisplayName() { + return Component.empty(); + } + + @Override + public AbstractContainerMenu createMenu(int pContainerId, @NotNull Inventory playerInv, @NotNull Player player) { + return new KeyboardContainer(pContainerId, playerInv, player.blockPosition(), player.getLevel(), itemStack); + } + }; + } + + public MenuProvider createContainerWithComputer(Player playerEntity, ItemStack itemStack, ServerComputer computer) { + return new MenuProvider() { + @NotNull + @Override + public Component getDisplayName() { + return Component.empty(); + } + + @Override + public AbstractContainerMenu createMenu(int pContainerId, @NotNull Inventory playerInv, @NotNull Player player) { + return new KeyboardContainer(pContainerId, playerInv, player.blockPosition(), player.getLevel(), itemStack, computer); + } + }; + } + + @Override + public void writeContainerData(Player player, ItemStack stack, FriendlyByteBuf buf) { + buf.writeBlockPos(player.blockPosition()); + buf.writeItem(stack); + } + + @Override + public IModule createModule(SmartGlassesAccess access, ItemStack stack) { + return new KeyboardModule(this, stack); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/items/MemoryCardItem.java b/src/main/java/de/srendi/advancedperipherals/common/items/MemoryCardItem.java index 0bd126d4b..469fd24bf 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/items/MemoryCardItem.java +++ b/src/main/java/de/srendi/advancedperipherals/common/items/MemoryCardItem.java @@ -30,9 +30,8 @@ public boolean isEnabled() { public void appendHoverText(ItemStack stack, @Nullable Level levelIn, List tooltip, TooltipFlag flagIn) { super.appendHoverText(stack, levelIn, tooltip, flagIn); CompoundTag data = stack.getOrCreateTag(); - // TODO <0.8>: remove the owner name field - if (data.contains("ownerId") && data.contains("owner")) { - tooltip.add(EnumColor.buildTextComponent(Component.translatable("item.advancedperipherals.tooltip.memory_card.bound", data.getString("owner")))); + if (data.contains("ownerId")) { + tooltip.add(EnumColor.buildTextComponent(Component.translatable("item.advancedperipherals.tooltip.binding.bound_to", data.getString("ownerId")))); } } @@ -41,15 +40,12 @@ public InteractionResultHolder use(Level worldIn, Player playerIn, In if (!worldIn.isClientSide) { ItemStack stack = playerIn.getItemInHand(handIn); CompoundTag data = stack.getOrCreateTag(); - // TODO <0.8>: remove the owner name field - if (data.contains("ownerId") || data.contains("owner")) { - playerIn.displayClientMessage(Component.translatable("text.advancedperipherals.removed_player"), true); + if (data.contains("ownerId")) { + playerIn.displayClientMessage(EnumColor.buildTextComponent(Component.translatable("text.advancedperipherals.cleared_memorycard")), true); data.remove("ownerId"); - data.remove("owner"); } else { - playerIn.displayClientMessage(Component.translatable("text.advancedperipherals.added_player"), true); + playerIn.displayClientMessage(EnumColor.buildTextComponent(Component.translatable("text.advancedperipherals.bind_memorycard")), true); data.putUUID("ownerId", playerIn.getUUID()); - data.putString("owner", playerIn.getName().getString()); } } return super.use(worldIn, playerIn, handIn); diff --git a/src/main/java/de/srendi/advancedperipherals/common/items/base/BaseItem.java b/src/main/java/de/srendi/advancedperipherals/common/items/base/BaseItem.java index bc95f02d1..7f3743614 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/items/base/BaseItem.java +++ b/src/main/java/de/srendi/advancedperipherals/common/items/base/BaseItem.java @@ -34,12 +34,14 @@ public BaseItem() { @Override public InteractionResultHolder use(Level worldIn, Player playerIn, InteractionHand handIn) { - if (worldIn.isClientSide) - return new InteractionResultHolder<>(InteractionResult.PASS, playerIn.getItemInHand(handIn)); + ItemStack stack = playerIn.getItemInHand(handIn); + if (worldIn.isClientSide) { + return new InteractionResultHolder<>(InteractionResult.PASS, stack); + } if (this instanceof IInventoryItem inventoryItem) { ServerPlayer serverPlayerEntity = (ServerPlayer) playerIn; - ItemStack stack = playerIn.getItemInHand(handIn); - NetworkHooks.openScreen(serverPlayerEntity, inventoryItem.createContainer(playerIn, stack), buf -> buf.writeItem(stack)); + NetworkHooks.openScreen(serverPlayerEntity, inventoryItem.createContainer(playerIn, stack), buf -> inventoryItem.writeContainerData(playerIn, stack, buf)); + return new InteractionResultHolder<>(InteractionResult.SUCCESS, stack); } return super.use(worldIn, playerIn, handIn); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/items/base/IInventoryItem.java b/src/main/java/de/srendi/advancedperipherals/common/items/base/IInventoryItem.java index 7d4ff67f6..1897596e9 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/items/base/IInventoryItem.java +++ b/src/main/java/de/srendi/advancedperipherals/common/items/base/IInventoryItem.java @@ -1,11 +1,12 @@ package de.srendi.advancedperipherals.common.items.base; +import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; public interface IInventoryItem { + MenuProvider createContainer(Player player, ItemStack itemStack); - MenuProvider createContainer(Player playerEntity, ItemStack itemStack); - + void writeContainerData(Player player, ItemStack itemStack, FriendlyByteBuf buf); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/APNetworking.java b/src/main/java/de/srendi/advancedperipherals/common/network/APNetworking.java index d007a4b1d..5738f2553 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/network/APNetworking.java +++ b/src/main/java/de/srendi/advancedperipherals/common/network/APNetworking.java @@ -2,6 +2,7 @@ import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.network.base.IPacket; +import de.srendi.advancedperipherals.common.network.toclient.KeyboardMouseCapturePacket; import de.srendi.advancedperipherals.common.network.toclient.RenderableObjectBulkSyncPacket; import de.srendi.advancedperipherals.common.network.toclient.RenderableObjectClearPacket; import de.srendi.advancedperipherals.common.network.toclient.RenderableObjectDeletePacket; @@ -9,6 +10,9 @@ import de.srendi.advancedperipherals.common.network.toclient.SaddleTurtleInfoPacket; import de.srendi.advancedperipherals.common.network.toclient.ToastToClientPacket; import de.srendi.advancedperipherals.common.network.toserver.GlassesHotkeyPacket; +import de.srendi.advancedperipherals.common.network.toserver.KeyboardMouseClickPacket; +import de.srendi.advancedperipherals.common.network.toserver.KeyboardMouseMovePacket; +import de.srendi.advancedperipherals.common.network.toserver.KeyboardMouseScrollPacket; import de.srendi.advancedperipherals.common.network.toserver.SaddleTurtleControlPacket; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; @@ -38,13 +42,18 @@ public class APNetworking { private static int index = 0; public static void init() { + registerServerToClient(KeyboardMouseCapturePacket.class, KeyboardMouseCapturePacket::decode); + registerServerToClient(RenderableObjectBulkSyncPacket.class, RenderableObjectBulkSyncPacket::decode); + registerServerToClient(RenderableObjectClearPacket.class, RenderableObjectClearPacket::decode); + registerServerToClient(RenderableObjectDeletePacket.class, RenderableObjectDeletePacket::decode); + registerServerToClient(RenderableObjectSyncPacket.class, RenderableObjectSyncPacket::decode); registerServerToClient(SaddleTurtleInfoPacket.class, SaddleTurtleInfoPacket::decode); registerServerToClient(ToastToClientPacket.class, ToastToClientPacket::decode); - registerServerToClient(RenderableObjectSyncPacket.class, RenderableObjectSyncPacket::decode); - registerServerToClient(RenderableObjectDeletePacket.class, RenderableObjectDeletePacket::decode); - registerServerToClient(RenderableObjectClearPacket.class, RenderableObjectClearPacket::decode); - registerServerToClient(RenderableObjectBulkSyncPacket.class, RenderableObjectBulkSyncPacket::decode); + registerClientToServer(GlassesHotkeyPacket.class, GlassesHotkeyPacket::decode); + registerClientToServer(KeyboardMouseClickPacket.class, KeyboardMouseClickPacket::decode); + registerClientToServer(KeyboardMouseMovePacket.class, KeyboardMouseMovePacket::decode); + registerClientToServer(KeyboardMouseScrollPacket.class, KeyboardMouseScrollPacket::decode); registerClientToServer(SaddleTurtleControlPacket.class, SaddleTurtleControlPacket::decode); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toclient/KeyboardMouseCapturePacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/KeyboardMouseCapturePacket.java new file mode 100644 index 000000000..026f24151 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/KeyboardMouseCapturePacket.java @@ -0,0 +1,33 @@ +package de.srendi.advancedperipherals.common.network.toclient; + +import de.srendi.advancedperipherals.client.screens.KeyboardScreen; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +public class KeyboardMouseCapturePacket implements IPacket { + + private final boolean enable; + + public KeyboardMouseCapturePacket(boolean enable) { + this.enable = enable; + } + + @Override + public void handle(NetworkEvent.Context context) { + if (!(Minecraft.getInstance().screen instanceof KeyboardScreen screen)) { + return; + } + screen.setCaptureMouse(this.enable); + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeBoolean(this.enable); + } + + public static KeyboardMouseCapturePacket decode(FriendlyByteBuf buffer) { + return new KeyboardMouseCapturePacket(buffer.readBoolean()); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toserver/GlassesHotkeyPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/GlassesHotkeyPacket.java index c6f5506ed..6892e9eee 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/network/toserver/GlassesHotkeyPacket.java +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/GlassesHotkeyPacket.java @@ -2,7 +2,9 @@ import de.srendi.advancedperipherals.common.items.SmartGlassesItem; import de.srendi.advancedperipherals.common.network.base.IPacket; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesComputer; +import de.srendi.advancedperipherals.common.smartglasses.modules.keyboard.KeyboardModule; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; @@ -10,16 +12,12 @@ import net.minecraftforge.network.NetworkEvent; import net.minecraftforge.server.ServerLifecycleHooks; -import java.util.UUID; - public class GlassesHotkeyPacket implements IPacket { - private final UUID player; private final String keyBind; private final int keyPressDuration; - public GlassesHotkeyPacket(UUID player, String keyBind, int keyPressDuration) { - this.player = player; + public GlassesHotkeyPacket(String keyBind, int keyPressDuration) { this.keyBind = keyBind; this.keyPressDuration = keyPressDuration; } @@ -28,28 +26,47 @@ public GlassesHotkeyPacket(UUID player, String keyBind, int keyPressDuration) { public void handle(NetworkEvent.Context context) { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); - ServerPlayer serverPlayer = server.getPlayerList().getPlayer(player); - if (serverPlayer == null) + ServerPlayer serverPlayer = context.getSender(); + if (serverPlayer == null) { return; + } + ItemStack smartGlasses = null; + SmartGlassesComputer computer = null; for (ItemStack stack : serverPlayer.getAllSlots()) { if (stack.getItem() instanceof SmartGlassesItem) { - SmartGlassesComputer computer = SmartGlassesItem.getServerComputer(server, stack); - - if (computer != null) - computer.queueEvent("glassesKeyPressed", new Object[]{keyBind, keyPressDuration}); + computer = SmartGlassesItem.getServerComputer(server, stack); + if (computer != null) { + smartGlasses = stack; + break; + } } } + if (computer == null) { + return; + } + if (keyPressDuration >= 0) { + computer.queueEvent("glasses_key_pressed", new Object[]{keyBind, keyPressDuration}); + return; + } + SmartGlassesAccess glasses = computer.getSmartGlassesAccess(); + computer.getModules().values() + .stream() + .filter(KeyboardModule.class::isInstance) + .map(KeyboardModule.class::cast) + .findFirst() + .ifPresent((keyboardModule) -> { + keyboardModule.openKeyboard(glasses); + }); } @Override public void encode(FriendlyByteBuf buffer) { - buffer.writeUUID(player); buffer.writeUtf(keyBind); buffer.writeInt(keyPressDuration); } public static GlassesHotkeyPacket decode(FriendlyByteBuf buffer) { - return new GlassesHotkeyPacket(buffer.readUUID(), buffer.readUtf(), buffer.readInt()); + return new GlassesHotkeyPacket(buffer.readUtf(), buffer.readInt()); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toserver/KeyboardMouseClickPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/KeyboardMouseClickPacket.java new file mode 100644 index 000000000..9c6acb829 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/KeyboardMouseClickPacket.java @@ -0,0 +1,52 @@ +package de.srendi.advancedperipherals.common.network.toserver; + +import de.srendi.advancedperipherals.common.items.SmartGlassesItem; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesComputer; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class KeyboardMouseClickPacket implements IPacket { + + private final int button; + private final boolean isRelease; + + public KeyboardMouseClickPacket(int button, boolean isRelease) { + this.button = button; + this.isRelease = isRelease; + } + + @Override + public void handle(NetworkEvent.Context context) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + + ServerPlayer serverPlayer = context.getSender(); + if (serverPlayer == null) { + return; + } + + for (ItemStack stack : serverPlayer.getAllSlots()) { + if (stack.getItem() instanceof SmartGlassesItem) { + SmartGlassesComputer computer = SmartGlassesItem.getServerComputer(server, stack); + if (computer != null) { + computer.queueEvent(isRelease ? "player_mouse_up" : "player_mouse_click", new Object[]{button}); + break; + } + } + } + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeVarInt(button); + buffer.writeBoolean(isRelease); + } + + public static KeyboardMouseClickPacket decode(FriendlyByteBuf buffer) { + return new KeyboardMouseClickPacket(buffer.readVarInt(), buffer.readBoolean()); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toserver/KeyboardMouseMovePacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/KeyboardMouseMovePacket.java new file mode 100644 index 000000000..27e8783fd --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/KeyboardMouseMovePacket.java @@ -0,0 +1,52 @@ +package de.srendi.advancedperipherals.common.network.toserver; + +import de.srendi.advancedperipherals.common.items.SmartGlassesItem; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesComputer; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class KeyboardMouseMovePacket implements IPacket { + + private final double dx; + private final double dy; + + public KeyboardMouseMovePacket(double dx, double dy) { + this.dx = dx; + this.dy = dy; + } + + @Override + public void handle(NetworkEvent.Context context) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + + ServerPlayer serverPlayer = context.getSender(); + if (serverPlayer == null) { + return; + } + + for (ItemStack stack : serverPlayer.getAllSlots()) { + if (stack.getItem() instanceof SmartGlassesItem) { + SmartGlassesComputer computer = SmartGlassesItem.getServerComputer(server, stack); + if (computer != null) { + computer.queueEvent("player_mouse_move", new Object[]{dx, dy}); + break; + } + } + } + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeDouble(dx); + buffer.writeDouble(dy); + } + + public static KeyboardMouseMovePacket decode(FriendlyByteBuf buffer) { + return new KeyboardMouseMovePacket(buffer.readDouble(), buffer.readDouble()); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toserver/KeyboardMouseScrollPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/KeyboardMouseScrollPacket.java new file mode 100644 index 000000000..9f8752532 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/KeyboardMouseScrollPacket.java @@ -0,0 +1,49 @@ +package de.srendi.advancedperipherals.common.network.toserver; + +import de.srendi.advancedperipherals.common.items.SmartGlassesItem; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesComputer; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.server.ServerLifecycleHooks; + +public class KeyboardMouseScrollPacket implements IPacket { + + private final int delta; + + public KeyboardMouseScrollPacket(int delta) { + this.delta = delta; + } + + @Override + public void handle(NetworkEvent.Context context) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + + ServerPlayer serverPlayer = context.getSender(); + if (serverPlayer == null) { + return; + } + + for (ItemStack stack : serverPlayer.getAllSlots()) { + if (stack.getItem() instanceof SmartGlassesItem) { + SmartGlassesComputer computer = SmartGlassesItem.getServerComputer(server, stack); + if (computer != null) { + computer.queueEvent("player_mouse_scroll", new Object[]{delta}); + break; + } + } + } + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeVarInt(delta); + } + + public static KeyboardMouseScrollPacket decode(FriendlyByteBuf buffer) { + return new KeyboardMouseScrollPacket(buffer.readVarInt()); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/APContainerTypes.java b/src/main/java/de/srendi/advancedperipherals/common/setup/APContainerTypes.java index b51d363b3..cdbc4f94d 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/setup/APContainerTypes.java +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/APContainerTypes.java @@ -3,23 +3,33 @@ import dan200.computercraft.shared.network.container.ComputerContainerData; import dan200.computercraft.shared.network.container.ContainerData; import de.srendi.advancedperipherals.common.container.InventoryManagerContainer; +import de.srendi.advancedperipherals.common.container.KeyboardContainer; import de.srendi.advancedperipherals.common.container.SmartGlassesContainer; import net.minecraft.core.BlockPos; import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraftforge.common.extensions.IForgeMenuType; import net.minecraftforge.registries.RegistryObject; public class APContainerTypes { - public static final RegistryObject> INVENTORY_MANAGER_CONTAINER = APRegistration.CONTAINER_TYPES.register("memory_card_container", () -> IForgeMenuType.create((windowId, inv, data) -> { - BlockPos pos = data.readBlockPos(); + public static final RegistryObject> INVENTORY_MANAGER_CONTAINER = APRegistration.CONTAINER_TYPES.register("memory_card_container", () -> IForgeMenuType.create((windowId, inv, buf) -> { + BlockPos pos = buf.readBlockPos(); Level level = inv.player.getCommandSenderWorld(); return new InventoryManagerContainer(windowId, inv, pos, level); })); - public static final RegistryObject> SMART_GLASSES_CONTAINER = APRegistration.CONTAINER_TYPES.register("smart_glasses_container", () -> ContainerData.toType(ComputerContainerData::new, - (id, inv, data) -> new SmartGlassesContainer(id, player -> true, null, data, inv, data.displayStack()) + public static final RegistryObject> KEYBOARD_CONTAINER = APRegistration.CONTAINER_TYPES.register("keyboard_container", () -> IForgeMenuType.create((windowId, inv, buf) -> { + BlockPos pos = buf.readBlockPos(); + ItemStack keyboardItem = buf.readItem(); + Level level = inv.player.getCommandSenderWorld(); + return new KeyboardContainer(windowId, inv, pos, level, keyboardItem); + })); + + public static final RegistryObject> SMART_GLASSES_CONTAINER = APRegistration.CONTAINER_TYPES.register("smart_glasses_container", () -> ContainerData.toType( + ComputerContainerData::new, + (id, inv, buf) -> new SmartGlassesContainer(id, player -> true, null, buf, inv, buf.displayStack()) )); protected static void register() { diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/APItems.java b/src/main/java/de/srendi/advancedperipherals/common/setup/APItems.java index 57d45b1e3..9b3c9f26b 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/setup/APItems.java +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/APItems.java @@ -4,6 +4,7 @@ import de.srendi.advancedperipherals.common.addons.ae2.AE2Registries; import de.srendi.advancedperipherals.common.configuration.APConfig; import de.srendi.advancedperipherals.common.items.APItem; +import de.srendi.advancedperipherals.common.items.KeyboardItem; import de.srendi.advancedperipherals.common.items.MemoryCardItem; import de.srendi.advancedperipherals.common.items.SmartGlassesInterfaceItem; import de.srendi.advancedperipherals.common.items.SmartGlassesItem; @@ -23,6 +24,7 @@ public class APItems { public static final RegistryObject END_AUTOMATA_CORE = APRegistration.ITEMS.register("end_automata_core", () -> new APItem(new Item.Properties().stacksTo(1), APConfig.METAPHYSICS_CONFIG.enableEndAutomataCore)); public static final RegistryObject HOTKEY_MODULE = APRegistration.ITEMS.register("hotkey_module", HotkeyModuleItem::new); public static final RegistryObject HUSBANDRY_AUTOMATA_CORE = APRegistration.ITEMS.register("husbandry_automata_core", () -> new APItem(new Item.Properties().stacksTo(1), APConfig.METAPHYSICS_CONFIG.enableHusbandryAutomataCore)); + public static final RegistryObject KEYBOARD = APRegistration.ITEMS.register("keyboard", KeyboardItem::new); public static final RegistryObject MEMORY_CARD = APRegistration.ITEMS.register("memory_card", MemoryCardItem::new); public static final RegistryObject NIGHT_VISION_MODULE = APRegistration.ITEMS.register("nightvision_module", NightVisionModuleItem::new); public static final RegistryObject OVERLAY_MODULE = APRegistration.ITEMS.register("overlay_module", OverlayGlassesItem::new); diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesComputer.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesComputer.java index 2880f55f4..cf817da89 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesComputer.java +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/SmartGlassesComputer.java @@ -187,12 +187,15 @@ private void updatePeripheralsAndModules(SmartGlassesItemHandler itemHandler) { } this.upgrades = upgradesBuilder.build(); for (int slot = SmartGlassesItemHandler.PERIPHERAL_SLOTS; slot < SmartGlassesItemHandler.SLOTS; slot++) { - ItemStack peripheralItem = itemHandler.getStackInSlot(slot); + ItemStack moduleItem = itemHandler.getStackInSlot(slot); IModule oldModule = modules.get(slot); - if (!peripheralItem.isEmpty() && peripheralItem.getItem() instanceof IModuleItem module) { - IModule newModule = module.createModule(smartGlassesAccess); - if (oldModule != null && oldModule.getName().equals(newModule.getName())) { - continue; + if (!moduleItem.isEmpty() && moduleItem.getItem() instanceof IModuleItem module) { + IModule newModule = module.createModule(smartGlassesAccess, moduleItem); + if (oldModule != null) { + if (oldModule.getName().equals(newModule.getName())) { + continue; + } + oldModule.onUnequipped(smartGlassesAccess); } modules.put(slot, newModule); } else if (oldModule != null) { diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleFunctions.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleFunctions.java index 3656500eb..1433b5938 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleFunctions.java +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleFunctions.java @@ -8,6 +8,4 @@ */ public interface IModuleFunctions extends IPeripheralPlugin { - IModuleFunctions EMPTY = new IModuleFunctions() {}; - } diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleItem.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleItem.java index bed3560a2..b0d4975f6 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleItem.java +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/IModuleItem.java @@ -8,7 +8,7 @@ public interface IModuleItem { - IModule createModule(SmartGlassesAccess access); + IModule createModule(SmartGlassesAccess access, ItemStack stack); /** * This method is called every tick the item is in the inventory of the smart glasses diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/hotkey/HotkeyModuleItem.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/hotkey/HotkeyModuleItem.java index 9dd8594a6..6763be02e 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/hotkey/HotkeyModuleItem.java +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/hotkey/HotkeyModuleItem.java @@ -8,8 +8,8 @@ import de.srendi.advancedperipherals.common.smartglasses.modules.IModule; import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleItem; import de.srendi.advancedperipherals.common.util.KeybindUtil; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; @@ -24,32 +24,34 @@ public boolean isEnabled() { } @Override - public IModule createModule(SmartGlassesAccess access) { + public IModule createModule(SmartGlassesAccess access, ItemStack stack) { return new HotkeyModule(); } @Override public void inventoryTick(@NotNull ItemStack stack, @NotNull Level level, @NotNull Entity entity, int slot, boolean isSelected) { - if (!level.isClientSide() || !(entity instanceof Player player)) + if (!level.isClientSide() || !(entity instanceof LocalPlayer)) { return; + } if (KeybindUtil.isKeyPressed(KeyBindings.GLASSES_HOTKEY_KEYBINDING)) { // Add another 50ms to the duration, one tick setKeyPressDuration(stack, getKeyPressDuration(stack) + 50); - } else if(getKeyPressDuration(stack) > 0) { - // If the key is not pressed, but the duration is greater than 0, we can assume that the key was pressed - // We can now post the event - - int duration = getKeyPressDuration(stack); + return; + } + int duration = getKeyPressDuration(stack); + // If the key is not pressed, but the duration is greater than 0, we can assume that the key was pressed + // We can now post the event + if (duration > 0) { setKeyPressDuration(stack, 0); String keyBind = KeyBindings.GLASSES_HOTKEY_KEYBINDING.getKey().getName(); - APNetworking.sendToServer(new GlassesHotkeyPacket(player.getUUID(), keyBind, duration)); + APNetworking.sendToServer(new GlassesHotkeyPacket(keyBind, duration)); } } public static int getKeyPressDuration(ItemStack stack) { - return stack.copy().getOrCreateTag().getInt(KEY_PRESS_DURATION_NBT); + return stack.hasTag() ? stack.getTag().getInt(KEY_PRESS_DURATION_NBT) : 0; } public static void setKeyPressDuration(ItemStack stack, int keyPressDuration) { diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/keyboard/KeyboardFunctions.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/keyboard/KeyboardFunctions.java new file mode 100644 index 000000000..8c5a7f138 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/keyboard/KeyboardFunctions.java @@ -0,0 +1,23 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.keyboard; + +import dan200.computercraft.api.lua.LuaFunction; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleFunctions; + +public class KeyboardFunctions implements IModuleFunctions { + + private final KeyboardModule keyboardModule; + + public KeyboardFunctions(KeyboardModule keyboardModule) { + this.keyboardModule = keyboardModule; + } + + @LuaFunction + public final boolean isCapturingMouse() { + return keyboardModule.isCapturingMouse(); + } + + @LuaFunction + public final void setCaptureMouse(boolean enable) { + keyboardModule.setCaptureMouse(enable); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/keyboard/KeyboardModule.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/keyboard/KeyboardModule.java new file mode 100644 index 000000000..a839c046e --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/keyboard/KeyboardModule.java @@ -0,0 +1,95 @@ +package de.srendi.advancedperipherals.common.smartglasses.modules.keyboard; + +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.container.KeyboardContainer; +import de.srendi.advancedperipherals.common.items.KeyboardItem; +import de.srendi.advancedperipherals.common.network.APNetworking; +import de.srendi.advancedperipherals.common.network.toclient.KeyboardMouseCapturePacket; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; +import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesComputer; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModule; +import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleFunctions; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.network.NetworkHooks; +import org.jetbrains.annotations.Nullable; + +public class KeyboardModule implements IModule { + + private final KeyboardItem keyboardItem; + private final ItemStack keyboardItemStack; + private boolean lastCaptureMouse = false; + private volatile boolean captureMouse = false; + + public KeyboardModule(KeyboardItem keyboardItem, ItemStack stack) { + this.keyboardItem = keyboardItem; + this.keyboardItemStack = stack; + } + + @Override + public ResourceLocation getName() { + return AdvancedPeripherals.getRL("keyboard"); + } + + @Nullable + @Override + public IModuleFunctions getFunctions(SmartGlassesAccess smartGlassesAccess) { + return new KeyboardFunctions(this); + } + + public boolean isCapturingMouse() { + return captureMouse; + } + + public void setCaptureMouse(boolean enable) { + if (captureMouse == enable) { + return; + } + captureMouse = enable; + } + + @Override + public void tick(SmartGlassesAccess glasses) { + if (!(glasses.getEntity() instanceof ServerPlayer player)) { + return; + } + boolean captureMouse = this.captureMouse; + if (captureMouse != lastCaptureMouse) { + lastCaptureMouse = captureMouse; + APNetworking.sendTo(new KeyboardMouseCapturePacket(captureMouse), player); + } + } + + @Override + public void onUnequipped(SmartGlassesAccess glasses) { + if (!(glasses.getEntity() instanceof ServerPlayer player)) { + return; + } + if (!(player.containerMenu instanceof KeyboardContainer keyboard)) { + return; + } + if (keyboard.getKeyboardItem() == this.keyboardItemStack) { + player.closeContainer(); + } + } + + public void openKeyboard(SmartGlassesAccess glasses) { + if (!(glasses.getEntity() instanceof ServerPlayer player)) { + return; + } + SmartGlassesComputer computer = glasses.getComputer(); + ItemStack stack = computer.getStack(); + + stack.getOrCreateTag().putBoolean(KeyboardItem.OPENING_TAG, true); + computer.queueEvent("keyboard_open"); + + KeyboardItem keyboardItem = this.keyboardItem; + NetworkHooks.openScreen(player, keyboardItem.createContainerWithComputer(player, stack, computer), buf -> keyboardItem.writeContainerData(player, stack, buf)); + boolean captureMouse = this.captureMouse; + this.lastCaptureMouse = captureMouse; + if (captureMouse) { + APNetworking.sendTo(new KeyboardMouseCapturePacket(true), player); + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModule.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModule.java index f1333b273..5c938b289 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModule.java +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModule.java @@ -11,7 +11,7 @@ public class NightVisionModule implements IModule { - public boolean nightVisionEnabled = true; + private boolean nightVisionEnabled = true; public NightVisionModule() { @@ -35,7 +35,6 @@ public void onUnequipped(SmartGlassesAccess smartGlassesAccess) { player.removeEffect(MobEffects.NIGHT_VISION); } } - } /** diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModuleItem.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModuleItem.java index 44da3ee90..825bab885 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModuleItem.java +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/nightvision/NightVisionModuleItem.java @@ -20,7 +20,7 @@ public boolean isEnabled() { } @Override - public IModule createModule(SmartGlassesAccess access) { + public IModule createModule(SmartGlassesAccess access, ItemStack stack) { return new NightVisionModule(); } @@ -30,12 +30,20 @@ public void inventoryTick(ItemStack itemStack, Level level, Entity entity, int i return; } - if (module instanceof NightVisionModule nightVisionModule) { - if (nightVisionModule.nightVisionEnabled) { - player.addEffect(new MobEffectInstance(MobEffects.NIGHT_VISION, 20 * 13 - 1 /* minus 1 tick then the client timing won't flash */)); - } else { - player.removeEffect(MobEffects.NIGHT_VISION); - } + if (!(module instanceof NightVisionModule nightVisionModule)) { + return; + } + if (nightVisionModule.isNightVisionEnabled()) { + player.addEffect(new MobEffectInstance( + MobEffects.NIGHT_VISION, + 20 * 13 - 1, /* minus 1 tick then the client timing won't flash */ + 0, + false, + false, + true + )); + } else { + player.removeEffect(MobEffects.NIGHT_VISION); } } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayGlassesItem.java b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayGlassesItem.java index 20a3bd78b..46126c53f 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayGlassesItem.java +++ b/src/main/java/de/srendi/advancedperipherals/common/smartglasses/modules/overlay/OverlayGlassesItem.java @@ -4,6 +4,7 @@ import de.srendi.advancedperipherals.common.smartglasses.SmartGlassesAccess; import de.srendi.advancedperipherals.common.smartglasses.modules.IModule; import de.srendi.advancedperipherals.common.smartglasses.modules.IModuleItem; +import net.minecraft.world.item.ItemStack; public class OverlayGlassesItem extends BaseItem implements IModuleItem { @@ -13,7 +14,7 @@ public boolean isEnabled() { } @Override - public IModule createModule(SmartGlassesAccess smartGlassesAccess) { + public IModule createModule(SmartGlassesAccess smartGlassesAccess, ItemStack stack) { return new OverlayModule(smartGlassesAccess); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/ServerWorker.java b/src/main/java/de/srendi/advancedperipherals/common/util/ServerWorker.java index cbde6790b..fc9dced5a 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/ServerWorker.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/ServerWorker.java @@ -33,7 +33,7 @@ public static void addToNextTick(final Runnable task) { @SubscribeEvent public static void serverTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.END) { - while (!callQueue.isEmpty()) { + for (int remain = callQueue.size(); remain > 0; remain--) { final Runnable runnable = callQueue.poll(); tasksRan++; AdvancedPeripherals.debug("Running task #" + tasksRan + ". Running " + runnable.getClass()); diff --git a/src/main/resources/assets/advancedperipherals/models/item/keyboard.json b/src/main/resources/assets/advancedperipherals/models/item/keyboard.json new file mode 100644 index 000000000..ec94c3cb6 --- /dev/null +++ b/src/main/resources/assets/advancedperipherals/models/item/keyboard.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "advancedperipherals:item/keyboard" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/advancedperipherals/textures/item/keyboard.png b/src/main/resources/assets/advancedperipherals/textures/item/keyboard.png new file mode 100644 index 000000000..ee2bf5a81 Binary files /dev/null and b/src/main/resources/assets/advancedperipherals/textures/item/keyboard.png differ