From 12399def3d0ee2916d964f39d7d5a96561ff8158 Mon Sep 17 00:00:00 2001 From: 1Turtle Date: Sat, 20 Jan 2024 18:07:23 +0100 Subject: [PATCH] add: Anchors where boats don't despawn --- .../partnership/client/PartnershipClient.kt | 1 + .../partnership/blockstates/anchor.json | 16 ++ .../assets/partnership/lang/de_de.json | 8 + .../assets/partnership/lang/en_gb.json | 8 + .../assets/partnership/lang/en_pt.json | 8 + .../assets/partnership/lang/en_us.json | 8 + .../assets/partnership/lang/lol_us.json | 8 + .../partnership/models/block/anchor.json | 211 ++++++++++++++++++ .../partnership/models/item/anchor.json | 3 + .../partnership/textures/block/anchor.png | Bin 0 -> 726 bytes .../mixin/BoatDespawnMixin.java | 44 ++-- .../partnership/main/Partnership.kt | 12 +- .../partnership/main/block/AnchorBlock.kt | 102 +++++++++ .../item/extendable/DescriptiveBlockItem.kt | 14 ++ .../partnership/main/level/IsDockSaveData.kt | 55 +++++ .../main/level/command/MarkChunkAsSeaport.kt | 82 +++++++ .../main/registries/BlockRegistries.kt | 14 ++ .../main/registries/CommandRegistries.kt | 12 + .../main/registries/GameRuleRegistries.kt | 2 +- .../main/registries/ItemRegistries.kt | 11 + .../tags/blocks/mineable/pickaxe.json | 3 +- .../loot_tables/blocks/anchor.json | 14 ++ .../data/partnership/recipes/anchor.json | 9 + 23 files changed, 622 insertions(+), 23 deletions(-) create mode 100644 src/client/resources/assets/partnership/blockstates/anchor.json create mode 100644 src/client/resources/assets/partnership/models/block/anchor.json create mode 100644 src/client/resources/assets/partnership/models/item/anchor.json create mode 100644 src/client/resources/assets/partnership/textures/block/anchor.png create mode 100644 src/main/kotlin/cc/tweaked_programs/partnership/main/block/AnchorBlock.kt create mode 100644 src/main/kotlin/cc/tweaked_programs/partnership/main/item/extendable/DescriptiveBlockItem.kt create mode 100644 src/main/kotlin/cc/tweaked_programs/partnership/main/level/IsDockSaveData.kt create mode 100644 src/main/kotlin/cc/tweaked_programs/partnership/main/level/command/MarkChunkAsSeaport.kt create mode 100644 src/main/kotlin/cc/tweaked_programs/partnership/main/registries/CommandRegistries.kt create mode 100644 src/main/resources/data/partnership/loot_tables/blocks/anchor.json create mode 100644 src/main/resources/data/partnership/recipes/anchor.json diff --git a/src/client/kotlin/cc/tweaked_programs/partnership/client/PartnershipClient.kt b/src/client/kotlin/cc/tweaked_programs/partnership/client/PartnershipClient.kt index 5555f9b..1858e6c 100644 --- a/src/client/kotlin/cc/tweaked_programs/partnership/client/PartnershipClient.kt +++ b/src/client/kotlin/cc/tweaked_programs/partnership/client/PartnershipClient.kt @@ -42,6 +42,7 @@ object PartnershipClient : ClientModInitializer { private fun blockRendering() { BlockRenderLayerMap.INSTANCE.putBlock(BlockRegistries.METAL_SCAFFOLDING, RenderType.cutout()) BlockRenderLayerMap.INSTANCE.putBlock(BlockRegistries.BUOY, RenderType.cutout()) + BlockRenderLayerMap.INSTANCE.putBlock(BlockRegistries.ANCHOR, RenderType.cutout()) } private fun entityRendering() { diff --git a/src/client/resources/assets/partnership/blockstates/anchor.json b/src/client/resources/assets/partnership/blockstates/anchor.json new file mode 100644 index 0000000..e2220cb --- /dev/null +++ b/src/client/resources/assets/partnership/blockstates/anchor.json @@ -0,0 +1,16 @@ +{ + "multipart": [ + { "when": { "facing": "north" }, + "apply": { "model": "partnership:block/anchor", "uvlock": false } + }, + { "when": { "facing": "east" }, + "apply": { "model": "partnership:block/anchor", "y": 90, "uvlock": false } + }, + { "when": { "facing": "south" }, + "apply": { "model": "partnership:block/anchor", "y": 180, "uvlock": false } + }, + { "when": { "facing": "west" }, + "apply": { "model": "partnership:block/anchor", "y": 270, "uvlock": false } + } + ] +} \ No newline at end of file diff --git a/src/client/resources/assets/partnership/lang/de_de.json b/src/client/resources/assets/partnership/lang/de_de.json index d9e67f7..697bc08 100644 --- a/src/client/resources/assets/partnership/lang/de_de.json +++ b/src/client/resources/assets/partnership/lang/de_de.json @@ -10,6 +10,9 @@ "block.partnership.chain_buoy": "Kettenboje", "tooltip.block.partnership.chain_buoy": "Geeignet zur Markierung von Grenzen auf dem Wasser zwischen Bojen.", + "block.partnership.anchor": "Anker", + "tooltip.block.partnership.anchor": "Ideal für Häfen zur Sicherung von Booten.", + "item.partnership.captains_hat": "Kapitänsmütze", "tooltip.item.partnership.captains_hat": "Wird vom Kapitän persönlich getragen.", @@ -53,6 +56,11 @@ "gamerule.boatDespawnTimer": "Boote verschwinden timer", + "command.partnership.feedback.error.players_only": "Nur Spieler können diesen Befehl verwenden.", + "command.partnership.feedback.dockableChunkStateNone": "Chunk %s wurde nicht als Hafen markiert.", + "command.partnership.feedback.dockableChunkStateOne": "Chunk %s wurde mit einem Anker als Hafen markiert.", + "command.partnership.feedback.dockableChunkStateMul": "Chunk %s hat %s Anker, die es als Hafen markieren.", + "modmenu.partnership.modfest": "ModFest 1.20", "modmenu.partnership.kofi": "Ko-fi", "modmenu.partnership.modrinth": "Modrinth", diff --git a/src/client/resources/assets/partnership/lang/en_gb.json b/src/client/resources/assets/partnership/lang/en_gb.json index 25e4954..1446b8c 100644 --- a/src/client/resources/assets/partnership/lang/en_gb.json +++ b/src/client/resources/assets/partnership/lang/en_gb.json @@ -10,6 +10,9 @@ "block.partnership.chain_buoy": "Chain Buoy", "tooltip.block.partnership.chain_buoy": "Used to make the borders between Buoys on water.", + "block.partnership.anchor": "Anchor", + "tooltip.block.partnership.anchor": "Ideal for docks to secure boats.", + "item.partnership.captains_hat": "Captain's Hat", "tooltip.item.partnership.captains_hat": "Worn by the captain themself.", @@ -53,6 +56,11 @@ "gamerule.boatDespawnTimer": "Boat despawn timer", + "command.partnership.feedback.error.players_only": "Only players can use this command.", + "command.partnership.feedback.dockableChunkStateNone": "Chunk %s is not being marked as dock.", + "command.partnership.feedback.dockableChunkStateOne": "Chunk %s has one anchor marking it as an dock.", + "command.partnership.feedback.dockableChunkStateMul": "Chunk %s has %s anchors marking it as an dock.", + "modmenu.partnership.modfest": "ModFest 1.20", "modmenu.partnership.kofi": "Ko-fi", "modmenu.partnership.modrinth": "Modrinth" diff --git a/src/client/resources/assets/partnership/lang/en_pt.json b/src/client/resources/assets/partnership/lang/en_pt.json index 805b33f..8154e4c 100644 --- a/src/client/resources/assets/partnership/lang/en_pt.json +++ b/src/client/resources/assets/partnership/lang/en_pt.json @@ -10,6 +10,9 @@ "block.partnership.chain_buoy": "Anchor Matey", "tooltip.block.partnership.chain_buoy": "Deployed to mark the boundaries betwixt buoys at sea.", + "block.partnership.anchor": "Bower", + "tooltip.block.partnership.anchor": "Perfect for docks to batten down the hatches of me boats.", + "item.partnership.captains_hat": "Crown o' the Ship", "tooltip.item.partnership.captains_hat": "Worn by the Cap'n himself, aye!", @@ -53,6 +56,11 @@ "gamerule.boatDespawnTimer": "Boat despawn timer", + "command.partnership.feedback.error.players_only": "Only players can use this command.", + "command.partnership.feedback.dockableChunkStateNone": "Chunk %s is not being marked as dock.", + "command.partnership.feedback.dockableChunkStateOne": "Chunk %s has one anchor marking it as an dock.", + "command.partnership.feedback.dockableChunkStateMul": "Chunk %s has %s anchors marking it as an dock.", + "modmenu.partnership.modfest": "ModFest 1.20", "modmenu.partnership.kofi": "Ko-fi", "modmenu.partnership.modrinth": "Modrinth" diff --git a/src/client/resources/assets/partnership/lang/en_us.json b/src/client/resources/assets/partnership/lang/en_us.json index c0e100e..4eb5177 100644 --- a/src/client/resources/assets/partnership/lang/en_us.json +++ b/src/client/resources/assets/partnership/lang/en_us.json @@ -11,6 +11,9 @@ "block.partnership.chain_buoy": "Chain Buoy", "tooltip.block.partnership.chain_buoy": "Used to make the borders between Buoys on water.", + "block.partnership.anchor": "Anchor", + "tooltip.block.partnership.anchor": "Ideal for docks to secure boats.", + "item.partnership.captains_hat": "Captain's Hat", "tooltip.item.partnership.captains_hat": "Worn by the captain themself.", @@ -54,6 +57,11 @@ "gamerule.boatDespawnTimer": "Boat despawn timer", + "command.partnership.feedback.error.players_only": "Only players can use this command.", + "command.partnership.feedback.dockableChunkStateNone": "Chunk %s is not being marked as dock.", + "command.partnership.feedback.dockableChunkStateOne": "Chunk %s has one anchor marking it as an dock.", + "command.partnership.feedback.dockableChunkStateMul": "Chunk %s has %s anchors marking it as an dock.", + "modmenu.partnership.modfest": "ModFest 1.20", "modmenu.partnership.kofi": "Ko-fi", "modmenu.partnership.modrinth": "Modrinth", diff --git a/src/client/resources/assets/partnership/lang/lol_us.json b/src/client/resources/assets/partnership/lang/lol_us.json index 3699618..4177c78 100644 --- a/src/client/resources/assets/partnership/lang/lol_us.json +++ b/src/client/resources/assets/partnership/lang/lol_us.json @@ -10,6 +10,9 @@ "block.partnership.chain_buoy": "buoi-chan", "tooltip.block.partnership.chain_buoy": "usd to make teh bOrderz betwin buoyZ on watr", + "block.partnership.anchor": "Anchor", + "tooltip.block.partnership.anchor": "Ideal for docks to secure boats.", + "item.partnership.captains_hat": "CAPTAInzparkls", "tooltip.item.partnership.captains_hat": "weared by teh captain, k", @@ -51,6 +54,11 @@ "gamerule.boatDespawnTimer": "Boaty despawunuy timer", + "command.partnership.feedback.error.players_only": "Only players can use this command.", + "command.partnership.feedback.dockableChunkStateNone": "Chunk %s is not being marked as dock.", + "command.partnership.feedback.dockableChunkStateOne": "Chunk %s has one anchor marking it as an dock.", + "command.partnership.feedback.dockableChunkStateMul": "Chunk %s has %s anchors marking it as an dock.", + "modmenu.partnership.modfest": "ModFest 1.20", "modmenu.partnership.kofi": "Ko-fi", "modmenu.partnership.modrinth": "Modrinth" diff --git a/src/client/resources/assets/partnership/models/block/anchor.json b/src/client/resources/assets/partnership/models/block/anchor.json new file mode 100644 index 0000000..a47b763 --- /dev/null +++ b/src/client/resources/assets/partnership/models/block/anchor.json @@ -0,0 +1,211 @@ +{ + "credit": "Sammy L. Koch | Made with Blockbench", + "parent": "minecraft:block/block", + "texture_size": [64, 64], + "textures": { + "0": "partnership:block/anchor", + "particle": "partnership:block/anchor" + }, + "elements": [ + { + "from": [4, 12, 0], + "to": [12, 14, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 0, -7]}, + "faces": { + "north": {"uv": [5, 2.5, 3, 3], "texture": "#0"}, + "east": {"uv": [6.25, 2.5, 5.75, 3], "texture": "#0"}, + "south": {"uv": [5, 2.5, 3, 3], "texture": "#0"}, + "west": {"uv": [6.25, 3, 5.75, 3.5], "texture": "#0"}, + "up": {"uv": [5, 3, 3, 3.5], "texture": "#0"}, + "down": {"uv": [5, 4, 3, 3.5], "texture": "#0"} + } + }, + { + "from": [7, 2, 0.5], + "to": [9, 16, 1.5], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 0, -7]}, + "faces": { + "north": {"uv": [3, 2.5, 2.5, 6], "texture": "#0"}, + "east": {"uv": [5.25, 0, 5, 3.5], "texture": "#0"}, + "south": {"uv": [3, 2.5, 2.5, 6], "texture": "#0"}, + "west": {"uv": [2.25, 5, 2, 8.5], "texture": "#0"}, + "up": {"uv": [6.25, 5, 5.75, 5.25], "texture": "#0"} + } + }, + { + "name": "base", + "from": [4, 0, 0], + "to": [12, 2, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 0, -7]}, + "faces": { + "north": {"uv": [5, 4, 3, 4.5], "texture": "#0"}, + "east": {"uv": [6.25, 3.5, 5.75, 4], "texture": "#0"}, + "south": {"uv": [5, 4, 3, 4.5], "texture": "#0"}, + "west": {"uv": [6.25, 4, 5.75, 4.5], "texture": "#0"}, + "up": {"uv": [5, 4.5, 3, 5], "texture": "#0"}, + "down": {"uv": [2, 5.5, 0, 5], "texture": "#0"} + } + }, + { + "name": "lower", + "from": [11.0052, -2.65165, 0.25], + "to": [16.0052, -1.15165, 1.75], + "rotation": {"angle": 45, "axis": "z", "origin": [8, 0, -7]}, + "faces": { + "north": {"uv": [6.25, 4.5, 5, 5], "texture": "#0"}, + "south": {"uv": [6.25, 4.5, 5, 5], "texture": "#0"}, + "up": {"uv": [6.5, 0, 5.25, 0.5], "texture": "#0"}, + "down": {"uv": [6.5, 1, 5.25, 0.5], "texture": "#0"} + } + }, + { + "name": "tip", + "from": [16.0052, -3.65165, -0.25], + "to": [18.0052, -0.15165, 2.25], + "rotation": {"angle": 45, "axis": "z", "origin": [8, 0, -7]}, + "faces": { + "north": {"uv": [5.75, 2.5, 5.25, 3.5], "texture": "#0"}, + "east": {"uv": [3.75, 5, 3, 6], "texture": "#0"}, + "south": {"uv": [5.75, 2.5, 5.25, 3.5], "texture": "#0"}, + "west": {"uv": [5.75, 3.5, 5, 4.5], "texture": "#0"}, + "up": {"uv": [0.5, 5.5, 0, 6.25], "texture": "#0"}, + "down": {"uv": [1, 6.25, 0.5, 5.5], "texture": "#0"} + } + }, + { + "name": "tip", + "from": [-2.0052, -3.65165, -0.25], + "to": [-0.0052, -0.15165, 2.25], + "rotation": {"angle": -45, "axis": "z", "origin": [8, 0, -7]}, + "faces": { + "north": {"uv": [5.75, 5, 5.25, 6], "texture": "#0"}, + "east": {"uv": [4.5, 5, 3.75, 6], "texture": "#0"}, + "south": {"uv": [5.75, 5, 5.25, 6], "texture": "#0"}, + "west": {"uv": [5.25, 5, 4.5, 6], "texture": "#0"}, + "up": {"uv": [1.5, 5.5, 1, 6.25], "texture": "#0"}, + "down": {"uv": [2, 6.25, 1.5, 5.5], "texture": "#0"} + } + }, + { + "name": "lower", + "from": [-0.0052, -2.65165, 0.25], + "to": [4.9948, -1.15165, 1.75], + "rotation": {"angle": -45, "axis": "z", "origin": [8, 0, -7]}, + "faces": { + "north": {"uv": [6.5, 1, 5.25, 1.5], "texture": "#0"}, + "south": {"uv": [6.5, 1, 5.25, 1.5], "texture": "#0"}, + "up": {"uv": [6.5, 1.5, 5.25, 2], "texture": "#0"}, + "down": {"uv": [6.5, 2.5, 5.25, 2], "texture": "#0"} + } + }, + { + "name": "top", + "from": [3, 16.075, -10], + "to": [13, 16.075, 0], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 0, -7]}, + "faces": { + "up": {"uv": [2.5, 0, 0, 2.5], "texture": "#0"}, + "down": {"uv": [0, 2.5, 2.5, 0], "texture": "#0"} + } + }, + { + "name": "east-west", + "from": [8, 6, -10], + "to": [8, 16, 0], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 0, -7]}, + "faces": { + "east": {"uv": [2.5, 2.5, 0, 5], "texture": "#0"}, + "west": {"uv": [2.5, 2.5, 0, 5], "texture": "#0"} + } + }, + { + "name": "north-south", + "from": [3, 6, -5], + "to": [13, 16, -5], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 0, -7]}, + "faces": { + "north": {"uv": [5, 0, 2.5, 2.5], "texture": "#0"}, + "south": {"uv": [5, 0, 2.5, 2.5], "texture": "#0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [0, 180, 0], + "translation": [0, -2.25, -5], + "scale": [0.5, 0.5, 0.5] + }, + "thirdperson_lefthand": { + "rotation": [0, 180, 0], + "translation": [0, -2.25, -5], + "scale": [0.5, 0.5, 0.5] + }, + "firstperson_righthand": { + "rotation": [-8, -60, 0], + "translation": [-0.5, 1.25, 2.25], + "scale": [0.5, 0.5, 0.5] + }, + "firstperson_lefthand": { + "rotation": [-8, -60, 0], + "translation": [-0.5, 1.25, 2.25], + "scale": [0.5, 0.5, 0.5] + }, + "ground": { + "translation": [0, 5.25, 5], + "scale": [0.5, 0.5, 0.5] + }, + "gui": { + "rotation": [20, -45, 0], + "translation": [-4, -1.75, 0], + "scale": [0.8, 0.8, 0.8] + }, + "head": { + "translation": [0, 0, 14.75] + }, + "fixed": { + "rotation": [0, 180, 0], + "translation": [0, 0, -7] + } + }, + "groups": [ + { + "name": "root", + "origin": [0, 0, 0], + "color": 0, + "children": [ + { + "name": "neck", + "origin": [0, 0, 0], + "color": 0, + "children": [0, 1] + }, + { + "name": "hook", + "origin": [4, 0.25, 1], + "color": 0, + "children": [ + 2, + { + "name": "east", + "origin": [12, 0.25, 1], + "color": 0, + "children": [3, 4] + }, + { + "name": "west", + "origin": [4, 0.25, 1], + "color": 0, + "children": [5, 6] + } + ] + }, + { + "name": "chain", + "origin": [0, 0, 0], + "color": 0, + "children": [7, 8, 9] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/client/resources/assets/partnership/models/item/anchor.json b/src/client/resources/assets/partnership/models/item/anchor.json new file mode 100644 index 0000000..a40896a --- /dev/null +++ b/src/client/resources/assets/partnership/models/item/anchor.json @@ -0,0 +1,3 @@ +{ + "parent": "partnership:block/anchor" +} \ No newline at end of file diff --git a/src/client/resources/assets/partnership/textures/block/anchor.png b/src/client/resources/assets/partnership/textures/block/anchor.png new file mode 100644 index 0000000000000000000000000000000000000000..f011743e5bef2dc64346d72de4719e07b9cf3b8b GIT binary patch literal 726 zcmV;{0xA88P) z$U>`$7Q{jm0tp&&$~Sm=kO{LpyLr>NJMsBlb~BS%o_XG91O|YJNC+VSpinH+#>$+K zbJJ6+w6M0Rt@-gSDYU@=5E^u0^7M=zQxLxxNC83!K}2MgDp0L2xjFy&aLJyC7tVn~ zu}nnN)w-!n9>1>s4M(ac#HIiuqI5QgR3?u?vD{G!hkM&tkH=i+!jUM#k*M|_L~J3@ z&9x;&M5#<3fSv?Z!jULi&AK@X0PbD;&(+_Ki>y)wi4X7ERlqqvIWw!hUtc~@(jlQK z;BapnRw;&)<3z`Wqf!NIu1iF8@F|6*_&nC*v94j@7An(ItFDT&nac)GTV z%mJpOd4N}kx3!a?My(3qKCT^dsP9c1e5412eg`XxZU=sIQszrxW4>qh6e!N9bP}Dx}cu`RYI>`zP2U1&j%j? z0CIe6d;+(37eaP-Y9H|X`g3F9U@t;dLeg^b9#6)& z^Ip%*14aR@6YNB<9$-rR1Ay4tNf2PS_`=$z?RSvt_|WmX;20J93V~6C72vl3e!~jz zTL8ad1^6w1-#mK-Fbu;m48t%C!!QiPFbu;m48t%C!!XZ*{~8`k3TcvaLjV8(07*qo IM6N<$f~>1hIRF3v literal 0 HcmV?d00001 diff --git a/src/main/java/cc/tweaked_programs/mixin/BoatDespawnMixin.java b/src/main/java/cc/tweaked_programs/mixin/BoatDespawnMixin.java index 4e95142..6cb498d 100644 --- a/src/main/java/cc/tweaked_programs/mixin/BoatDespawnMixin.java +++ b/src/main/java/cc/tweaked_programs/mixin/BoatDespawnMixin.java @@ -1,10 +1,12 @@ package cc.tweaked_programs.mixin; +import cc.tweaked_programs.partnership.main.level.command.MarkChunkAsSeaport; import cc.tweaked_programs.partnership.main.registries.GameRuleRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.VariantHolder; import net.minecraft.world.entity.vehicle.Boat; @@ -40,26 +42,30 @@ public BoatDespawnMixin(EntityType entityType, Level level) { int despawnTimer = getDespawnTimer(); int definedDespawnTimer = getDefinedDespawnTimer(this.level()); - if (definedDespawnTimer >= 0) { - // Boats should despawn - if (this.getPassengers().isEmpty()) { - // Countdown starts as boat is not being used anymore - if (despawnTimer > 0) { - despawnTimer--; - - // Make sure to stay in bounds - if (despawnTimer > definedDespawnTimer) - despawnTimer = definedDespawnTimer; - - // Update - setDespawnTimer(despawnTimer); - } else if (despawnTimer == 0) { - // Goodbye :) - this.discard(); + if (definedDespawnTimer >= 0 && !this.level().isClientSide && this.level() instanceof ServerLevel serverLevel) { + int anchors = MarkChunkAsSeaport.INSTANCE.getAnchorsOfChunk(serverLevel, this.chunkPosition()); + + if (anchors <= 0) { + // Boats should despawn + if (this.getPassengers().isEmpty()) { + // Countdown starts as boat is not being used anymore + if (despawnTimer > 0) { + despawnTimer--; + + // Make sure to stay in bounds + if (despawnTimer > definedDespawnTimer) + despawnTimer = definedDespawnTimer; + + // Update + setDespawnTimer(despawnTimer); + } else if (despawnTimer == 0) { + // Goodbye :) + this.discard(); + } + } else if (despawnTimer >= 0) { + // Reset timer + setDespawnTimer(getDefinedDespawnTimer(this.level())); } - } else if (despawnTimer >= 0) { - // Reset timer - setDespawnTimer(getDefinedDespawnTimer(this.level())); } } } diff --git a/src/main/kotlin/cc/tweaked_programs/partnership/main/Partnership.kt b/src/main/kotlin/cc/tweaked_programs/partnership/main/Partnership.kt index bdb41cf..f9e5fc3 100644 --- a/src/main/kotlin/cc/tweaked_programs/partnership/main/Partnership.kt +++ b/src/main/kotlin/cc/tweaked_programs/partnership/main/Partnership.kt @@ -14,8 +14,16 @@ object Partnership : ModInitializer { val logger: Logger = LoggerFactory.getLogger(MOD_ID) override fun onInitialize() { - // WAKE UP - BlockRegistries; BlockEntityRegistries; ItemRegistries; GroupRegistries; MenuRegistries; RecipeRegistries; EntityRegistries; NetworkRegistries; GameRuleRegistries + BlockRegistries + BlockEntityRegistries + ItemRegistries + GroupRegistries + MenuRegistries + RecipeRegistries + EntityRegistries + NetworkRegistries + GameRuleRegistries + CommandRegistries Compat.check() } diff --git a/src/main/kotlin/cc/tweaked_programs/partnership/main/block/AnchorBlock.kt b/src/main/kotlin/cc/tweaked_programs/partnership/main/block/AnchorBlock.kt new file mode 100644 index 0000000..e9f94eb --- /dev/null +++ b/src/main/kotlin/cc/tweaked_programs/partnership/main/block/AnchorBlock.kt @@ -0,0 +1,102 @@ +package cc.tweaked_programs.partnership.main.block + +import cc.tweaked_programs.partnership.main.level.command.MarkChunkAsSeaport +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.item.context.BlockPlaceContext +import net.minecraft.world.level.BlockGetter +import net.minecraft.world.level.Level +import net.minecraft.world.level.LevelAccessor +import net.minecraft.world.level.block.* +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.block.state.StateDefinition +import net.minecraft.world.level.block.state.properties.BlockStateProperties +import net.minecraft.world.level.material.FluidState +import net.minecraft.world.level.material.Fluids +import net.minecraft.world.phys.shapes.CollisionContext +import net.minecraft.world.phys.shapes.Shapes +import net.minecraft.world.phys.shapes.VoxelShape + +class AnchorBlock(properties: Properties) : Block(properties), SimpleWaterloggedBlock { + + init { + registerDefaultState(stateDefinition.any() + .setValue(BlockStateProperties.HORIZONTAL_FACING, Direction.NORTH) + .setValue(BlockStateProperties.WATERLOGGED, false) + ) + } + + override fun createBlockStateDefinition(builder: StateDefinition.Builder) { builder + .add(BlockStateProperties.HORIZONTAL_FACING) + .add(BlockStateProperties.WATERLOGGED) + } + + override fun getStateForPlacement(ctx: BlockPlaceContext): BlockState? = defaultBlockState() + .setValue(BlockStateProperties.HORIZONTAL_FACING, if (ctx.player?.isCrouching == true) ctx.horizontalDirection.opposite else ctx.horizontalDirection) + .setValue(BlockStateProperties.WATERLOGGED, ctx.level + .getFluidState(ctx.clickedPos).type === Fluids.WATER) + + @Suppress("OVERRIDE_DEPRECATION", "DEPRECATION") + override fun updateShape(blockState: BlockState, direction: Direction, targetBlockState: BlockState, + levelAccessor: LevelAccessor, blockPos: BlockPos, targetBlockPos: BlockPos): BlockState? { + + if (blockState.getValue(ChainBlock.WATERLOGGED)) + levelAccessor.scheduleTick(blockPos, Fluids.WATER, Fluids.WATER.getTickDelay(levelAccessor)) + + return super.updateShape(blockState, direction, targetBlockState, levelAccessor, blockPos, targetBlockPos) + } + + @Suppress("OVERRIDE_DEPRECATION", "DEPRECATION") + override fun getFluidState(blockState: BlockState): FluidState { + if (blockState.getValue(ChainBlock.WATERLOGGED)) + return Fluids.WATER.getSource(false) + + return super.getFluidState(blockState) + } + + @Suppress("OVERRIDE_DEPRECATION") + override fun rotate(blockState: BlockState, rotation: Rotation): BlockState { + return blockState.setValue( + HorizontalDirectionalBlock.FACING, rotation.rotate(blockState.getValue( + HorizontalDirectionalBlock.FACING) as Direction)) as BlockState + } + + @Suppress("OVERRIDE_DEPRECATION") + override fun mirror(blockState: BlockState, mirror: Mirror): BlockState { + return blockState.rotate(mirror.getRotation(blockState.getValue(HorizontalDirectionalBlock.FACING) as Direction)) + } + + @Suppress("OVERRIDE_DEPRECATION") + override fun getShape(blockState: BlockState, blockGetter: BlockGetter, blockPos: BlockPos, + collisionContext: CollisionContext + ): VoxelShape = when(blockState.getValue(HorizontalDirectionalBlock.FACING)) { + Direction.NORTH -> Shapes.create(0.0, 0.0, 0.0, 1.0, 1.0, 0.125) + Direction.EAST -> Shapes.create(0.875, 0.0, 0.0, 1.0, 1.0, 1.0) + Direction.SOUTH -> Shapes.create(0.0, 0.0, 0.875, 1.0, 1.0, 1.0) + Direction.WEST -> Shapes.create(0.0, 0.0, 0.0, 0.125, 1.0, 1.0) + else -> Shapes.block() + } + + @Suppress("OVERRIDE_DEPRECATION", "DEPRECATION") + override fun onPlace(blockState: BlockState, level: Level, blockPos: BlockPos, blockState2: BlockState, bl: Boolean) { + super.onPlace(blockState, level, blockPos, blockState2, bl) + if (!level.isClientSide && level is ServerLevel) { + val chunkPos = level.getChunk(blockPos).pos + val anchors = MarkChunkAsSeaport.getAnchorsOfChunk(level, chunkPos) + + MarkChunkAsSeaport.setChunk(level, chunkPos, anchors+1) + } + } + + @Suppress("OVERRIDE_DEPRECATION", "DEPRECATION") + override fun onRemove(blockState: BlockState, level: Level, blockPos: BlockPos, blockState2: BlockState, bl: Boolean) { + super.onRemove(blockState, level, blockPos, blockState2, bl) + if (!level.isClientSide && level is ServerLevel) { + val chunkPos = level.getChunk(blockPos).pos + val anchors = MarkChunkAsSeaport.getAnchorsOfChunk(level, chunkPos) + + MarkChunkAsSeaport.setChunk(level, chunkPos, anchors-1) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/cc/tweaked_programs/partnership/main/item/extendable/DescriptiveBlockItem.kt b/src/main/kotlin/cc/tweaked_programs/partnership/main/item/extendable/DescriptiveBlockItem.kt new file mode 100644 index 0000000..ef7d11f --- /dev/null +++ b/src/main/kotlin/cc/tweaked_programs/partnership/main/item/extendable/DescriptiveBlockItem.kt @@ -0,0 +1,14 @@ +package cc.tweaked_programs.partnership.main.item.extendable + +import net.minecraft.network.chat.Component +import net.minecraft.world.item.BlockItem +import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.TooltipFlag +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block + +class DescriptiveBlockItem(block: Block, properties: Properties) : BlockItem(block, properties) { + + override fun appendHoverText(itemStack: ItemStack, level: Level?, list: MutableList, tooltipFlag: TooltipFlag) + = AdvancedItemDescription.appendHoverText(descriptionId, false, list) +} \ No newline at end of file diff --git a/src/main/kotlin/cc/tweaked_programs/partnership/main/level/IsDockSaveData.kt b/src/main/kotlin/cc/tweaked_programs/partnership/main/level/IsDockSaveData.kt new file mode 100644 index 0000000..4295e6f --- /dev/null +++ b/src/main/kotlin/cc/tweaked_programs/partnership/main/level/IsDockSaveData.kt @@ -0,0 +1,55 @@ +package cc.tweaked_programs.partnership.main.level + +import net.minecraft.nbt.* +import net.minecraft.util.datafix.DataFixTypes +import net.minecraft.world.level.ChunkPos +import net.minecraft.world.level.saveddata.SavedData + + +class IsDockSaveData : SavedData() { + + var dockableChunks: MutableMap = mutableMapOf() + + override fun save(tag: CompoundTag): CompoundTag { + val chunksTag = ListTag() + dockableChunks.forEach { (pos, value) -> + chunksTag.add(CompoundTag().apply { + putLong("pos", pos) + putInt("value", value) + }) + } + tag.put(CHUNKS_KEY_TAG, chunksTag) + + return tag + } + + fun get(pos: ChunkPos): Int = dockableChunks[pos.toLong()] ?: 0 + + companion object { + const val FILE_NAME = "partnershipDockableChunks" + const val CHUNKS_KEY_TAG = "dockableChunks" + + val FACTORY = Factory( + this::create, + this::load, + DataFixTypes.LEVEL + ) + + fun create() = IsDockSaveData() + + private fun load(tag: CompoundTag): IsDockSaveData { + val data = this.create() + + tag.getList(CHUNKS_KEY_TAG, Tag.TAG_COMPOUND.toInt()).forEach { entryTag -> + entryTag as CompoundTag + + val pos = entryTag.getLong("pos") + val value = entryTag.getInt("value") + + data.dockableChunks[pos] = value + } + + return data + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/cc/tweaked_programs/partnership/main/level/command/MarkChunkAsSeaport.kt b/src/main/kotlin/cc/tweaked_programs/partnership/main/level/command/MarkChunkAsSeaport.kt new file mode 100644 index 0000000..c960792 --- /dev/null +++ b/src/main/kotlin/cc/tweaked_programs/partnership/main/level/command/MarkChunkAsSeaport.kt @@ -0,0 +1,82 @@ +package cc.tweaked_programs.partnership.main.level.command + +import cc.tweaked_programs.partnership.main.level.IsDockSaveData +import com.mojang.brigadier.Command +import com.mojang.brigadier.CommandDispatcher +import com.mojang.brigadier.arguments.IntegerArgumentType.getInteger +import com.mojang.brigadier.arguments.IntegerArgumentType.integer +import com.mojang.brigadier.builder.LiteralArgumentBuilder.literal +import com.mojang.brigadier.builder.RequiredArgumentBuilder.argument +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType +import net.minecraft.commands.CommandSourceStack +import net.minecraft.network.chat.Component +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.level.ChunkPos + + +object MarkChunkAsSeaport { + fun register(dispatcher: CommandDispatcher) { + dispatcher.register(literal("partnership") + .requires { source -> source.hasPermission(3) } + + .then(literal("isChunkDockable") + .executes { context -> + if (context.source.entity == null) + throw SimpleCommandExceptionType(Component.translatable("command.partnership.feedback.error.players_only")).create() + + val data = context.source.level.dataStorage.computeIfAbsent(IsDockSaveData.FACTORY, IsDockSaveData.FILE_NAME) + val chunk = context.source.entity?.chunkPosition()!! + val anchors = data.get(chunk) + + val pos = "[${chunk.x}, ${chunk.z}]" + val result = when (anchors) { + 0 -> Component.translatable("command.partnership.feedback.dockableChunkStateNone").string.format(pos) + 1 -> Component.translatable("command.partnership.feedback.dockableChunkStateOne").string.format(pos) + else -> Component.translatable("command.partnership.feedback.dockableChunkStateMul").string.format(pos, anchors) + } + + context.source.sendSuccess({ Component.literal(result) } , true) + Command.SINGLE_SUCCESS + } + + .then(argument("anchors", integer()) + .executes { context -> + + if (!context.source.isPlayer) + throw SimpleCommandExceptionType(Component.translatable("command.partnership.feedback.error.players_only")).create() + + val anchors = getInteger(context, "anchors") + val chunk = context.source.player!!.chunkPosition() + val pos = "[${chunk.x}, ${chunk.z}]" + + setChunk(context.source.level, chunk, anchors) + + val result = when (anchors) { + 0 -> Component.translatable("command.partnership.feedback.dockableChunkStateNone").string.format(pos) + 1 -> Component.translatable("command.partnership.feedback.dockableChunkStateOne").string.format(pos) + else -> Component.translatable("command.partnership.feedback.dockableChunkStateMul").string.format(pos, anchors) + } + + context.source.sendSuccess({ Component.literal(result) } , true) + Command.SINGLE_SUCCESS + }) + ) + ) + } + + fun setChunk(level: ServerLevel, chunk: ChunkPos, anchors: Int) { + val data = level.dataStorage.computeIfAbsent(IsDockSaveData.FACTORY, IsDockSaveData.FILE_NAME) + + if (anchors == 0) + data.dockableChunks.remove(chunk.toLong()) + else data.dockableChunks[chunk.toLong()] = anchors + + data.setDirty() + level.dataStorage.save() + } + + fun getAnchorsOfChunk(level: ServerLevel, chunk: ChunkPos): Int { + val data = level.dataStorage.computeIfAbsent(IsDockSaveData.FACTORY, IsDockSaveData.FILE_NAME) + return data.get(chunk) + } +} diff --git a/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/BlockRegistries.kt b/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/BlockRegistries.kt index ef6bb38..eff255a 100644 --- a/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/BlockRegistries.kt +++ b/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/BlockRegistries.kt @@ -1,6 +1,7 @@ package cc.tweaked_programs.partnership.main.registries import cc.tweaked_programs.partnership.main.MOD_ID +import cc.tweaked_programs.partnership.main.block.AnchorBlock import cc.tweaked_programs.partnership.main.block.MetalScaffoldingBlock import cc.tweaked_programs.partnership.main.block.boatyard.BoatyardBlock import cc.tweaked_programs.partnership.main.block.buoy.BuoyBlock @@ -12,6 +13,7 @@ import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.resources.ResourceLocation import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.SoundType +import net.minecraft.world.level.material.PushReaction object BlockRegistries { @@ -74,4 +76,16 @@ object BlockRegistries { .strength(1.25F) .nonOpaque()) } + + val ANCHOR = create( + name = "anchor" + ) { properties -> + AnchorBlock( + properties + .sounds(SoundType.METAL) + .strength(6F) + .pistonBehavior(PushReaction.IGNORE) + .nonOpaque() + ) + } } \ No newline at end of file diff --git a/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/CommandRegistries.kt b/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/CommandRegistries.kt new file mode 100644 index 0000000..03f1817 --- /dev/null +++ b/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/CommandRegistries.kt @@ -0,0 +1,12 @@ +package cc.tweaked_programs.partnership.main.registries + +import cc.tweaked_programs.partnership.main.level.command.MarkChunkAsSeaport +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback + +object CommandRegistries { + init { + CommandRegistrationCallback.EVENT.register { dispatcher, commandBuildContext, commandSelection -> + MarkChunkAsSeaport.register(dispatcher) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/GameRuleRegistries.kt b/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/GameRuleRegistries.kt index 0095321..f46e711 100644 --- a/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/GameRuleRegistries.kt +++ b/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/GameRuleRegistries.kt @@ -5,5 +5,5 @@ import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry import net.minecraft.world.level.GameRules object GameRuleRegistries { - val BOAT_DESPAWN_TIMER = GameRuleRegistry.register("boatDespawnTimer", GameRules.Category.MISC, GameRuleFactory.createIntRule(-1)) + val BOAT_DESPAWN_TIMER: GameRules.Key = GameRuleRegistry.register("boatDespawnTimer", GameRules.Category.MISC, GameRuleFactory.createIntRule(-1)) } \ No newline at end of file diff --git a/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/ItemRegistries.kt b/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/ItemRegistries.kt index 6db8f58..8108d8f 100644 --- a/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/ItemRegistries.kt +++ b/src/main/kotlin/cc/tweaked_programs/partnership/main/registries/ItemRegistries.kt @@ -7,6 +7,7 @@ import cc.tweaked_programs.partnership.main.entity.Sailboat import cc.tweaked_programs.partnership.main.item.BoatyardItem import cc.tweaked_programs.partnership.main.item.Hat import cc.tweaked_programs.partnership.main.item.PaddleItem +import cc.tweaked_programs.partnership.main.item.extendable.DescriptiveBlockItem import cc.tweaked_programs.partnership.main.item.extendable.DescriptivePlaceOnWaterBlockItem import cc.tweaked_programs.partnership.main.item.extendable.GenericBoatItem import cc.tweaked_programs.partnership.main.item.extendable.GenericDescriptiveBlockItem @@ -56,6 +57,7 @@ object ItemRegistries { val PLANK: Item val MARINE_CANNON: Item val CANNONBALL: Item + val ANCHOR: Item init { KAYAK = create( @@ -243,5 +245,14 @@ object ItemRegistries { }, itemSupplier = { properties -> Item(properties.maxCount(64)) } ) + + ANCHOR = create( + name = "anchor", + category = CreativeModeTabs.BUILDING_BLOCKS, + categoryRegister = { content, item -> + content.addAfter(Items.NETHERITE_BLOCK, item) + }, + itemSupplier = { properties -> DescriptiveBlockItem(BlockRegistries.ANCHOR, properties.maxCount(1)) } + ) } } \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json b/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json index af011cf..36dcf1d 100644 --- a/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json +++ b/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json @@ -3,6 +3,7 @@ "values": [ "partnership:boatyard", "partnership:metal_scaffolding", - "partnership:marine_cannon" + "partnership:marine_cannon", + "partnership:anchor" ] } diff --git a/src/main/resources/data/partnership/loot_tables/blocks/anchor.json b/src/main/resources/data/partnership/loot_tables/blocks/anchor.json new file mode 100644 index 0000000..5ebd78b --- /dev/null +++ b/src/main/resources/data/partnership/loot_tables/blocks/anchor.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "partnership:anchor" + } + ] + } + ] +} diff --git a/src/main/resources/data/partnership/recipes/anchor.json b/src/main/resources/data/partnership/recipes/anchor.json new file mode 100644 index 0000000..0cb8c39 --- /dev/null +++ b/src/main/resources/data/partnership/recipes/anchor.json @@ -0,0 +1,9 @@ +{ + "type": "partnership:boatyard_construct_serializer", + "ingredients": [ + {"id": "minecraft:netherite_hoe", "Count": 1}, {"id": "minecraft:air", "Count": 1}, {"id": "minecraft:air", "Count": 1}, {"id": "minecraft:air", "Count": 1}, + {"id": "minecraft:iron_ingot", "Count": 1}, {"id": "minecraft:iron_ingot", "Count": 1}, {"id": "minecraft:iron_ingot", "Count": 1}, {"id": "minecraft:chain", "Count": 2}, + {"id": "minecraft:netherite_hoe", "Count": 1}, {"id": "minecraft:air", "Count": 1}, {"id": "minecraft:air", "Count": 1}, {"id": "minecraft:air", "Count": 1} + ], + "output": {"id": "partnership:anchor", "Count": 1} +}