diff --git a/build.gradle b/build.gradle index 3eaaaa61f..6a1d2010b 100644 --- a/build.gradle +++ b/build.gradle @@ -316,7 +316,7 @@ dependencies { compileOnly fg.deobf("com.ldtteam:multipiston:${multipiston_version}") compileOnly fg.deobf("com.ldtteam:domum_ornamentum:${domumornamentum_version}:universal") compileOnly fg.deobf("com.ldtteam:blockui:${blockui_version}") - // IMPORTANT. This should be removed/uncommented when running `runData` + // IMPORTANT. This should be removed/commented when running `runData` runtimeOnly fg.deobf("com.ldtteam:minecolonies:${minecolonies_version}") runtimeOnly fg.deobf("com.ldtteam:structurize:${structurize_version}") runtimeOnly fg.deobf("com.ldtteam:multipiston:${multipiston_version}") diff --git a/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b b/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b index 67f24359b..559ba3090 100644 --- a/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b +++ b/src/generated/resources/.cache/03e4de26f1265135874f8cdcaebc09d9c08eb42b @@ -1,2 +1,2 @@ -// 1.19.2 2024-05-22T09:06:54.177869995 Tags for minecraft:item +// 1.19.2 2024-05-28T14:53:16.653667 Tags for minecraft:item 72eba3b11f69e16c87488f7c4ba7cfdad42c378e data/advancedperipherals/tags/items/smart_glasses.json diff --git a/src/generated/resources/.cache/2db41954e490230d51b10affff25ee2ee27b8d5b b/src/generated/resources/.cache/2db41954e490230d51b10affff25ee2ee27b8d5b index 834374d4a..fe56a6ce0 100644 --- a/src/generated/resources/.cache/2db41954e490230d51b10affff25ee2ee27b8d5b +++ b/src/generated/resources/.cache/2db41954e490230d51b10affff25ee2ee27b8d5b @@ -1,2 +1,2 @@ -// 1.19.2 2023-09-25T15:21:21.7663044 AP POI Type Tags +// 1.19.2 2024-05-28T14:53:16.655175 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 863bee0d1..bc70b7af4 100644 --- a/src/generated/resources/.cache/5a761efb7472ef97566e41e81451930a004134bf +++ b/src/generated/resources/.cache/5a761efb7472ef97566e41e81451930a004134bf @@ -1,4 +1,4 @@ -// 1.19.2 2023-09-25T15:21:21.7927076 Turtle Upgrades +// 1.19.2 2024-05-28T14:53:16.655476 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 @@ -10,4 +10,5 @@ c9b2df2d4fed11f60a8e6f8da77b2fa53dd13572 data/advancedperipherals/computercraft/ 42fc2b9a2601ef44d617cb18302c2c4fff31d282 data/advancedperipherals/computercraft/turtle_upgrades/overpowered_husbandry_automata.json fa7743922ef6b4dd3e633f2857e4047d533f13b5 data/advancedperipherals/computercraft/turtle_upgrades/overpowered_weak_automata.json 4054c59ceb099f17c4555fd5f36b2f8b4109f624 data/advancedperipherals/computercraft/turtle_upgrades/player_turtle.json +fa6624d0dab03bd26c2cccecad51848d5071ecd3 data/advancedperipherals/computercraft/turtle_upgrades/saddle_turtle.json c8059a2717cfac5b02898658c4d2d52fbd5710d4 data/advancedperipherals/computercraft/turtle_upgrades/weak_automata.json diff --git a/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 b/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 index 5362386e5..fe9b9c502 100644 --- a/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 +++ b/src/generated/resources/.cache/67cce32b1c3cbbcb1f646605f4914e3f196986c2 @@ -1,4 +1,4 @@ -// 1.19.2 2023-09-25T15:21:21.7873091 LootTables +// 1.19.2 2024-05-28T14:53:16.656615 LootTables d865e8ac35302c486faf5c7122569c554186186d data/advancedperipherals/loot_tables/blocks/block_reader.json a6f896cc3dbd8da12737825ec71e32970f54025c data/advancedperipherals/loot_tables/blocks/chat_box.json f50f506ae1987537f76be4c05a81689b25798f91 data/advancedperipherals/loot_tables/blocks/colony_integrator.json diff --git a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e index 57b11e7d4..c4a79999b 100644 --- a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e +++ b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e @@ -1,4 +1,4 @@ -// 1.19.2 2023-09-27T10:45:57.2509102 Recipes +// 1.19.2 2024-05-28T14:53:16.657381 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 @@ -27,8 +27,8 @@ f1f468c732f8c802c27776d3fd7aac432bcac8e3 data/advancedperipherals/recipes/comput 55c257e4e8548d1453a7ab96c547d64c22b3e1d6 data/advancedperipherals/recipes/environment_detector.json 2ddf64c122165bcd3a277db8a1c7e96b4d510c67 data/advancedperipherals/recipes/geo_scanner.json ebe70aa9fe80c5b962c13aa1fbadc32269ba81b9 data/advancedperipherals/recipes/inventory_manager.json -809bc6929cf5eab72648e8f1fb565b58749fec12 data/advancedperipherals/recipes/memory_card.json 82895838af6c6aea0c60e3a3fbf71073ab684167 data/advancedperipherals/recipes/me_bridge.json +809bc6929cf5eab72648e8f1fb565b58749fec12 data/advancedperipherals/recipes/memory_card.json 8a73c4eb66e7a1cdc8e51d33466cf5a30da9270e data/advancedperipherals/recipes/nbt_storage.json 360432f30d61291066aa8c54692629f7a92e178d data/advancedperipherals/recipes/overpowered_end_automata_core.json 4ea6e90d13a61d90ad245539d20020ff9cb843e1 data/advancedperipherals/recipes/overpowered_husbandry_automata_core.json diff --git a/src/generated/resources/.cache/ae219fa7c7d3297c14e454863eac3998a4eab78c b/src/generated/resources/.cache/ae219fa7c7d3297c14e454863eac3998a4eab78c index 920ac4b21..8fe8c2d79 100644 --- a/src/generated/resources/.cache/ae219fa7c7d3297c14e454863eac3998a4eab78c +++ b/src/generated/resources/.cache/ae219fa7c7d3297c14e454863eac3998a4eab78c @@ -1,4 +1,4 @@ -// 1.19.2 2023-09-25T15:21:21.7823145 Pocket Computer Upgrades +// 1.19.2 2024-05-28T14:53:16.655934 Pocket Computer Upgrades b672635324c0df354e587efc81d0b19a581eae2f data/advancedperipherals/computercraft/pocket_upgrades/chatty_pocket.json 30b8f663613c7ce77048fd69631afcc11a682276 data/advancedperipherals/computercraft/pocket_upgrades/colony_pocket.json d4647159c2f2693a9c5e8d12bf740635751d29a8 data/advancedperipherals/computercraft/pocket_upgrades/environment_pocket.json diff --git a/src/generated/resources/.cache/b8526e444ae7356037f3a813274f6835d1f3dd16 b/src/generated/resources/.cache/b8526e444ae7356037f3a813274f6835d1f3dd16 index 8dae79ce3..01ccc33ab 100644 --- a/src/generated/resources/.cache/b8526e444ae7356037f3a813274f6835d1f3dd16 +++ b/src/generated/resources/.cache/b8526e444ae7356037f3a813274f6835d1f3dd16 @@ -1,4 +1,4 @@ -// 1.19.2 2024-05-21T19:34:45.6005706 Block States: advancedperipherals +// 1.19.2 2024-05-28T14:53:16.658228 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 3ca333ee4..ea5891f84 100644 --- a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 +++ b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 @@ -1,2 +1,2 @@ -// 1.19.2 2024-05-21T19:49:29.0042891 Languages: en_us -2503b9953090303ef91a3d7ae64f7a6a6b75bb3b assets/advancedperipherals/lang/en_us.json +// 1.19.2 2024-05-28T14:53:16.658014 Languages: en_us +2580077212426421e05822910bde2edff88e2346 assets/advancedperipherals/lang/en_us.json diff --git a/src/generated/resources/.cache/f95c7003282837dabaa33e3ffceec4e6865b5218 b/src/generated/resources/.cache/f95c7003282837dabaa33e3ffceec4e6865b5218 index 012a6293c..25f180a23 100644 --- a/src/generated/resources/.cache/f95c7003282837dabaa33e3ffceec4e6865b5218 +++ b/src/generated/resources/.cache/f95c7003282837dabaa33e3ffceec4e6865b5218 @@ -1,4 +1,4 @@ -// 1.19.2 2024-05-01T21:24:42.041223 Block tags +// 1.19.2 2024-05-28T14:53:16.656337 Block tags e1f71dcb4f9e7e36e29b0ad09d6520dc3adfa4a6 data/forge/tags/blocks/needs_wood_tool.json ef4684e10e5054e8cfd515dffa4a98169d281078 data/minecraft/tags/blocks/mineable/pickaxe.json 8de9358ffeaa8d5f015774f70244a93b915427b8 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 ee30d74a9..4533665e0 100644 --- a/src/generated/resources/assets/advancedperipherals/lang/en_us.json +++ b/src/generated/resources/assets/advancedperipherals/lang/en_us.json @@ -85,6 +85,7 @@ "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.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", "turtle.advancedperipherals.chatty_turtle": "Chatty", @@ -98,5 +99,6 @@ "turtle.advancedperipherals.overpowered_husbandry_automata": "Overpowered husbandry automata", "turtle.advancedperipherals.overpowered_weak_automata": "Overpowered weak automata", "turtle.advancedperipherals.player_turtle": "Player Detector", + "turtle.advancedperipherals.saddle_turtle": "Saddle", "turtle.advancedperipherals.weak_automata": "Weak automata" } \ No newline at end of file diff --git a/src/generated/resources/data/advancedperipherals/computercraft/turtle_upgrades/saddle_turtle.json b/src/generated/resources/data/advancedperipherals/computercraft/turtle_upgrades/saddle_turtle.json new file mode 100644 index 000000000..0670d5c0b --- /dev/null +++ b/src/generated/resources/data/advancedperipherals/computercraft/turtle_upgrades/saddle_turtle.json @@ -0,0 +1,4 @@ +{ + "type": "advancedperipherals:saddle_turtle", + "item": "minecraft:saddle" +} \ No newline at end of file diff --git a/src/main/java/de/srendi/advancedperipherals/APCreativeTab.java b/src/main/java/de/srendi/advancedperipherals/APCreativeTab.java index 52eba5e66..8489c5f95 100644 --- a/src/main/java/de/srendi/advancedperipherals/APCreativeTab.java +++ b/src/main/java/de/srendi/advancedperipherals/APCreativeTab.java @@ -32,6 +32,7 @@ public void fillItemList(NonNullList items) { items.addAll(turtleUpgrade(CCRegistration.ID.CHATTY_TURTLE)); items.addAll(turtleUpgrade(CCRegistration.ID.CHUNKY_TURTLE)); items.addAll(turtleUpgrade(CCRegistration.ID.COMPASS_TURTLE)); + items.addAll(turtleUpgrade(CCRegistration.ID.SADDLE_TURTLE)); items.addAll(turtleUpgrade(CCRegistration.ID.PLAYER_TURTLE)); items.addAll(turtleUpgrade(CCRegistration.ID.ENVIRONMENT_TURTLE)); items.addAll(turtleUpgrade(CCRegistration.ID.GEOSCANNER_TURTLE)); diff --git a/src/main/java/de/srendi/advancedperipherals/client/ClientEventSubscriber.java b/src/main/java/de/srendi/advancedperipherals/client/ClientEventSubscriber.java new file mode 100644 index 000000000..0904a99a2 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/ClientEventSubscriber.java @@ -0,0 +1,84 @@ +package de.srendi.advancedperipherals.client; + +import com.mojang.blaze3d.platform.InputConstants; +import de.srendi.advancedperipherals.AdvancedPeripherals; +import de.srendi.advancedperipherals.common.entity.TurtleSeatEntity; +import de.srendi.advancedperipherals.common.network.PacketHandler; +import de.srendi.advancedperipherals.common.network.toserver.SaddleTurtleControlPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.Input; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.InputEvent; +import net.minecraftforge.client.event.MovementInputUpdateEvent; +import net.minecraftforge.client.event.RenderGuiOverlayEvent; +import net.minecraftforge.client.gui.overlay.VanillaGuiOverlay; +import net.minecraftforge.event.entity.EntityMountEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(modid = AdvancedPeripherals.MOD_ID, value = Dist.CLIENT) +public class ClientEventSubscriber { + @SubscribeEvent + public static void renderingHuds(RenderGuiOverlayEvent.Pre event) { + if (ClientRegistry.SADDLE_TURTLE_OVERLAY.shouldRenderFuelBar() && event.getOverlay().id().equals(VanillaGuiOverlay.EXPERIENCE_BAR.id())) { + event.setCanceled(true); + return; + } + } + + private static boolean sneaking = false; + + @SubscribeEvent + public static void playerTryDismount(InputEvent.Key event) { + Minecraft minecraft = Minecraft.getInstance(); + if (!minecraft.options.keyShift.matches(event.getKey(), event.getScanCode())) { + return; + } + switch (event.getAction()) { + case InputConstants.PRESS: + sneaking = true; + if (ClientRegistry.SADDLE_TURTLE_OVERLAY.isPlayerMountedOnTurtle()) { + minecraft.options.keyShift.setDown(false); + } + break; + case InputConstants.RELEASE: + sneaking = false; + break; + } + } + + private static Input lastInput = new Input(); + private static boolean lastSneak = false; + + @SubscribeEvent + public static void playerMounting(EntityMountEvent event) { + if (event.isMounting() && event.getEntityMounting() == Minecraft.getInstance().player && event.getEntityBeingMounted() instanceof TurtleSeatEntity) { + // clear last key records + lastInput.up = false; + lastInput.down = false; + lastInput.left = false; + lastInput.right = false; + lastInput.jumping = false; + lastSneak = false; + } + } + + @SubscribeEvent + public static void playerMove(MovementInputUpdateEvent event) { + if (ClientRegistry.SADDLE_TURTLE_OVERLAY.isPlayerMountedOnTurtle()) { + Input input = event.getInput(); + if (sneaking == lastSneak && lastInput != null) { + if (lastInput.up == input.up && lastInput.down == input.down && lastInput.left == input.left && lastInput.right == input.right && lastInput.jumping == input.jumping) { + return; + } + } + lastInput.up = input.up; + lastInput.down = input.down; + lastInput.left = input.left; + lastInput.right = input.right; + lastInput.jumping = input.jumping; + lastSneak = sneaking; + PacketHandler.sendToServer(new SaddleTurtleControlPacket(input.up, input.down, input.left, input.right, input.jumping, sneaking)); + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/client/ClientRegistry.java b/src/main/java/de/srendi/advancedperipherals/client/ClientRegistry.java index d5e52ae28..9eaf6025f 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.SaddleTurtleScreen; import de.srendi.advancedperipherals.client.screens.SmartGlassesScreen; import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes; import de.srendi.advancedperipherals.common.setup.APContainerTypes; @@ -15,6 +16,7 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.EntityRenderersEvent; import net.minecraftforge.client.event.ModelEvent; +import net.minecraftforge.client.event.RegisterGuiOverlaysEvent; import net.minecraftforge.client.event.RegisterKeyMappingsEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; @@ -25,6 +27,8 @@ public class ClientRegistry { private static final String[] TURTLE_MODELS = new String[]{"turtle_chat_box_upgrade_left", "turtle_chat_box_upgrade_right", "turtle_environment_upgrade_left", "turtle_environment_upgrade_right", "turtle_player_upgrade_left", "turtle_player_upgrade_right", "turtle_geoscanner_upgrade_left", "turtle_geoscanner_upgrade_right"}; + public static final SaddleTurtleScreen SADDLE_TURTLE_OVERLAY = new SaddleTurtleScreen(); + @SubscribeEvent public static void registerModels(ModelEvent.RegisterAdditional event) { for (String model : TURTLE_MODELS) { @@ -39,6 +43,7 @@ public static void onClientSetup(FMLClientSetupEvent event) { ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.CHUNKY_TURTLE.get(), TurtleUpgradeModeller.flatItem()); ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.COMPASS_TURTLE.get(), TurtleUpgradeModeller.flatItem()); + ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.SADDLE_TURTLE.get(), TurtleUpgradeModeller.flatItem()); ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.CHAT_BOX_TURTLE.get(), TurtleUpgradeModeller.sided(new ModelResourceLocation(AdvancedPeripherals.getRL("turtle_chat_box_upgrade_left"), "inventory"), new ModelResourceLocation(AdvancedPeripherals.getRL("turtle_chat_box_upgrade_right"), "inventory"))); ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.ENVIRONMENT_TURTLE.get(), TurtleUpgradeModeller.sided(new ModelResourceLocation(AdvancedPeripherals.getRL("turtle_environment_upgrade_left"), "inventory"), new ModelResourceLocation(AdvancedPeripherals.getRL("turtle_environment_upgrade_right"), "inventory"))); ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.GEO_SCANNER_TURTLE.get(), TurtleUpgradeModeller.sided(new ModelResourceLocation(AdvancedPeripherals.getRL("turtle_geoscanner_upgrade_left"), "inventory"), new ModelResourceLocation(AdvancedPeripherals.getRL("turtle_geoscanner_upgrade_right"), "inventory"))); @@ -62,4 +67,9 @@ public static void registeringKeymappings(RegisterKeyMappingsEvent event) { public static void registeringRenderers(EntityRenderersEvent.RegisterRenderers event) { event.registerBlockEntityRenderer(APBlockEntityTypes.DISTANCE_DETECTOR.get(), DistanceDetectorRenderer::new); } + + @SubscribeEvent + public static void registeringOverlays(RegisterGuiOverlaysEvent event) { + event.registerAboveAll(SaddleTurtleScreen.ID, SADDLE_TURTLE_OVERLAY); + } } diff --git a/src/main/java/de/srendi/advancedperipherals/client/screens/SaddleTurtleScreen.java b/src/main/java/de/srendi/advancedperipherals/client/screens/SaddleTurtleScreen.java new file mode 100644 index 000000000..e206172a0 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/client/screens/SaddleTurtleScreen.java @@ -0,0 +1,148 @@ +package de.srendi.advancedperipherals.client.screens; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import de.srendi.advancedperipherals.common.entity.TurtleSeatEntity; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiComponent; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.FormattedText; +import net.minecraft.util.FormattedCharSequence; +import net.minecraftforge.client.gui.overlay.ForgeGui; +import net.minecraftforge.client.gui.overlay.IGuiOverlay; + +public class SaddleTurtleScreen extends GuiComponent implements IGuiOverlay { + public static final String ID = "saddle_turtle_overlay"; + + private static final long ACTIVE_TIMEOUT = 5000; + + private ForgeGui gui; + private int screenWidth = 0; + private int screenHeight = 0; + + private int fuelLevel = 0; + private int fuelLimit = 0; + private int barColor = 0; + private long lastActived = 0; + + public SaddleTurtleScreen() {} + + protected Font getFont() { + return this.gui.getMinecraft().font; + } + + protected int textWidth(String text) { + return getFont().width(text); + } + + protected int textWidth(FormattedText text) { + return getFont().width(text); + } + + protected int textWidth(FormattedCharSequence text) { + return getFont().width(text); + } + + public static boolean isPlayerMountedOnTurtle() { + LocalPlayer player = Minecraft.getInstance().player; + return player != null && player.getRootVehicle() instanceof TurtleSeatEntity; + } + + public boolean shouldRenderFuelBar() { + if (this.lastActived == 0) { + return false; + } + if (!isPlayerMountedOnTurtle()) { + this.hide(); + return false; + } + return this.lastActived + ACTIVE_TIMEOUT > System.currentTimeMillis(); + } + + public void hide() { + this.fuelLevel = 0; + this.fuelLimit = 0; + this.barColor = 0; + this.lastActived = 0; + } + + public void keepAlive() { + this.lastActived = System.currentTimeMillis(); + } + + public void setFuelLevel(int level) { + if (level < 0) { + level = 0; + } + if (this.fuelLevel != level) { + this.fuelLevel = level; + this.keepAlive(); + } + } + + public void setFuelLimit(int limit) { + if (this.fuelLimit != limit) { + this.fuelLimit = limit; + this.keepAlive(); + } + } + + public void setBarColor(int color) { + if (this.barColor != color) { + this.barColor = color; + this.keepAlive(); + } + } + + private void renderFuelBar(PoseStack stack) { + // TODO: use a better looking bar here, and/or find someway to change the bar's color + RenderSystem.setShaderTexture(0, GuiComponent.GUI_ICONS_LOCATION); + int fontColor = 0x80ff20; + + int width = 182; + int left = this.screenWidth / 2 - 91; + int top = this.screenHeight - 32 + 3; + this.blit(stack, left, top, 0, 64, width, 5); + if (fuelLevel > 0 && fuelLimit > 0) { + int progWidth = fuelLevel * width / fuelLimit; + this.blit(stack, left, top, 0, 69, progWidth, 5); + } + + String text = fuelLimit > 0 ? String.format("%d / %d", fuelLevel, fuelLimit) : "Infinity"; + int x = (this.screenWidth - getFont().width(text)) / 2; + int y = this.screenHeight - 31; + getFont().draw(stack, text, (float)(x + 1), (float) y, 0); + getFont().draw(stack, text, (float)(x - 1), (float) y, 0); + getFont().draw(stack, text, (float) x, (float)(y + 1), 0); + getFont().draw(stack, text, (float) x, (float)(y - 1), 0); + getFont().draw(stack, text, (float) x, (float) y, fontColor); + } + + private void renderDismountHint(PoseStack stack) { + Minecraft minecraft = Minecraft.getInstance(); + Component name = Component.translatable("block.computercraft.turtle_normal.upgraded", Component.translatable("turtle.advancedperipherals.saddle_turtle")); + // TODO: get and render turtle's label if exists + Component text = Component.translatable("text.advancedperipherals.saddle_turtle_dismount_hint", + name, minecraft.options.keyShift.getTranslatedKeyMessage(), minecraft.options.keyInventory.getTranslatedKeyMessage()); + float top = 10; + float x = (float)(this.screenWidth / 2 - textWidth(text) / 2); + getFont().drawShadow(stack, text, x, top, 0xffffff); + } + + public void render(ForgeGui gui, PoseStack poseStack, float partialTick, int screenWidth, int screenHeight) { + if (!isPlayerMountedOnTurtle()) { + return; + } + + this.gui = gui; + this.screenWidth = screenWidth; + this.screenHeight = screenHeight; + + if (this.shouldRenderFuelBar()) { + this.renderFuelBar(poseStack); + } + this.renderDismountHint(poseStack); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SimpleFreeOperation.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SimpleFreeOperation.java index b86b1aa39..5ed3604c4 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SimpleFreeOperation.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SimpleFreeOperation.java @@ -7,7 +7,8 @@ import java.util.Map; public enum SimpleFreeOperation implements IPeripheralOperation { - CHAT_MESSAGE(100); + CHAT_MESSAGE(1000), + SADDLE_CAPTURE(5000); private final int defaultCooldown; private ForgeConfigSpec.IntValue cooldown; @@ -18,7 +19,7 @@ public enum SimpleFreeOperation implements IPeripheralOperation { @Override public void addToConfig(ForgeConfigSpec.Builder builder) { - cooldown = builder.defineInRange(settingsName() + "Cooldown", defaultCooldown, 1_000, Integer.MAX_VALUE); + cooldown = builder.defineInRange(settingsName() + "Cooldown", defaultCooldown, 100, Integer.MAX_VALUE); } @Override diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SingleOperation.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SingleOperation.java index 565e54c7c..30e2d21af 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SingleOperation.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SingleOperation.java @@ -70,7 +70,7 @@ public Map computerDescription() { @Override public void addToConfig(ForgeConfigSpec.Builder builder) { - cooldown = builder.defineInRange(settingsName() + "Cooldown", defaultCooldown, 1_000, Integer.MAX_VALUE); + cooldown = builder.defineInRange(settingsName() + "Cooldown", defaultCooldown, 100, Integer.MAX_VALUE); cost = builder.defineInRange(settingsName() + "Cost", defaultCost, 0, Integer.MAX_VALUE); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SphereOperation.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SphereOperation.java index 147b06400..9e8e0ac0f 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SphereOperation.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/operations/SphereOperation.java @@ -29,7 +29,7 @@ public enum SphereOperation implements IPeripheralOperation 1 ? arguments.getBoolean(1) : false; return withOperation(SCAN_ENTITIES, new SphereOperationContext(radius), context -> { if (radius > SCAN_ENTITIES.getMaxCostRadius()) return MethodResult.of(null, "Radius exceeds max value"); @@ -206,8 +206,7 @@ public final MethodResult scanEntities(@NotNull IComputerAccess access, @NotNull }, context -> { BlockPos pos = owner.getPos(); AABB box = new AABB(pos); - List> entities = new ArrayList<>(); - getLevel().getEntities((Entity) null, box.inflate(radius), LivingEntity.class::isInstance).forEach(entity -> entities.add(LuaConverter.completeEntityWithPositionToLua(entity, ItemStack.EMPTY, pos))); + List> entities = getLevel().getEntities((Entity) null, box.inflate(radius), entity -> entity instanceof LivingEntity && entity.isAlive()).stream().map(entity -> LuaConverter.completeEntityWithPositionToLua(entity, pos, detailed)).toList(); return MethodResult.of(entities); }, null); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/SaddlePeripheral.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/SaddlePeripheral.java new file mode 100644 index 000000000..04af84c82 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/SaddlePeripheral.java @@ -0,0 +1,203 @@ +package de.srendi.advancedperipherals.common.addons.computercraft.peripheral; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.lua.MethodResult; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.shared.turtle.core.TurtleBrain; +import de.srendi.advancedperipherals.common.addons.computercraft.owner.TurtlePeripheralOwner; +import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.common.entity.TurtleSeatEntity; +import de.srendi.advancedperipherals.common.network.PacketHandler; +import de.srendi.advancedperipherals.common.network.toclient.SaddleTurtleInfoPacket; +import de.srendi.advancedperipherals.common.util.LuaConverter; +import de.srendi.advancedperipherals.lib.peripherals.BasePeripheral; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.Map; +import java.util.function.Predicate; + +import static de.srendi.advancedperipherals.common.addons.computercraft.operations.SimpleFreeOperation.SADDLE_CAPTURE; + +public class SaddlePeripheral extends BasePeripheral { + + private static final int ANIM_DURATION = 8; // Should be same as TurtleBrain.ANIM_DURATION + + public static final String PERIPHERAL_TYPE = "saddle"; + private TurtleSeatEntity seat = null; + private volatile Entity rider = null; + private BlockPos lastPos = null; + private int moveProg = 0; + private int tickCount = 0; + + private int barColor = 0; + + public SaddlePeripheral(ITurtleAccess turtle, TurtleSide side) { + super(PERIPHERAL_TYPE, new TurtlePeripheralOwner(turtle, side)); + owner.attachOperation(SADDLE_CAPTURE); + } + + @Override + public boolean isEnabled() { + return APConfig.PERIPHERALS_CONFIG.enableSaddleTurtle.get(); + } + + @Nullable + public Entity getRidingEntity() { + return this.isEntityRiding() ? this.rider : null; + } + + public boolean isEntityRiding() { + return this.seat != null && this.rider != null && this.seat.isAlive() && this.seat.hasPassenger(this.rider); + } + + @Override + public void attach(@NotNull IComputerAccess computer) { + super.attach(computer); + this.lastPos = owner.getPos(); + } + + @Override + public void detach(@NotNull IComputerAccess computer) { + this.standUp(); + super.detach(computer); + } + + public void update() { + if (this.seat != null) { + if (!isEntityRiding()) { + this.standUp(); + return; + } + this.seat.keepAlive(); + BlockPos pos = owner.getPos(); + BlockPos dir = pos.subtract(this.lastPos); + int dist = Math.abs(dir.getX()) + Math.abs(dir.getY()) + Math.abs(dir.getZ()); + if (dist != 0) { + Vec3 newPos = new Vec3(pos.getX() + 0.5, pos.getY() + 0.4, pos.getZ() + 0.5); + if (dist == 1 && ++this.moveProg < ANIM_DURATION) { + float step = ((float) this.moveProg) / ANIM_DURATION; + newPos = newPos.add(Vec3.atLowerCornerOf(dir).scale(step - 1)); + } else { + this.moveProg = 0; + this.lastPos = pos; + } + this.seat.moveTo(newPos.x(), newPos.y(), newPos.z()); + } + this.tickCount++; + if (this.tickCount > 40) { + this.tickCount = 0; + this.sendHUD(); + } + } + } + + private void sendHUD() { + if (this.rider instanceof ServerPlayer player) { + ITurtleAccess turtle = owner.getTurtle(); + SaddleTurtleInfoPacket packet = new SaddleTurtleInfoPacket(turtle.getFuelLevel(), turtle.getFuelLimit(), barColor); + PacketHandler.sendTo(packet, player); + } + } + + private boolean sitDown(@NotNull Entity entity) { + Level world = owner.getLevel(); + BlockPos pos = owner.getPos(); + this.seat = new TurtleSeatEntity(owner.getTurtle()); + this.seat.setPos(pos.getX() + 0.5, pos.getY() + 0.4, pos.getZ() + 0.5); + if (!world.addFreshEntity(this.seat)) { + return false; + } + if (!entity.startRiding(this.seat, true)) { + return false; + } + if (entity instanceof TamableAnimal tamable) { + tamable.setInSittingPose(true); + } + this.seat.keepAlive(); + this.rider = entity; + this.sendHUD(); + return true; + } + + private boolean standUp() { + if (this.seat == null) { + return false; + } + boolean isVehicle = this.seat.isVehicle(); + this.seat.discard(); + this.seat = null; + this.rider = null; + if (owner.getTurtle() instanceof TurtleBrain brain) { + brain.getOwner().createServerComputer().queueEvent("saddle_release"); + } + return isVehicle; + } + + @LuaFunction(mainThread = true) + public MethodResult capture() throws LuaException { + if (isEntityRiding()) { + return MethodResult.of(null, "Another entity is riding"); + } + return withOperation(SADDLE_CAPTURE, null, null, context -> { + Predicate suitableEntity = (entity) -> entity.isAlive(); + if (!APConfig.PERIPHERALS_CONFIG.allowSaddleTurtleCapturePlayer.get()) { + suitableEntity = suitableEntity.and((entity) -> !(entity instanceof Player)); + } + final Predicate finalSuitableEntity = suitableEntity; + HitResult entityHit = owner.withPlayer(player -> player.findHit(false, true, finalSuitableEntity)); + if (entityHit.getType() == HitResult.Type.MISS) { + return MethodResult.of(null, "Nothing found"); + } + LivingEntity entity = (LivingEntity) ((EntityHitResult) entityHit).getEntity(); + if (!sitDown(entity)) { + return MethodResult.of(null, "Entity cannot sit"); + } + if (owner.getTurtle() instanceof TurtleBrain brain) { + brain.getOwner().createServerComputer().queueEvent("saddle_capture"); + } + return MethodResult.of(true); + }, null); + } + + @LuaFunction(mainThread = true) + public MethodResult release() { + if (!standUp()) { + return MethodResult.of(null, "No entity is riding"); + } + return MethodResult.of(true); + } + + @LuaFunction + public boolean hasRider() { + return this.rider != null; + } + + @LuaFunction(mainThread = true) + public MethodResult getRider(IArguments args) throws LuaException { + boolean detailed = args.count() > 0 ? args.getBoolean(0) : false; + Entity entity = getRidingEntity(); + if (entity == null) { + return MethodResult.of(null, "No entity is riding"); + } + Map data = LuaConverter.completeEntityToLua(entity, getPeripheralOwner().getToolInMainHand(), detailed); + if (data.get("pitch") instanceof Number pitch) { + data.put("pitch", (pitch.floatValue() - owner.getTurtle().getDirection().toYRot() + 360 + 180) % 360 - 180); + } + return MethodResult.of(data); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityHandPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityHandPlugin.java index 14dd9e6f1..027869f62 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityHandPlugin.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityHandPlugin.java @@ -76,17 +76,18 @@ public final MethodResult inspectAnimal(@NotNull IArguments arguments) throws Lu if (!(entity instanceof Animal animal)) return MethodResult.of(null, "Well, entity is not animal entity, but how?"); - return MethodResult.of(LuaConverter.animalToLua(animal, owner.getToolInMainHand())); + return MethodResult.of(LuaConverter.animalToLua(animal, owner.getToolInMainHand(), true)); } @LuaFunction(mainThread = true) - public final MethodResult searchAnimals() { + public final MethodResult searchAnimals(IArguments args) throws LuaException { + boolean detailed = args.count() > 0 ? args.getBoolean(0) : false; automataCore.addRotationCycle(); TurtlePeripheralOwner owner = automataCore.getPeripheralOwner(); BlockPos currentPos = owner.getPos(); AABB box = new AABB(currentPos); ItemStack itemInHand = owner.getToolInMainHand(); - List> entities = owner.getLevel().getEntities((Entity) null, box.inflate(automataCore.getInteractionRadius()), suitableEntity).stream().map(entity -> LuaConverter.completeEntityWithPositionToLua(entity, itemInHand, currentPos)).toList(); + List> entities = owner.getLevel().getEntities((Entity) null, box.inflate(automataCore.getInteractionRadius()), suitableEntity).stream().map(entity -> LuaConverter.completeEntityWithPositionToLua(entity, itemInHand, currentPos, detailed)).toList(); return MethodResult.of(entities); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityTransferPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityTransferPlugin.java index e46ca4356..c8a231d7c 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityTransferPlugin.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataEntityTransferPlugin.java @@ -120,8 +120,12 @@ public final MethodResult releaseAnimal() { } @LuaFunction(mainThread = true) - public final MethodResult getCapturedAnimal() { + public final MethodResult getCapturedAnimal(IArguments args) throws LuaException { + boolean detailed = args.count() > 0 ? args.getBoolean(0) : false; Entity extractedEntity = extractEntity(); - return MethodResult.of(LuaConverter.completeEntityToLua(extractedEntity, automataCore.getPeripheralOwner().getToolInMainHand())); + if (extractedEntity == null) { + return MethodResult.of(null, "No entity is stored"); + } + return MethodResult.of(LuaConverter.completeEntityToLua(extractedEntity, automataCore.getPeripheralOwner().getToolInMainHand(), detailed)); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataLookPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataLookPlugin.java index 2b27487bf..a3b5446ac 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataLookPlugin.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataLookPlugin.java @@ -61,7 +61,7 @@ public final MethodResult lookAtEntity(@NotNull IArguments arguments) throws Lua return MethodResult.of(null, "No entity find"); EntityHitResult entityHit = (EntityHitResult) result; - return MethodResult.of(LuaConverter.entityToLua(entityHit.getEntity())); + return MethodResult.of(LuaConverter.entityToLua(entityHit.getEntity(), true)); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataWarpingPlugin.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataWarpingPlugin.java index 462dd58a3..9c7ad8369 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataWarpingPlugin.java +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/peripheral/plugins/AutomataWarpingPlugin.java @@ -5,7 +5,6 @@ import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.turtle.ITurtleAccess; import de.srendi.advancedperipherals.common.addons.computercraft.operations.SingleOperationContext; import de.srendi.advancedperipherals.common.addons.computercraft.owner.FuelAbility; diff --git a/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/turtles/TurtleSaddleUpgrade.java b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/turtles/TurtleSaddleUpgrade.java new file mode 100644 index 000000000..d1098f63d --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/addons/computercraft/turtles/TurtleSaddleUpgrade.java @@ -0,0 +1,45 @@ +package de.srendi.advancedperipherals.common.addons.computercraft.turtles; + +import dan200.computercraft.api.peripheral.IPeripheral; +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.api.turtle.TurtleSide; +import de.srendi.advancedperipherals.common.addons.computercraft.peripheral.SaddlePeripheral; +import de.srendi.advancedperipherals.common.configuration.APConfig; +import de.srendi.advancedperipherals.lib.turtle.PeripheralTurtleUpgrade; +import net.minecraft.client.resources.model.ModelResourceLocation; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +public class TurtleSaddleUpgrade extends PeripheralTurtleUpgrade { + + public TurtleSaddleUpgrade(ResourceLocation id, ItemStack stack) { + super(id, stack); + } + + @Override + public ModelResourceLocation getLeftModel() { + return null; + } + + @Override + public ModelResourceLocation getRightModel() { + return null; + } + + @Override + protected SaddlePeripheral buildPeripheral(@NotNull ITurtleAccess turtle, @NotNull TurtleSide side) { + return new SaddlePeripheral(turtle, side); + } + + @Override + public void update(@NotNull ITurtleAccess turtle, @NotNull TurtleSide side) { + super.update(turtle, side); + if (APConfig.PERIPHERALS_CONFIG.enableSaddleTurtle.get()) { + IPeripheral peripheral = turtle.getPeripheral(side); + if (peripheral instanceof SaddlePeripheral saddlePeripheral) { + saddlePeripheral.update(); + } + } + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/configuration/PeripheralsConfig.java b/src/main/java/de/srendi/advancedperipherals/common/configuration/PeripheralsConfig.java index 9589d4f43..67bb59e8d 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/configuration/PeripheralsConfig.java +++ b/src/main/java/de/srendi/advancedperipherals/common/configuration/PeripheralsConfig.java @@ -87,6 +87,10 @@ public class PeripheralsConfig implements IAPConfig { public final ForgeConfigSpec.IntValue poweredPeripheralMaxEnergyStorage; private final ForgeConfigSpec configSpec; + // Saddle turtle (it's tamed) + public final ForgeConfigSpec.BooleanValue enableSaddleTurtle; + public final ForgeConfigSpec.BooleanValue allowSaddleTurtleCapturePlayer; + public PeripheralsConfig() { ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder(); @@ -193,6 +197,11 @@ public PeripheralsConfig() { disablePocketFuelConsumption = builder.comment("If true, pockets will have infinite fuel").define("disablePocketFuelConsumption", true); + pop("Saddle_Turtle", builder); + + enableSaddleTurtle = builder.comment("Enable saddle turtle").define("enableSaddleTurtle", true); + allowSaddleTurtleCapturePlayer = builder.comment("Allow saddle turtle to capture player").define("allowSaddleTurtleCapturePlayer", true); + pop("Operations", builder); register(SingleOperation.values(), builder); 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 1f321fa62..3ff16d31c 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/data/EnUsLanguageProvider.java +++ b/src/main/java/de/srendi/advancedperipherals/common/data/EnUsLanguageProvider.java @@ -33,7 +33,7 @@ protected void addTranslations() { addAdvancements(); addTooltips(); addKeybinds(); - addText(); + addTexts(); add(APVillagers.COMPUTER_SCIENTIST, "Computer Scientist"); add("advancedperipherals.name", AdvancedPeripherals.NAME); add("curios.identifier.glasses", "Glasses"); @@ -78,12 +78,13 @@ private void addBlocks() { } private void addTurtles() { - addTurtle(CCRegistration.ID.CHUNKY_TURTLE, "Chunky"); addTurtle(CCRegistration.ID.CHATTY_TURTLE, "Chatty"); + addTurtle(CCRegistration.ID.CHUNKY_TURTLE, "Chunky"); + addTurtle(CCRegistration.ID.COMPASS_TURTLE, "Compass"); + addTurtle(CCRegistration.ID.SADDLE_TURTLE, "Saddle"); addTurtle(CCRegistration.ID.ENVIRONMENT_TURTLE, "Environment"); addTurtle(CCRegistration.ID.PLAYER_TURTLE, "Player Detector"); addTurtle(CCRegistration.ID.GEOSCANNER_TURTLE, "Geo"); - addTurtle(CCRegistration.ID.COMPASS_TURTLE, "Compass"); addTurtle(CCRegistration.ID.WEAK_AUTOMATA, "Weak automata"); addTurtle(CCRegistration.ID.HUSBANDRY_AUTOMATA, "Husbandry automata"); addTurtle(CCRegistration.ID.END_AUTOMATA, "End automata"); @@ -139,12 +140,13 @@ private void addTooltips() { addTooltip(APItems.OVERPOWERED_END_AUTOMATA_CORE.get(), "&7Improved version of the end automata core, that provides some overpowered uses! Be careful, the upgrade is very fragile."); } - private void addText() { - add("text." + AdvancedPeripherals.MOD_ID + ".removed_player", "Cleared the memory card"); - add("text." + AdvancedPeripherals.MOD_ID + ".added_player", "Added you to the memory card"); - add("text." + AdvancedPeripherals.MOD_ID + ".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?"); - add("text." + AdvancedPeripherals.MOD_ID + ".smart_glasses.peripherals", "Peripherals"); - add("text." + AdvancedPeripherals.MOD_ID + ".smart_glasses.modules", "Modules"); + 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("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."); } private void addKeybinds() { @@ -161,6 +163,10 @@ private void add(@NotNull Supplier key, @NotNull String name add("entity.minecraft.villager." + AdvancedPeripherals.MOD_ID + "." + key.get().name(), name); } + private void addText(String key, String value) { + add("text." + AdvancedPeripherals.MOD_ID + "." + key, value); + } + private void addTurtle(@NotNull ResourceLocation key, @NotNull String name) { add("turtle." + key.getNamespace() + "." + key.getPath(), name); } diff --git a/src/main/java/de/srendi/advancedperipherals/common/data/TurtleUpgradesProvider.java b/src/main/java/de/srendi/advancedperipherals/common/data/TurtleUpgradesProvider.java index 70ec6c177..86d8e8bbe 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/data/TurtleUpgradesProvider.java +++ b/src/main/java/de/srendi/advancedperipherals/common/data/TurtleUpgradesProvider.java @@ -24,6 +24,7 @@ protected void addUpgrades(@NotNull Consumer> simpleWithCustomItem(CCRegistration.ID.CHUNKY_TURTLE, CCRegistration.CHUNKY_TURTLE.get(), APItems.CHUNK_CONTROLLER.get()).add(addUpgrade); simpleWithCustomItem(CCRegistration.ID.GEOSCANNER_TURTLE, CCRegistration.GEO_SCANNER_TURTLE.get(), APBlocks.GEO_SCANNER.get().asItem()).add(addUpgrade); simpleWithCustomItem(CCRegistration.ID.COMPASS_TURTLE, CCRegistration.COMPASS_TURTLE.get(), net.minecraft.world.item.Items.COMPASS).add(addUpgrade); + simpleWithCustomItem(CCRegistration.ID.SADDLE_TURTLE, CCRegistration.SADDLE_TURTLE.get(), net.minecraft.world.item.Items.SADDLE).add(addUpgrade); simpleWithCustomItem(CCRegistration.ID.WEAK_AUTOMATA, CCRegistration.WEAK_TURTLE.get(), APItems.WEAK_AUTOMATA_CORE.get()).add(addUpgrade); simpleWithCustomItem(CCRegistration.ID.END_AUTOMATA, CCRegistration.END_TURTLE.get(), APItems.END_AUTOMATA_CORE.get()).add(addUpgrade); simpleWithCustomItem(CCRegistration.ID.HUSBANDRY_AUTOMATA, CCRegistration.HUSBANDRY_TURTLE.get(), APItems.HUSBANDRY_AUTOMATA_CORE.get()).add(addUpgrade); diff --git a/src/main/java/de/srendi/advancedperipherals/common/entity/TurtleSeatEntity.java b/src/main/java/de/srendi/advancedperipherals/common/entity/TurtleSeatEntity.java new file mode 100644 index 000000000..e2ef07f0b --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/entity/TurtleSeatEntity.java @@ -0,0 +1,242 @@ +package de.srendi.advancedperipherals.common.entity; + +import dan200.computercraft.api.turtle.ITurtleAccess; +import dan200.computercraft.shared.computer.core.ServerComputer; +import dan200.computercraft.shared.turtle.blocks.TileTurtle; +import dan200.computercraft.shared.turtle.core.TurtleBrain; +import dan200.computercraft.shared.turtle.items.TurtleItemFactory; +import dan200.computercraft.shared.network.container.ComputerContainerData; +import de.srendi.advancedperipherals.common.network.toserver.SaddleTurtleControlPacket; +import de.srendi.advancedperipherals.common.setup.APEntities; +import net.minecraft.client.renderer.culling.Frustum; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.HasCustomInventoryScreen; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; +import net.minecraft.resources.ResourceLocation; + +import org.jetbrains.annotations.Nullable; + +public class TurtleSeatEntity extends Entity implements HasCustomInventoryScreen { + + // TODO: better rendering + + private ITurtleAccess turtle; + private int life; + + private boolean forwardKey = false; + private boolean backKey = false; + private boolean leftKey = false; + private boolean rightKey = false; + private boolean upKey = false; + private boolean downKey = false; + private boolean forwardKeyOld = false; + private boolean backKeyOld = false; + private boolean leftKeyOld = false; + private boolean rightKeyOld = false; + private boolean upKeyOld = false; + private boolean downKeyOld = false; + + public TurtleSeatEntity(EntityType type, Level world) { + super(type, world); + this.noPhysics = true; + } + + public TurtleSeatEntity(ITurtleAccess turtle) { + this(APEntities.TURTLE_SEAT.get(), turtle.getLevel()); + this.turtle = turtle; + this.life = 0; + } + + public ITurtleAccess getOwner() { + return turtle; + } + + @Nullable + private ServerComputer getServerComputer() { + Player player = this.getSelfAndPassengers().filter(e -> e instanceof Player).map(e -> (Player) e).findFirst().orElse(null); + if (player != null && this.turtle instanceof TurtleBrain turtle) { + TileTurtle tile = turtle.getOwner(); + if (tile.isUsable(player)) { + return tile.createServerComputer(); + } + } + return null; + } + + public void keepAlive() { + this.life = 2; + } + + @Override + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this); + } + + @Override + public void readAdditionalSaveData(CompoundTag storage) {} + + @Override + public void addAdditionalSaveData(CompoundTag storage) {} + + @Override + protected void defineSynchedData() {} + + @Override + public void setPos(double x, double y, double z) { + super.setPos(x, y, z); + AABB bb = this.getBoundingBox(); + this.setBoundingBox(bb.move(new Vec3(x, y, z).subtract(bb.getCenter()))); + } + + @Override + protected void removePassenger(Entity entity) { + super.removePassenger(entity); + this.forwardKey = false; + this.backKey = false; + this.leftKey = false; + this.rightKey = false; + this.upKey = false; + this.downKey = false; + this.forwardKeyOld = false; + this.backKeyOld = false; + this.leftKeyOld = false; + this.rightKeyOld = false; + this.upKeyOld = false; + this.downKeyOld = false; + if (entity instanceof TamableAnimal tamed) { + tamed.setInSittingPose(false); + } + } + + @Override + public Vec3 getDismountLocationForPassenger(LivingEntity entity) { + return super.getDismountLocationForPassenger(entity).add(0, 0.5, 0); + } + + @Override + public Entity getControllingPassenger() { + return null; // this.getFirstPassenger(); + } + + @Override + public void tick() { + if (this.level.isClientSide) { + return; + } + this.life--; + if (this.life < 0) { + this.discard(); + return; + } + ServerComputer computer = this.getServerComputer(); + if (computer != null) { + if (this.forwardKey != this.forwardKeyOld) { + this.forwardKeyOld = this.forwardKey; + computer.queueEvent("saddle_control", new Object[]{"forward", this.forwardKey}); + } + if (this.backKey != this.backKeyOld) { + this.backKeyOld = this.backKey; + computer.queueEvent("saddle_control", new Object[]{"back", this.backKey}); + } + if (this.leftKey != this.leftKeyOld) { + this.leftKeyOld = this.leftKey; + computer.queueEvent("saddle_control", new Object[]{"left", this.leftKey}); + } + if (this.rightKey != this.rightKeyOld) { + this.rightKeyOld = this.rightKey; + computer.queueEvent("saddle_control", new Object[]{"right", this.rightKey}); + } + if (this.upKey != this.upKeyOld) { + this.upKeyOld = this.upKey; + computer.queueEvent("saddle_control", new Object[]{"up", this.upKey}); + } + if (this.downKey != this.downKeyOld) { + this.downKeyOld = this.downKey; + computer.queueEvent("saddle_control", new Object[]{"down", this.downKey}); + } + } + } + + public void handleSaddleTurtleControlPacket(SaddleTurtleControlPacket packet) { + this.forwardKey = packet.forward; + this.backKey = packet.back; + this.leftKey = packet.left; + this.rightKey = packet.right; + this.upKey = packet.up; + this.downKey = packet.down; + } + + @Override + public void openCustomInventoryScreen(Player player) { + if (!this.level.isClientSide && this.hasPassenger(player)) { + if (this.downKey) { + player.stopRiding(); + this.discard(); + return; + } + if (this.turtle instanceof TurtleBrain turtle) { + TileTurtle tile = turtle.getOwner(); + if (!tile.isUsable(player)) { + return; + } + ServerComputer computer = tile.createServerComputer(); + ItemStack stack = TurtleItemFactory.create(tile); + new ComputerContainerData(computer, stack).open(player, tile); + } + } + } + + public static class Renderer extends EntityRenderer { + public Renderer(EntityRendererProvider.Context ctx) { + super(ctx); + } + + @Override + public boolean shouldRender(TurtleSeatEntity a0, Frustum a1, double a2, double a3, double a4) { + return false; + } + + @Override + public ResourceLocation getTextureLocation(TurtleSeatEntity a0) { + return null; + } + } + + @Override + public boolean canChangeDimensions() { + return false; + } + + @Override + public boolean shouldBlockExplode(net.minecraft.world.level.Explosion a0, net.minecraft.world.level.BlockGetter a1, BlockPos a2, BlockState a3, float a4) { + return false; + } + + @Override + public boolean isIgnoringBlockTriggers() { + return true; + } + + @Override + public PushReaction getPistonPushReaction() { + return PushReaction.IGNORE; + } + + @Override + public void setDeltaMovement(Vec3 a0) {} +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/PacketHandler.java b/src/main/java/de/srendi/advancedperipherals/common/network/PacketHandler.java index 77bbd1fb9..8658d0d0d 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/network/PacketHandler.java +++ b/src/main/java/de/srendi/advancedperipherals/common/network/PacketHandler.java @@ -3,8 +3,10 @@ import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.network.base.IPacket; import de.srendi.advancedperipherals.common.network.toclient.DistanceDetectorSyncPacket; +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.SaddleTurtleControlPacket; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; @@ -34,8 +36,10 @@ public class PacketHandler { public static void init() { registerServerToClient(DistanceDetectorSyncPacket.class, DistanceDetectorSyncPacket::decode); + registerServerToClient(SaddleTurtleInfoPacket.class, SaddleTurtleInfoPacket::decode); registerServerToClient(ToastToClientPacket.class, ToastToClientPacket::decode); registerClientToServer(GlassesHotkeyPacket.class, GlassesHotkeyPacket::decode); + registerClientToServer(SaddleTurtleControlPacket.class, SaddleTurtleControlPacket::decode); } public static void registerServerToClient(Class packet, Function decode) { diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toclient/SaddleTurtleInfoPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/SaddleTurtleInfoPacket.java new file mode 100644 index 000000000..7cb9e3cf9 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toclient/SaddleTurtleInfoPacket.java @@ -0,0 +1,45 @@ +package de.srendi.advancedperipherals.common.network.toclient; + +import de.srendi.advancedperipherals.common.network.base.IPacket; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.fml.loading.FMLEnvironment; +import net.minecraftforge.network.NetworkEvent; + +import static de.srendi.advancedperipherals.client.ClientRegistry.SADDLE_TURTLE_OVERLAY; + +public class SaddleTurtleInfoPacket implements IPacket { + + private final int fuelLevel; + private final int fuelLimit; + private final int barColor; + + public SaddleTurtleInfoPacket(int fuelLevel, int fuelLimit, int barColor) { + this.fuelLevel = fuelLevel; + this.fuelLimit = fuelLimit; + this.barColor = barColor; + } + + @Override + public void handle(NetworkEvent.Context context) { + if (!FMLEnvironment.dist.isClient()) { + return; + } + SADDLE_TURTLE_OVERLAY.setFuelLevel(this.fuelLevel); + SADDLE_TURTLE_OVERLAY.setFuelLimit(this.fuelLimit); + SADDLE_TURTLE_OVERLAY.setBarColor(this.barColor); + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeInt(this.fuelLevel); + buffer.writeInt(this.fuelLimit); + buffer.writeInt(this.barColor); + } + + public static SaddleTurtleInfoPacket decode(FriendlyByteBuf buffer) { + int fuelLevel = buffer.readInt(); + int fuelLimit = buffer.readInt(); + int barColor = buffer.readInt(); + return new SaddleTurtleInfoPacket(fuelLevel, fuelLimit, barColor); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/network/toserver/SaddleTurtleControlPacket.java b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/SaddleTurtleControlPacket.java new file mode 100644 index 000000000..e9fca5ba5 --- /dev/null +++ b/src/main/java/de/srendi/advancedperipherals/common/network/toserver/SaddleTurtleControlPacket.java @@ -0,0 +1,77 @@ +package de.srendi.advancedperipherals.common.network.toserver; + +import de.srendi.advancedperipherals.common.entity.TurtleSeatEntity; +import de.srendi.advancedperipherals.common.network.base.IPacket; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkEvent; + +public class SaddleTurtleControlPacket implements IPacket { + + public final boolean forward; + public final boolean back; + public final boolean left; + public final boolean right; + public final boolean up; + public final boolean down; + + private static final byte FORWARD_BIT = 1 << 0; + private static final byte BACK_BIT = 1 << 1; + private static final byte LEFT_BIT = 1 << 2; + private static final byte RIGHT_BIT = 1 << 3; + private static final byte UP_BIT = 1 << 4; + private static final byte DOWN_BIT = 1 << 5; + + public SaddleTurtleControlPacket(boolean forward, boolean back, boolean left, boolean right, boolean up, boolean down) { + this.forward = forward; + this.back = back; + this.left = left; + this.right = right; + this.up = up; + this.down = down; + } + + private SaddleTurtleControlPacket(byte bits) { + this((bits & FORWARD_BIT) != 0, (bits & BACK_BIT) != 0, (bits & LEFT_BIT) != 0, (bits & RIGHT_BIT) != 0, (bits & UP_BIT) != 0, (bits & DOWN_BIT) != 0); + } + + @Override + public void handle(NetworkEvent.Context context) { + ServerPlayer player = context.getSender(); + if (player != null && player.getRootVehicle() instanceof TurtleSeatEntity seat) { + seat.handleSaddleTurtleControlPacket(this); + } + } + + private byte encodeToBits() { + byte b = 0; + if (this.forward) { + b |= FORWARD_BIT; + } + if (this.back) { + b |= BACK_BIT; + } + if (this.left) { + b |= LEFT_BIT; + } + if (this.right) { + b |= RIGHT_BIT; + } + if (this.up) { + b |= UP_BIT; + } + if (this.down) { + b |= DOWN_BIT; + } + return b; + } + + @Override + public void encode(FriendlyByteBuf buffer) { + buffer.writeByte(this.encodeToBits()); + } + + public static SaddleTurtleControlPacket decode(FriendlyByteBuf buffer) { + return new SaddleTurtleControlPacket(buffer.readByte()); + } +} diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/APEntities.java b/src/main/java/de/srendi/advancedperipherals/common/setup/APEntities.java index 9a9d4c3b6..3f94ddba9 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/setup/APEntities.java +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/APEntities.java @@ -2,6 +2,7 @@ import de.srendi.advancedperipherals.AdvancedPeripherals; import de.srendi.advancedperipherals.common.entity.TurtleEnderPearl; +import de.srendi.advancedperipherals.common.entity.TurtleSeatEntity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MobCategory; import net.minecraftforge.registries.RegistryObject; @@ -20,6 +21,13 @@ public class APEntities { .updateInterval(5) .fireImmune() .build("turtle_ender_pearl")); + public static final RegistryObject> TURTLE_SEAT = APRegistration.ENTITIES.register("turtle_seat", + () -> EntityType.Builder.of(TurtleSeatEntity::new, MobCategory.MISC) + .sized(0.8F, 0.2F) + .clientTrackingRange(4) + .updateInterval(4) + .fireImmune() + .build("turtle_seat")); public static void register() { } @@ -27,5 +35,6 @@ public static void register() { @SubscribeEvent public static void livingRender(EntityRenderersEvent.RegisterRenderers event) { event.registerEntityRenderer(TURTLE_ENDER_PEARL.get(), TurtleEnderPearl.Renderer::new); + event.registerEntityRenderer(TURTLE_SEAT.get(), TurtleSeatEntity.Renderer::new); } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/setup/CCRegistration.java b/src/main/java/de/srendi/advancedperipherals/common/setup/CCRegistration.java index 11962445a..d19ba1b01 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/setup/CCRegistration.java +++ b/src/main/java/de/srendi/advancedperipherals/common/setup/CCRegistration.java @@ -21,6 +21,7 @@ public class CCRegistration { public static final RegistryObject> CHUNKY_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.CHUNKY_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleChunkyUpgrade::new)); public static final RegistryObject> GEO_SCANNER_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.GEOSCANNER_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleGeoScannerUpgrade::new)); public static final RegistryObject> COMPASS_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.COMPASS_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleCompassUpgrade::new)); + public static final RegistryObject> SADDLE_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.SADDLE_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleSaddleUpgrade::new)); public static final RegistryObject> WEAK_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.WEAK_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(WeakAutomata::new)); public static final RegistryObject> END_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.END_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(EndAutomata::new)); public static final RegistryObject> HUSBANDRY_TURTLE = APRegistration.TURTLE_SERIALIZER.register(ID.HUSBANDRY_AUTOMATA.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(HusbandryAutomata::new)); @@ -50,6 +51,7 @@ public static class ID { public static final ResourceLocation CHUNKY_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "chunky_turtle"); public static final ResourceLocation GEOSCANNER_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "geoscanner_turtle"); public static final ResourceLocation COMPASS_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "compass_turtle"); + public static final ResourceLocation SADDLE_TURTLE = new ResourceLocation(AdvancedPeripherals.MOD_ID, "saddle_turtle"); public static final ResourceLocation WEAK_AUTOMATA = new ResourceLocation(AdvancedPeripherals.MOD_ID, "weak_automata"); public static final ResourceLocation END_AUTOMATA = new ResourceLocation(AdvancedPeripherals.MOD_ID, "end_automata"); public static final ResourceLocation HUSBANDRY_AUTOMATA = new ResourceLocation(AdvancedPeripherals.MOD_ID, "husbandry_automata"); diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/EnumColor.java b/src/main/java/de/srendi/advancedperipherals/common/util/EnumColor.java index 9273fc561..2e3a97e00 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/EnumColor.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/EnumColor.java @@ -4,22 +4,22 @@ public enum EnumColor { - BLACK("\u00a70", "Black", "black", "§0", 0, new float[]{0f, 0f, 0f, 1f}), - DARK_BLUE("\u00a71", "Blue", "blue", "§1", 0xFF0000c9, new float[]{0f, 0f, 0.804f, 1f}), - DARK_GREEN("\u00a72", "Green", "green", "§2", 0xFF0c9400, new float[]{0.048f, 0.592f, 0f, 1f}), - DARK_AQUA("\u00a73", "Cyan", "cyan", "§3", 0xFF009494, new float[]{0f, 0.592f, 0.592f, 1f}), - DARK_RED("\u00a74", "Dark Red", "dark_red", "§4", 0xFF940000, new float[]{0.592f, 0f, 0f, 1f}), - DARK_PURPLE("\u00a75", "Purple", "purple", "§5", 0xFF510094, new float[]{0.324f, 0f, 0.592f, 1f}), - GOLD("\u00a76", "Orange", "orange", "§6", 0xFFb59700, new float[]{1f, 0.407f, 0f, 1f}), - GRAY("\u00a77", "Light Gray", "light_gray", "§7", 0xFF616161, new float[]{0.388f, 0.388f, 0.388f, 1f}), - DARK_GRAY("\u00a78", "Gray", "gray", "§8", 0xFF4a4a4a, new float[]{0.296f, 0.296f, 0.296f, 1f}), - BLUE("\u00a79", "Light Blue", "light_blue", "§9", 0xFF1919ff, new float[]{0.098f, 0.098f, 1f, 1f}), - GREEN("\u00a7a", "Lime", "lime", "§a", 0xFF00e02d, new float[]{0f, 0.878f, 0.176f, 1f}), - AQUA("\u00a7b", "Aqua", "aqua", "§b", 0xFF17ffe4, new float[]{0.090f, 1f, 0.894f, 1f}), - RED("\u00a7c", "Red", "red", "§c", 0xFFff1c1c, new float[]{1f, 0.109f, 0.109f, 1f}), - LIGHT_PURPLE("\u00a7d", "Magenta", "magenta", "§d", 0xFF7424ff, new float[]{0.454f, 0.141f, 1f, 1f}), - YELLOW("\u00a7e", "Yellow", "yellow", "§e", 0xFFc8ff00, new float[]{0.784f, 1f, 0f, 1f}), - WHITE("\u00a7f", "White", "white", "§f", 0xFFffffff, new float[]{1f, 1f, 1f, 1f}); + BLACK("\u00a70", "Black", "black", "&0", 0, new float[]{0f, 0f, 0f, 1f}), + DARK_BLUE("\u00a71", "Blue", "blue", "&1", 0xFF0000c9, new float[]{0f, 0f, 0.804f, 1f}), + DARK_GREEN("\u00a72", "Green", "green", "&2", 0xFF0c9400, new float[]{0.048f, 0.592f, 0f, 1f}), + DARK_AQUA("\u00a73", "Cyan", "cyan", "&3", 0xFF009494, new float[]{0f, 0.592f, 0.592f, 1f}), + DARK_RED("\u00a74", "Dark Red", "dark_red", "&4", 0xFF940000, new float[]{0.592f, 0f, 0f, 1f}), + DARK_PURPLE("\u00a75", "Purple", "purple", "&5", 0xFF510094, new float[]{0.324f, 0f, 0.592f, 1f}), + GOLD("\u00a76", "Orange", "orange", "&6", 0xFFb59700, new float[]{1f, 0.407f, 0f, 1f}), + GRAY("\u00a77", "Light Gray", "light_gray", "&7", 0xFF616161, new float[]{0.388f, 0.388f, 0.388f, 1f}), + DARK_GRAY("\u00a78", "Gray", "gray", "&8", 0xFF4a4a4a, new float[]{0.296f, 0.296f, 0.296f, 1f}), + BLUE("\u00a79", "Light Blue", "light_blue", "&9", 0xFF1919ff, new float[]{0.098f, 0.098f, 1f, 1f}), + GREEN("\u00a7a", "Lime", "lime", "&a", 0xFF00e02d, new float[]{0f, 0.878f, 0.176f, 1f}), + AQUA("\u00a7b", "Aqua", "aqua", "&b", 0xFF17ffe4, new float[]{0.090f, 1f, 0.894f, 1f}), + RED("\u00a7c", "Red", "red", "&c", 0xFFff1c1c, new float[]{1f, 0.109f, 0.109f, 1f}), + LIGHT_PURPLE("\u00a7d", "Magenta", "magenta", "&d", 0xFF7424ff, new float[]{0.454f, 0.141f, 1f, 1f}), + YELLOW("\u00a7e", "Yellow", "yellow", "&e", 0xFFc8ff00, new float[]{0.784f, 1f, 0f, 1f}), + WHITE("\u00a7f", "White", "white", "&f", 0xFFffffff, new float[]{1f, 1f, 1f, 1f}); private final String code; private final String name; diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/LuaConverter.java b/src/main/java/de/srendi/advancedperipherals/common/util/LuaConverter.java index e74410111..db6bcefc8 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/LuaConverter.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/LuaConverter.java @@ -9,13 +9,20 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.tags.TagKey; import net.minecraft.util.StringRepresentable; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.animal.Animal; +import net.minecraft.world.entity.npc.InventoryCarrier; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.scores.Team; import net.minecraftforge.common.IForgeShearable; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidType; @@ -31,29 +38,64 @@ public class LuaConverter { - public static Map entityToLua(Entity entity) { + public static Map entityToLua(Entity entity, boolean detailed) { Map data = new HashMap<>(); data.put("id", entity.getId()); data.put("uuid", entity.getStringUUID()); - data.put("name", entity.getName().getString()); - data.put("tags", entity.getTags()); + EntityType type = entity.getType(); + data.put("type", type.getDescriptionId()); + data.put("category", type.getCategory()); + data.put("canBurn", entity.fireImmune()); data.put("canFreeze", entity.canFreeze()); data.put("isGlowing", entity.isCurrentlyGlowing()); + data.put("isUnderWater", entity.isUnderWater()); + data.put("isInLava", entity.isInLava()); data.put("isInWall", entity.isInWall()); + data.put("pitch", entity.getYRot()); + data.put("yaw", entity.getXRot()); + if (!detailed) { + return data; + } + Team team = entity.getTeam(); + data.put("team", team != null ? team.getName() : null); + data.put("name", entity.getName().getString()); + data.put("air", entity.getAirSupply()); + data.put("maxAir", entity.getMaxAirSupply()); + data.put("frozen", entity.getTicksFrozen()); + data.put("freezeTicks", entity.getTicksRequiredToFreeze()); + data.put("tags", entity.getTags()); + if (entity instanceof InventoryCarrier carrier) { + Map invMap = new HashMap<>(); + SimpleContainer inv = carrier.getInventory(); + for (int slot = 0; slot < inv.getContainerSize(); slot++) { + ItemStack item = inv.getItem(slot); + if (!item.isEmpty()) { + invMap.put(slot, itemStackToObject(item)); + } + } + data.put("inventory", invMap); + } return data; } - public static Map livingEntityToLua(LivingEntity entity) { - Map data = entityToLua(entity); + public static Map livingEntityToLua(LivingEntity entity, boolean detailed) { + Map data = entityToLua(entity, detailed); + data.put("baby", entity.isBaby()); data.put("health", entity.getHealth()); data.put("maxHealth", entity.getMaxHealth()); data.put("lastDamageSource", entity.getLastDamageSource() == null ? null : entity.getLastDamageSource().toString()); + if (detailed) { + Map effMap = new HashMap<>(); + entity.getActiveEffectsMap().forEach((key, value) -> { + effMap.put(key.getDescriptionId(), effectToObject(value)); + }); + data.put("effects", effMap); + } return data; } - public static Map animalToLua(Animal animal, ItemStack itemInHand) { - Map data = livingEntityToLua(animal); - data.put("baby", animal.isBaby()); + public static Map animalToLua(Animal animal, ItemStack itemInHand, boolean detailed) { + Map data = livingEntityToLua(animal, detailed); data.put("inLove", animal.isInLove()); data.put("aggressive", animal.isAggressive()); if (animal instanceof IForgeShearable shareable && !itemInHand.isEmpty()) { @@ -62,14 +104,54 @@ public static Map animalToLua(Animal animal, ItemStack itemInHan return data; } + public static Map playerToLua(Player player, boolean detailed) { + Map data = livingEntityToLua(player, detailed); + data.put("score", player.getScore()); + data.put("luck", player.getLuck()); + Inventory inv = player.getInventory(); + data.put("handSlot", inv.selected); + if (detailed) { + Map invMap = new HashMap<>(); + for (int slot = 0; slot < inv.getContainerSize(); slot++) { + ItemStack item = inv.getItem(slot); + if (!item.isEmpty()) { + invMap.put(slot, itemStackToObject(item)); + } + } + data.put("inventory", invMap); + } + return data; + } + + public static Map completeEntityToLua(Entity entity) { + return completeEntityToLua(entity, false); + } + + public static Map completeEntityToLua(Entity entity, boolean detailed) { + return completeEntityToLua(entity, ItemStack.EMPTY, detailed); + } + public static Map completeEntityToLua(Entity entity, ItemStack itemInHand) { - if (entity instanceof Animal animal) return animalToLua(animal, itemInHand); - if (entity instanceof LivingEntity livingEntity) return livingEntityToLua(livingEntity); - return entityToLua(entity); + return completeEntityToLua(entity, itemInHand, false); + } + + public static Map completeEntityToLua(Entity entity, ItemStack itemInHand, boolean detailed) { + if (entity instanceof Player player) return playerToLua(player, detailed); + if (entity instanceof Animal animal) return animalToLua(animal, itemInHand, detailed); + if (entity instanceof LivingEntity livingEntity) return livingEntityToLua(livingEntity, detailed); + return entityToLua(entity, detailed); } - public static Map completeEntityWithPositionToLua(Entity entity, ItemStack itemInHand, BlockPos pos) { - Map data = completeEntityToLua(entity, itemInHand); + public static Map completeEntityWithPositionToLua(Entity entity, BlockPos pos) { + return completeEntityWithPositionToLua(entity, pos, false); + } + + public static Map completeEntityWithPositionToLua(Entity entity, BlockPos pos, boolean detailed) { + return completeEntityWithPositionToLua(entity, ItemStack.EMPTY, pos, detailed); + } + + public static Map completeEntityWithPositionToLua(Entity entity, ItemStack itemInHand, BlockPos pos, boolean detailed) { + Map data = completeEntityToLua(entity, itemInHand, detailed); data.put("x", entity.getX() - pos.getX()); data.put("y", entity.getY() - pos.getY()); data.put("z", entity.getZ() - pos.getZ()); @@ -95,8 +177,11 @@ public static Object stateToObject(Comparable blockStateValue) { } } + @Nullable public static Object posToObject(BlockPos pos) { - if (pos == null) return null; + if (pos == null) { + return null; + } Map map = new HashMap<>(3); map.put("x", pos.getX()); @@ -120,8 +205,11 @@ public static Map itemStackToObject(@NotNull ItemStack stack) { return map; } + @Nullable public static Map fluidStackToObject(@NotNull FluidStack stack) { - if (stack.isEmpty()) return new HashMap<>(); + if (stack.isEmpty()) { + return null; + } Map map = fluidToObject(stack.getFluid()); CompoundTag nbt = stack.copy().getOrCreateTag(); map.put("count", stack.getAmount()); @@ -185,10 +273,12 @@ public static String tagToString(@NotNull TagKey tag) { // BlockPos tricks public static BlockPos convertToBlockPos(Map table) throws LuaException { - if (!table.containsKey("x") || !table.containsKey("y") || !table.containsKey("z")) - throw new LuaException("Table should be block position table"); - if (!(table.get("x") instanceof Number x) || !(table.get("y") instanceof Number y) || !(table.get("z") instanceof Number z)) - throw new LuaException("Table should be block position table"); + if (!table.containsKey("x") || !table.containsKey("y") || !table.containsKey("z")) { + throw new LuaException("Table should contains key 'x', 'y' and 'z'"); + } + if (!(table.get("x") instanceof Number x) || !(table.get("y") instanceof Number y) || !(table.get("z") instanceof Number z)) { + throw new LuaException("Position should be numbers"); + } return new BlockPos(x.intValue(), y.intValue(), z.intValue()); } @@ -196,4 +286,12 @@ public static BlockPos convertToBlockPos(BlockPos center, Map table) throw BlockPos relative = convertToBlockPos(table); return new BlockPos(center.getX() + relative.getX(), center.getY() + relative.getY(), center.getZ() + relative.getZ()); } + + public static Object effectToObject(MobEffectInstance effect) { + Map map = new HashMap<>(); + map.put("name", effect.getDescriptionId()); + map.put("duration", effect.getDuration()); + map.put("amplifier", effect.getAmplifier()); + return map; + } } diff --git a/src/main/java/de/srendi/advancedperipherals/common/util/fakeplayer/FakePlayerProviderTurtle.java b/src/main/java/de/srendi/advancedperipherals/common/util/fakeplayer/FakePlayerProviderTurtle.java index eaa186d17..64cc45e22 100644 --- a/src/main/java/de/srendi/advancedperipherals/common/util/fakeplayer/FakePlayerProviderTurtle.java +++ b/src/main/java/de/srendi/advancedperipherals/common/util/fakeplayer/FakePlayerProviderTurtle.java @@ -6,13 +6,13 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.Container; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.wrapper.InvWrapper; import java.util.WeakHashMap; import java.util.function.Function; @@ -42,12 +42,12 @@ public static void load(APFakePlayer player, ITurtleAccess turtle) { playerInventory.selected = 0; // Copy primary items into player inventory and empty the rest - IItemHandler turtleInventory = turtle.getItemHandler(); - int size = turtleInventory.getSlots(); + Container turtleInventory = turtle.getInventory(); + int size = turtleInventory.getContainerSize(); int largerSize = playerInventory.getContainerSize(); playerInventory.selected = turtle.getSelectedSlot(); for (int i = 0; i < size; i++) { - playerInventory.setItem(i, turtleInventory.getStackInSlot(i)); + playerInventory.setItem(i, turtleInventory.getItem(i)); } for (int i = size; i < largerSize; i++) { playerInventory.setItem(i, ItemStack.EMPTY); @@ -55,9 +55,9 @@ public static void load(APFakePlayer player, ITurtleAccess turtle) { // Add properties ItemStack activeStack = player.getItemInHand(InteractionHand.MAIN_HAND); - if (!activeStack.isEmpty()) + if (!activeStack.isEmpty()) { player.getAttributes().addTransientAttributeModifiers(activeStack.getAttributeModifiers(EquipmentSlot.MAINHAND)); - + } } public static void unload(APFakePlayer player, ITurtleAccess turtle) { @@ -71,19 +71,19 @@ public static void unload(APFakePlayer player, ITurtleAccess turtle) { } // Copy primary items into turtle inventory and then insert/drop the rest - IItemHandlerModifiable turtleInventory = turtle.getItemHandler(); - int size = turtleInventory.getSlots(); + Container turtleInventory = turtle.getInventory(); + int size = turtleInventory.getContainerSize(); int largerSize = playerInventory.getContainerSize(); playerInventory.selected = turtle.getSelectedSlot(); for (int i = 0; i < size; i++) { - turtleInventory.setStackInSlot(i, playerInventory.getItem(i)); + turtleInventory.setItem(i, playerInventory.getItem(i)); playerInventory.setItem(i, ItemStack.EMPTY); } for (int i = size; i < largerSize; i++) { ItemStack remaining = playerInventory.getItem(i); if (!remaining.isEmpty()) { - remaining = ItemHandlerHelper.insertItem(turtleInventory, remaining, false); + remaining = ItemHandlerHelper.insertItem(new InvWrapper(turtleInventory), remaining, false); if (!remaining.isEmpty()) { BlockPos position = turtle.getPosition(); WorldUtil.dropItemStack(remaining, turtle.getLevel(), position, turtle.getDirection().getOpposite());