diff --git a/CHANGELOG.md b/CHANGELOG.md index 59767ae..9b30ddc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,6 @@ ## Bugfixes -- Rectify buggy implementation of Advanced Barriers. +- typo: `condition` field (previously `conditions`) in `PredicateBarrierBlock` +- fix: Don't cache registry accesses + +## Changes +- Operator items can now only be placed in creative mode diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f1f6aee --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,6 @@ +# Contribution Guide +Hello, contributor! There are a few things you need to know before contributing to Barricade. + +## JDK +You will need the [JetBrains Runtime](https://github.com/JetBrains/JetBrainsRuntime) or a JDK with DCEVM support. +If you use IntelliJ, you can download the JBR through the GUI. You can change the JDK in IntelliJ in File → Project Structure → Project → SDK. diff --git a/README.md b/README.md index 930e0e6..5f33169 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ This mod may also change barrier and light block rendering, to be friendlier to You can enable/disable the above by applying/removing the Barricade Rendering resource pack. +## Contribution +Please read the `CONTRIBUTING.md` document before contributing or if you have any issues building the mod. + ## Client-side Only This mod is able to run on clients without having it on the server. When run like this, the mod will only apply the diff --git a/buildSrc/src/main/kotlin/net/modgarden/barricade/gradle/Versions.kt b/buildSrc/src/main/kotlin/net/modgarden/barricade/gradle/Versions.kt index d1427d4..3553118 100644 --- a/buildSrc/src/main/kotlin/net/modgarden/barricade/gradle/Versions.kt +++ b/buildSrc/src/main/kotlin/net/modgarden/barricade/gradle/Versions.kt @@ -1,7 +1,7 @@ package net.modgarden.barricade.gradle object Versions { - const val MOD = "2.0.7" + const val MOD = "2.1.0" const val MINECRAFT = "1.21.1" const val PARCHMENT_MINECRAFT = "1.21" diff --git a/common/src/generated/resources/assets/barricade/blockstates/creative_only_button.json b/common/src/generated/resources/assets/barricade/blockstates/creative_only_button.json new file mode 100644 index 0000000..293b4ee --- /dev/null +++ b/common/src/generated/resources/assets/barricade/blockstates/creative_only_button.json @@ -0,0 +1,118 @@ +{ + "variants": { + "face=ceiling,facing=east,powered=false": { + "model": "barricade:block/creative_only_button", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=east,powered=true": { + "model": "barricade:block/creative_only_button_pressed", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=north,powered=false": { + "model": "barricade:block/creative_only_button", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=north,powered=true": { + "model": "barricade:block/creative_only_button_pressed", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=south,powered=false": { + "model": "barricade:block/creative_only_button", + "x": 180 + }, + "face=ceiling,facing=south,powered=true": { + "model": "barricade:block/creative_only_button_pressed", + "x": 180 + }, + "face=ceiling,facing=west,powered=false": { + "model": "barricade:block/creative_only_button", + "x": 180, + "y": 90 + }, + "face=ceiling,facing=west,powered=true": { + "model": "barricade:block/creative_only_button_pressed", + "x": 180, + "y": 90 + }, + "face=floor,facing=east,powered=false": { + "model": "barricade:block/creative_only_button", + "y": 90 + }, + "face=floor,facing=east,powered=true": { + "model": "barricade:block/creative_only_button_pressed", + "y": 90 + }, + "face=floor,facing=north,powered=false": { + "model": "barricade:block/creative_only_button" + }, + "face=floor,facing=north,powered=true": { + "model": "barricade:block/creative_only_button_pressed" + }, + "face=floor,facing=south,powered=false": { + "model": "barricade:block/creative_only_button", + "y": 180 + }, + "face=floor,facing=south,powered=true": { + "model": "barricade:block/creative_only_button_pressed", + "y": 180 + }, + "face=floor,facing=west,powered=false": { + "model": "barricade:block/creative_only_button", + "y": 270 + }, + "face=floor,facing=west,powered=true": { + "model": "barricade:block/creative_only_button_pressed", + "y": 270 + }, + "face=wall,facing=east,powered=false": { + "model": "barricade:block/creative_only_button", + "uvlock": true, + "x": 90, + "y": 90 + }, + "face=wall,facing=east,powered=true": { + "model": "barricade:block/creative_only_button_pressed", + "uvlock": true, + "x": 90, + "y": 90 + }, + "face=wall,facing=north,powered=false": { + "model": "barricade:block/creative_only_button", + "uvlock": true, + "x": 90 + }, + "face=wall,facing=north,powered=true": { + "model": "barricade:block/creative_only_button_pressed", + "uvlock": true, + "x": 90 + }, + "face=wall,facing=south,powered=false": { + "model": "barricade:block/creative_only_button", + "uvlock": true, + "x": 90, + "y": 180 + }, + "face=wall,facing=south,powered=true": { + "model": "barricade:block/creative_only_button_pressed", + "uvlock": true, + "x": 90, + "y": 180 + }, + "face=wall,facing=west,powered=false": { + "model": "barricade:block/creative_only_button", + "uvlock": true, + "x": 90, + "y": 270 + }, + "face=wall,facing=west,powered=true": { + "model": "barricade:block/creative_only_button_pressed", + "uvlock": true, + "x": 90, + "y": 270 + } + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/barricade/blockstates/creative_only_lever.json b/common/src/generated/resources/assets/barricade/blockstates/creative_only_lever.json new file mode 100644 index 0000000..f5892ec --- /dev/null +++ b/common/src/generated/resources/assets/barricade/blockstates/creative_only_lever.json @@ -0,0 +1,110 @@ +{ + "variants": { + "face=ceiling,facing=east,powered=false": { + "model": "minecraft:block/lever_on", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=east,powered=true": { + "model": "minecraft:block/lever", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=north,powered=false": { + "model": "minecraft:block/lever_on", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=north,powered=true": { + "model": "minecraft:block/lever", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=south,powered=false": { + "model": "minecraft:block/lever_on", + "x": 180 + }, + "face=ceiling,facing=south,powered=true": { + "model": "minecraft:block/lever", + "x": 180 + }, + "face=ceiling,facing=west,powered=false": { + "model": "minecraft:block/lever_on", + "x": 180, + "y": 90 + }, + "face=ceiling,facing=west,powered=true": { + "model": "minecraft:block/lever", + "x": 180, + "y": 90 + }, + "face=floor,facing=east,powered=false": { + "model": "minecraft:block/lever_on", + "y": 90 + }, + "face=floor,facing=east,powered=true": { + "model": "minecraft:block/lever", + "y": 90 + }, + "face=floor,facing=north,powered=false": { + "model": "minecraft:block/lever_on" + }, + "face=floor,facing=north,powered=true": { + "model": "minecraft:block/lever" + }, + "face=floor,facing=south,powered=false": { + "model": "minecraft:block/lever_on", + "y": 180 + }, + "face=floor,facing=south,powered=true": { + "model": "minecraft:block/lever", + "y": 180 + }, + "face=floor,facing=west,powered=false": { + "model": "minecraft:block/lever_on", + "y": 270 + }, + "face=floor,facing=west,powered=true": { + "model": "minecraft:block/lever", + "y": 270 + }, + "face=wall,facing=east,powered=false": { + "model": "minecraft:block/lever_on", + "x": 90, + "y": 90 + }, + "face=wall,facing=east,powered=true": { + "model": "minecraft:block/lever", + "x": 90, + "y": 90 + }, + "face=wall,facing=north,powered=false": { + "model": "minecraft:block/lever_on", + "x": 90 + }, + "face=wall,facing=north,powered=true": { + "model": "minecraft:block/lever", + "x": 90 + }, + "face=wall,facing=south,powered=false": { + "model": "minecraft:block/lever_on", + "x": 90, + "y": 180 + }, + "face=wall,facing=south,powered=true": { + "model": "minecraft:block/lever", + "x": 90, + "y": 180 + }, + "face=wall,facing=west,powered=false": { + "model": "minecraft:block/lever_on", + "x": 90, + "y": 270 + }, + "face=wall,facing=west,powered=true": { + "model": "minecraft:block/lever", + "x": 90, + "y": 270 + } + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/barricade/models/block/creative_only_button.json b/common/src/generated/resources/assets/barricade/models/block/creative_only_button.json new file mode 100644 index 0000000..42d1cc4 --- /dev/null +++ b/common/src/generated/resources/assets/barricade/models/block/creative_only_button.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/button", + "textures": { + "texture": "minecraft:block/stone" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/barricade/models/block/creative_only_button_inventory.json b/common/src/generated/resources/assets/barricade/models/block/creative_only_button_inventory.json new file mode 100644 index 0000000..ffee63f --- /dev/null +++ b/common/src/generated/resources/assets/barricade/models/block/creative_only_button_inventory.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/button_inventory", + "textures": { + "texture": "minecraft:block/stone" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/barricade/models/block/creative_only_button_pressed.json b/common/src/generated/resources/assets/barricade/models/block/creative_only_button_pressed.json new file mode 100644 index 0000000..4606dfa --- /dev/null +++ b/common/src/generated/resources/assets/barricade/models/block/creative_only_button_pressed.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/button_pressed", + "textures": { + "texture": "minecraft:block/stone" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/barricade/models/item/creative_only_button.json b/common/src/generated/resources/assets/barricade/models/item/creative_only_button.json new file mode 100644 index 0000000..fb2ea8d --- /dev/null +++ b/common/src/generated/resources/assets/barricade/models/item/creative_only_button.json @@ -0,0 +1,3 @@ +{ + "parent": "barricade:block/creative_only_button_inventory" +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/barricade/models/item/creative_only_lever.json b/common/src/generated/resources/assets/barricade/models/item/creative_only_lever.json new file mode 100644 index 0000000..d5a62d4 --- /dev/null +++ b/common/src/generated/resources/assets/barricade/models/item/creative_only_lever.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "minecraft:block/lever" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/data/barricade/tags/block/barriers.json b/common/src/generated/resources/data/barricade/tags/block/barriers.json index 0aea222..a362f4b 100644 --- a/common/src/generated/resources/data/barricade/tags/block/barriers.json +++ b/common/src/generated/resources/data/barricade/tags/block/barriers.json @@ -1,7 +1,7 @@ { - "values": [ - "minecraft:barrier", - "#barricade:directional_barriers", - "#barricade:predicate_barriers" - ] -} + "values": [ + "minecraft:barrier", + "#barricade:directional_barriers", + "#barricade:predicate_barriers" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/barricade/tags/block/directional_barriers.json b/common/src/generated/resources/data/barricade/tags/block/directional_barriers.json index 2de5dab..46d3f0a 100644 --- a/common/src/generated/resources/data/barricade/tags/block/directional_barriers.json +++ b/common/src/generated/resources/data/barricade/tags/block/directional_barriers.json @@ -1,13 +1,13 @@ { - "values": [ - "barricade:advanced_barrier", - "barricade:down_barrier", - "barricade:up_barrier", - "barricade:north_barrier", - "barricade:south_barrier", - "barricade:east_barrier", - "barricade:west_barrier", - "barricade:horizontal_barrier", - "barricade:vertical_barrier" - ] -} + "values": [ + "barricade:advanced_barrier", + "barricade:down_barrier", + "barricade:up_barrier", + "barricade:north_barrier", + "barricade:south_barrier", + "barricade:east_barrier", + "barricade:west_barrier", + "barricade:horizontal_barrier", + "barricade:vertical_barrier" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/barricade/tags/block/entity_barriers.json b/common/src/generated/resources/data/barricade/tags/block/entity_barriers.json index b37f51d..d20f437 100644 --- a/common/src/generated/resources/data/barricade/tags/block/entity_barriers.json +++ b/common/src/generated/resources/data/barricade/tags/block/entity_barriers.json @@ -1,9 +1,9 @@ { - "values": [ - "barricade:advanced_barrier", - "barricade:player_barrier", - "barricade:mob_barrier", - "barricade:passive_barrier", - "barricade:hostile_barrier" - ] -} + "values": [ + "barricade:advanced_barrier", + "barricade:player_barrier", + "barricade:mob_barrier", + "barricade:passive_barrier", + "barricade:hostile_barrier" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/barricade/tags/block/predicate_barriers.json b/common/src/generated/resources/data/barricade/tags/block/predicate_barriers.json index fb86b88..b0be017 100644 --- a/common/src/generated/resources/data/barricade/tags/block/predicate_barriers.json +++ b/common/src/generated/resources/data/barricade/tags/block/predicate_barriers.json @@ -1,6 +1,6 @@ { - "values": [ - "#barricade:entity_barriers", - "barricade:creative_only_barrier" - ] -} + "values": [ + "#barricade:entity_barriers", + "barricade:creative_only_barrier" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/barricade/tags/entity_type/blocked_by_hostile_barrier.json b/common/src/generated/resources/data/barricade/tags/entity_type/blocked_by_hostile_barrier.json index 77e0e87..17f0467 100644 --- a/common/src/generated/resources/data/barricade/tags/entity_type/blocked_by_hostile_barrier.json +++ b/common/src/generated/resources/data/barricade/tags/entity_type/blocked_by_hostile_barrier.json @@ -1,37 +1,37 @@ { - "values": [ - "minecraft:blaze", - "minecraft:bogged", - "minecraft:breeze", - "minecraft:cave_spider", - "minecraft:creeper", - "minecraft:drowned", - "minecraft:elder_guardian", - "minecraft:ender_dragon", - "minecraft:enderman", - "minecraft:endermite", - "minecraft:ghast", - "minecraft:giant", - "minecraft:guardian", - "minecraft:hoglin", - "minecraft:husk", - "minecraft:magma_cube", - "minecraft:phantom", - "minecraft:piglin", - "minecraft:piglin_brute", - "minecraft:shulker", - "minecraft:skeleton", - "minecraft:slime", - "minecraft:spider", - "minecraft:stray", - "minecraft:vex", - "minecraft:warden", - "minecraft:witch", - "minecraft:wither", - "minecraft:wither_skeleton", - "minecraft:zoglin", - "minecraft:zombie", - "minecraft:zombie_villager", - "#minecraft:raiders" - ] -} + "values": [ + "minecraft:blaze", + "minecraft:bogged", + "minecraft:breeze", + "minecraft:cave_spider", + "minecraft:creeper", + "minecraft:drowned", + "minecraft:elder_guardian", + "minecraft:ender_dragon", + "minecraft:enderman", + "minecraft:endermite", + "minecraft:ghast", + "minecraft:giant", + "minecraft:guardian", + "minecraft:hoglin", + "minecraft:husk", + "minecraft:magma_cube", + "minecraft:phantom", + "minecraft:piglin", + "minecraft:piglin_brute", + "minecraft:shulker", + "minecraft:skeleton", + "minecraft:slime", + "minecraft:spider", + "minecraft:stray", + "minecraft:vex", + "minecraft:warden", + "minecraft:witch", + "minecraft:wither", + "minecraft:wither_skeleton", + "minecraft:zoglin", + "minecraft:zombie", + "minecraft:zombie_villager", + "#minecraft:raiders" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/barricade/tags/entity_type/blocked_by_mob_barrier.json b/common/src/generated/resources/data/barricade/tags/entity_type/blocked_by_mob_barrier.json index c93d41c..8ffff39 100644 --- a/common/src/generated/resources/data/barricade/tags/entity_type/blocked_by_mob_barrier.json +++ b/common/src/generated/resources/data/barricade/tags/entity_type/blocked_by_mob_barrier.json @@ -1,6 +1,6 @@ { - "values": [ - "#barricade:blocked_by_hostile_barrier", - "#barricade:blocked_by_passive_barrier" - ] -} + "values": [ + "#barricade:blocked_by_hostile_barrier", + "#barricade:blocked_by_passive_barrier" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/barricade/tags/entity_type/blocked_by_passive_barrier.json b/common/src/generated/resources/data/barricade/tags/entity_type/blocked_by_passive_barrier.json index 4ea82fe..6339328 100644 --- a/common/src/generated/resources/data/barricade/tags/entity_type/blocked_by_passive_barrier.json +++ b/common/src/generated/resources/data/barricade/tags/entity_type/blocked_by_passive_barrier.json @@ -1,47 +1,47 @@ { - "values": [ - "minecraft:allay", - "minecraft:armadillo", - "minecraft:axolotl", - "minecraft:bat", - "minecraft:bee", - "minecraft:camel", - "minecraft:cat", - "minecraft:chicken", - "minecraft:cod", - "minecraft:cow", - "minecraft:dolphin", - "minecraft:donkey", - "minecraft:fox", - "minecraft:frog", - "minecraft:glow_squid", - "minecraft:goat", - "minecraft:horse", - "minecraft:iron_golem", - "minecraft:llama", - "minecraft:mooshroom", - "minecraft:mule", - "minecraft:ocelot", - "minecraft:panda", - "minecraft:parrot", - "minecraft:pig", - "minecraft:polar_bear", - "minecraft:pufferfish", - "minecraft:rabbit", - "minecraft:salmon", - "minecraft:sheep", - "minecraft:skeleton_horse", - "minecraft:sniffer", - "minecraft:snow_golem", - "minecraft:squid", - "minecraft:strider", - "minecraft:tadpole", - "minecraft:trader_llama", - "minecraft:tropical_fish", - "minecraft:turtle", - "minecraft:villager", - "minecraft:wandering_trader", - "minecraft:wolf", - "minecraft:zombie_horse" - ] -} + "values": [ + "minecraft:allay", + "minecraft:armadillo", + "minecraft:axolotl", + "minecraft:bat", + "minecraft:bee", + "minecraft:camel", + "minecraft:cat", + "minecraft:chicken", + "minecraft:cod", + "minecraft:cow", + "minecraft:dolphin", + "minecraft:donkey", + "minecraft:fox", + "minecraft:frog", + "minecraft:glow_squid", + "minecraft:goat", + "minecraft:horse", + "minecraft:iron_golem", + "minecraft:llama", + "minecraft:mooshroom", + "minecraft:mule", + "minecraft:ocelot", + "minecraft:panda", + "minecraft:parrot", + "minecraft:pig", + "minecraft:polar_bear", + "minecraft:pufferfish", + "minecraft:rabbit", + "minecraft:salmon", + "minecraft:sheep", + "minecraft:skeleton_horse", + "minecraft:sniffer", + "minecraft:snow_golem", + "minecraft:squid", + "minecraft:strider", + "minecraft:tadpole", + "minecraft:trader_llama", + "minecraft:tropical_fish", + "minecraft:turtle", + "minecraft:villager", + "minecraft:wandering_trader", + "minecraft:wolf", + "minecraft:zombie_horse" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/barricade/tags/item/barriers.json b/common/src/generated/resources/data/barricade/tags/item/barriers.json index 397e90a..eb351ec 100644 --- a/common/src/generated/resources/data/barricade/tags/item/barriers.json +++ b/common/src/generated/resources/data/barricade/tags/item/barriers.json @@ -1,19 +1,19 @@ { - "values": [ - "minecraft:barrier", - "barricade:advanced_barrier", - "barricade:down_barrier", - "barricade:up_barrier", - "barricade:north_barrier", - "barricade:south_barrier", - "barricade:east_barrier", - "barricade:west_barrier", - "barricade:horizontal_barrier", - "barricade:vertical_barrier", - "barricade:advanced_barrier", - "barricade:player_barrier", - "barricade:mob_barrier", - "barricade:passive_barrier", - "barricade:hostile_barrier" - ] -} + "values": [ + "minecraft:barrier", + "barricade:advanced_barrier", + "barricade:down_barrier", + "barricade:up_barrier", + "barricade:north_barrier", + "barricade:south_barrier", + "barricade:east_barrier", + "barricade:west_barrier", + "barricade:horizontal_barrier", + "barricade:vertical_barrier", + "barricade:advanced_barrier", + "barricade:player_barrier", + "barricade:mob_barrier", + "barricade:passive_barrier", + "barricade:hostile_barrier" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/minecraft/tags/block/blocks_wind_charge_explosions.json b/common/src/generated/resources/data/minecraft/tags/block/blocks_wind_charge_explosions.json index 0cc5f8a..d7f4aaa 100644 --- a/common/src/generated/resources/data/minecraft/tags/block/blocks_wind_charge_explosions.json +++ b/common/src/generated/resources/data/minecraft/tags/block/blocks_wind_charge_explosions.json @@ -1,6 +1,6 @@ { - "values": [ - "#barricade:directional_barriers", - "#barricade:predicate_barriers" - ] -} + "values": [ + "#barricade:directional_barriers", + "#barricade:predicate_barriers" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/minecraft/tags/block/dragon_immune.json b/common/src/generated/resources/data/minecraft/tags/block/dragon_immune.json index 0cc5f8a..d7f4aaa 100644 --- a/common/src/generated/resources/data/minecraft/tags/block/dragon_immune.json +++ b/common/src/generated/resources/data/minecraft/tags/block/dragon_immune.json @@ -1,6 +1,6 @@ { - "values": [ - "#barricade:directional_barriers", - "#barricade:predicate_barriers" - ] -} + "values": [ + "#barricade:directional_barriers", + "#barricade:predicate_barriers" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/minecraft/tags/block/snow_layer_cannot_survive_on.json b/common/src/generated/resources/data/minecraft/tags/block/snow_layer_cannot_survive_on.json index 0cc5f8a..d7f4aaa 100644 --- a/common/src/generated/resources/data/minecraft/tags/block/snow_layer_cannot_survive_on.json +++ b/common/src/generated/resources/data/minecraft/tags/block/snow_layer_cannot_survive_on.json @@ -1,6 +1,6 @@ { - "values": [ - "#barricade:directional_barriers", - "#barricade:predicate_barriers" - ] -} + "values": [ + "#barricade:directional_barriers", + "#barricade:predicate_barriers" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/minecraft/tags/block/wither_immune.json b/common/src/generated/resources/data/minecraft/tags/block/wither_immune.json index 0cc5f8a..d7f4aaa 100644 --- a/common/src/generated/resources/data/minecraft/tags/block/wither_immune.json +++ b/common/src/generated/resources/data/minecraft/tags/block/wither_immune.json @@ -1,6 +1,6 @@ { - "values": [ - "#barricade:directional_barriers", - "#barricade:predicate_barriers" - ] -} + "values": [ + "#barricade:directional_barriers", + "#barricade:predicate_barriers" + ] +} \ No newline at end of file diff --git a/common/src/main/java/net/modgarden/barricade/Barricade.java b/common/src/main/java/net/modgarden/barricade/Barricade.java index 0ef64d9..fe3e3f2 100644 --- a/common/src/main/java/net/modgarden/barricade/Barricade.java +++ b/common/src/main/java/net/modgarden/barricade/Barricade.java @@ -15,6 +15,7 @@ public class Barricade { public static final String MOD_ID = "barricade"; public static final String MOD_NAME = "Barricade"; public static final Logger LOG = LoggerFactory.getLogger(MOD_NAME); + public static final String MIXIN_NOT_APPLIED = "Mixin not applied"; private static BarricadePlatformHelper helper; public static boolean serverContext; @@ -36,4 +37,4 @@ public static BarricadePlatformHelper getHelper() { public static void setHelper(BarricadePlatformHelper helper) { Barricade.helper = helper; } -} \ No newline at end of file +} diff --git a/common/src/main/java/net/modgarden/barricade/block/PredicateBarrierBlock.java b/common/src/main/java/net/modgarden/barricade/block/PredicateBarrierBlock.java index 5b5bf5e..4cd6c58 100644 --- a/common/src/main/java/net/modgarden/barricade/block/PredicateBarrierBlock.java +++ b/common/src/main/java/net/modgarden/barricade/block/PredicateBarrierBlock.java @@ -1,92 +1,38 @@ package net.modgarden.barricade.block; import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Holder; -import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.BarrierBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.EntityCollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; -import net.modgarden.barricade.Barricade; -import net.modgarden.silicate.api.SilicateRegistries; import net.modgarden.silicate.api.condition.GameCondition; -import net.modgarden.silicate.api.context.GameContext; -import net.modgarden.silicate.api.context.param.ContextParamMap; -import net.modgarden.silicate.api.context.param.ContextParamSet; -import net.modgarden.silicate.api.context.param.ContextParamTypes; -import net.modgarden.silicate.api.exception.InvalidContextParameterException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Function; /** * A type of {@link BarrierBlock} that uses {@link GameCondition} to determine if an entity collides. */ -public class PredicateBarrierBlock extends BarrierBlock { - private static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( - propertiesCodec(), - ResourceLocation.CODEC - .fieldOf("icon") - .forGetter(PredicateBarrierBlock::icon), - GameCondition.CODEC - .fieldOf("conditions") - .forGetter(PredicateBarrierBlock::rawCondition) - ).apply(instance, PredicateBarrierBlock::new)); - public static final ContextParamSet PARAM_SET = ContextParamSet.Builder - .of() - .required(ContextParamTypes.THIS_ENTITY) - .required(ContextParamTypes.BLOCK_STATE) - .required(ContextParamTypes.ORIGIN) - .build(); - private final ResourceLocation icon; - private final Function>> function; - private Holder> condition; - +public class PredicateBarrierBlock extends BarrierBlock implements PredicateBlock { + @SuppressWarnings("unused") public PredicateBarrierBlock(Properties properties, ResourceLocation icon, ResourceKey> conditionTemplate) { super(properties); - this.icon = icon; - this.function = registryAccess -> registryAccess.registryOrThrow(SilicateRegistries.CONDITION_TEMPLATE).getHolderOrThrow(conditionTemplate); } private PredicateBarrierBlock(Properties properties, ResourceLocation icon, Holder> condition) { super(properties); - this.icon = icon; - this.function = null; - this.condition = condition; - } - - public ResourceLocation icon() { - return icon; - } - - public Holder> condition(RegistryAccess registries) { - if (condition == null && function != null) - condition = function.apply(registries); - return condition; - } - - private Holder> rawCondition() { - return condition; } @Override public @NotNull MapCodec codec() { - return CODEC.xmap( - properties -> properties, - block -> (PredicateBarrierBlock) block - ); + return PredicateBlock.mapCodec(PredicateBarrierBlock::new); } @Override @@ -94,39 +40,6 @@ protected boolean skipRendering(BlockState state, BlockState adjacentState, @Not return adjacentState.is(state.getBlock()); } - /** - * @return Whether to let the entity pass (true) or block the entity (false). - */ - public boolean test( - @Nullable Level level, - @NotNull Entity entity, - BlockState state, - BlockPos pos - ) throws InvalidContextParameterException { - return !test(newContext(level, entity, state, pos)); - } - - public boolean test(GameContext context) { - if (context.getLevel() == null) - return rawCondition() != null && rawCondition().value().test(context); - return this.condition(context.getLevel().registryAccess()).value().test(context); - } - - public static GameContext newContext( - @Nullable Level level, - @NotNull Entity entity, - BlockState state, - BlockPos pos - ) throws InvalidContextParameterException { - ContextParamMap paramMap = ContextParamMap.Builder - .of(PARAM_SET) - .withParameter(ContextParamTypes.THIS_ENTITY, entity) - .withParameter(ContextParamTypes.BLOCK_STATE, state) - .withParameter(ContextParamTypes.ORIGIN, pos.getCenter()) - .build(); - return GameContext.of(level, paramMap); - } - @Override protected @NotNull VoxelShape getCollisionShape( @NotNull BlockState state, @@ -134,21 +47,11 @@ public static GameContext newContext( @NotNull BlockPos pos, @NotNull CollisionContext context ) { - if (context instanceof EntityCollisionContext entityContext && entityContext.getEntity() != null) { - Level level = null; - if (blockGetter instanceof Level) { - level = (Level) blockGetter; - } - - try { - if (test(level, entityContext.getEntity(), state, pos)) { - return Shapes.empty(); - } - } catch (InvalidContextParameterException e) { - Barricade.LOG.error("Failed to test shape", e); - } + if (!this.isShaped(state, blockGetter, pos, context)) { + return Shapes.block(); + } else { + return Shapes.empty(); } - return Shapes.block(); } @Override @@ -158,21 +61,12 @@ public static GameContext newContext( @NotNull BlockPos pos, @NotNull CollisionContext context ) { - if (context instanceof EntityCollisionContext entityContext && entityContext.getEntity() != null) { - Level level = null; - if (blockGetter instanceof Level) { - level = (Level) blockGetter; - } - - try { - boolean isOperator = entityContext.getEntity() instanceof Player player && player.getAbilities().instabuild; - if (!isOperator && test(level, entityContext.getEntity(), state, pos)) { - return Shapes.empty(); - } - } catch (InvalidContextParameterException e) { - Barricade.LOG.error("Failed to test shape", e); - } + if (context instanceof EntityCollisionContext entityContext && + entityContext.getEntity() instanceof Player player && + player.getAbilities().instabuild) { + return super.getShape(state, blockGetter, pos, context); + } else { + return Shapes.empty(); } - return super.getShape(state, blockGetter, pos, context); } } diff --git a/common/src/main/java/net/modgarden/barricade/block/PredicateBlock.java b/common/src/main/java/net/modgarden/barricade/block/PredicateBlock.java new file mode 100644 index 0000000..c653c46 --- /dev/null +++ b/common/src/main/java/net/modgarden/barricade/block/PredicateBlock.java @@ -0,0 +1,152 @@ +package net.modgarden.barricade.block; + +import com.mojang.datafixers.util.Function3; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.EntityCollisionContext; +import net.modgarden.barricade.Barricade; +import net.modgarden.barricade.mixin.BlockBehaviourAccessor; +import net.modgarden.barricade.mixin.self.PredicateBlocksMixin; +import net.modgarden.silicate.api.condition.GameCondition; +import net.modgarden.silicate.api.context.GameContext; +import net.modgarden.silicate.api.context.param.ContextParamMap; +import net.modgarden.silicate.api.context.param.ContextParamSet; +import net.modgarden.silicate.api.context.param.ContextParamTypes; +import net.modgarden.silicate.api.exception.InvalidContextParameterException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static net.modgarden.barricade.Barricade.MIXIN_NOT_APPLIED; + +/** + *

How to make a PredicateBlock

+ *
    + *
  1. Create a class extending the target block and implementing {@link PredicateBlock}.
  2. + *
  3. Create dummy constructors as shown in {@link PredicateLeverBlock}.
  4. + *
  5. Override the {@code codec} method and return a call to {@link PredicateBlock#mapCodec(Constructor)}, passing a reference to the second constructor.
  6. + *
  7. Add the class to the mixin targets in {@link PredicateBlocksMixin}.
  8. + *
  9. Override the server-authoritative methods and the client-side behavior methods.
  10. + *
  11. Add your logic by calling methods in {@link PredicateBlock}.
  12. + *
+ */ +public interface PredicateBlock { + ContextParamSet PARAM_SET = ContextParamSet.Builder + .of() + .required(ContextParamTypes.THIS_ENTITY) + .required(ContextParamTypes.BLOCK_STATE) + .required(ContextParamTypes.ORIGIN) + .build(); + + static GameContext newContext( + @Nullable Level level, + @NotNull Entity entity, + BlockState state, + BlockPos pos + ) throws InvalidContextParameterException { + ContextParamMap paramMap = ContextParamMap.Builder + .of(PARAM_SET) + .withParameter(ContextParamTypes.THIS_ENTITY, entity) + .withParameter(ContextParamTypes.BLOCK_STATE, state) + .withParameter(ContextParamTypes.ORIGIN, pos.getCenter()) + .build(); + return GameContext.of(level, paramMap); + } + + static @NotNull MapCodec mapCodec(PredicateBlock.Constructor constructor) { + return RecordCodecBuilder.mapCodec(instance -> instance.group( + BlockBehaviourAccessor.invokePropertiesCodec(), + ResourceLocation.CODEC + .fieldOf("icon") + .forGetter(PredicateBlock::barricade$icon), + GameCondition.CODEC + .fieldOf("condition") + .forGetter(PredicateBlock::barricade$rawCondition) + ).apply(instance, constructor)) + .xmap( + t -> { + // This is a downcast, so it's always safe. + //noinspection unchecked + return (S) t; + }, + s -> { + // This upcast is always safe because the object being deserialized + // would be of type T if using this codec. + //noinspection unchecked + return (T) s; + } + ); + } + + default ResourceLocation barricade$icon() { + throw new IllegalStateException(MIXIN_NOT_APPLIED); + } + + default Holder> barricade$condition(RegistryAccess registries) { + throw new IllegalStateException(MIXIN_NOT_APPLIED); + } + + default @Nullable Holder> barricade$rawCondition() { + throw new IllegalStateException(MIXIN_NOT_APPLIED); + } + + /** + * @return Whether to let the entity interact (true) or block the entity's interaction (false). + */ + default boolean barricade$test( + @Nullable Level level, + @NotNull Entity entity, + BlockState state, + BlockPos pos + ) throws InvalidContextParameterException { + throw new IllegalStateException(MIXIN_NOT_APPLIED); + } + + default boolean barricade$test(GameContext context) { + throw new IllegalStateException(MIXIN_NOT_APPLIED); + } + + /** + * Checks if the entity in the collision context passes the condition. + * @return If the entity in the context passes the condition. + */ + default boolean isShaped( + @NotNull BlockState state, + @NotNull BlockGetter blockGetter, + @NotNull BlockPos pos, + @NotNull CollisionContext context + ) { + if (context instanceof EntityCollisionContext entityContext && entityContext.getEntity() != null) { + Level level = null; + if (blockGetter instanceof Level) { + level = (Level) blockGetter; + } + + try { + if (!barricade$test(level, entityContext.getEntity(), state, pos)) { + return false; + } + } catch (InvalidContextParameterException e) { + Barricade.LOG.error("Failed to test shape", e); + } + } + return true; + } + + // super mario in real life + @FunctionalInterface + interface Constructor extends Function3>, T> { + @Override + T apply(BlockBehaviour.Properties properties, ResourceLocation icon, Holder> condition); + } +} diff --git a/common/src/main/java/net/modgarden/barricade/block/PredicateButtonBlock.java b/common/src/main/java/net/modgarden/barricade/block/PredicateButtonBlock.java new file mode 100644 index 0000000..c89469c --- /dev/null +++ b/common/src/main/java/net/modgarden/barricade/block/PredicateButtonBlock.java @@ -0,0 +1,70 @@ +package net.modgarden.barricade.block; + +import com.mojang.serialization.MapCodec; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.ButtonBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockSetType; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.modgarden.silicate.api.condition.GameCondition; +import net.modgarden.silicate.api.exception.InvalidContextParameterException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static net.modgarden.barricade.Barricade.LOG; + +public class PredicateButtonBlock extends ButtonBlock implements PredicateBlock { + @SuppressWarnings("unused") + public PredicateButtonBlock(Properties properties, ResourceLocation icon, ResourceKey> conditionTemplate) { + super(BlockSetType.STONE, 20, properties); + } + + protected PredicateButtonBlock(Properties properties, ResourceLocation icon, Holder> condition) { + super(BlockSetType.STONE, 20, properties); + } + + @Override + public @NotNull MapCodec codec() { + return PredicateBlock.mapCodec(PredicateButtonBlock::new); + } + + @Override + protected @NotNull VoxelShape getShape( + @NotNull BlockState state, + @NotNull BlockGetter level, + @NotNull BlockPos pos, + @NotNull CollisionContext context + ) { + if (this.isShaped(state, level, pos, context)) { + return super.getShape(state, level, pos, context); + } else { + return Shapes.empty(); + } + } + + @Override + public void press( + @NotNull BlockState state, + @NotNull Level level, + @NotNull BlockPos pos, + @Nullable Player player + ) { + if (player == null) return; + + try { + if (this.barricade$test(level, player, state, pos)) { + super.press(state, level, pos, player); + } + } catch (InvalidContextParameterException e) { + LOG.error("Failed to test condition", e); + } + } +} diff --git a/common/src/main/java/net/modgarden/barricade/block/PredicateLeverBlock.java b/common/src/main/java/net/modgarden/barricade/block/PredicateLeverBlock.java new file mode 100644 index 0000000..fbf63b0 --- /dev/null +++ b/common/src/main/java/net/modgarden/barricade/block/PredicateLeverBlock.java @@ -0,0 +1,87 @@ +package net.modgarden.barricade.block; + +import com.mojang.serialization.MapCodec; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.*; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.modgarden.silicate.api.condition.GameCondition; +import net.modgarden.silicate.api.exception.InvalidContextParameterException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static net.modgarden.barricade.Barricade.LOG; + +public class PredicateLeverBlock extends LeverBlock implements PredicateBlock { + @SuppressWarnings("unused") + public PredicateLeverBlock(Properties properties, ResourceLocation icon, ResourceKey> conditionTemplate) { + super(properties); + } + + protected PredicateLeverBlock(Properties properties, ResourceLocation icon, Holder> condition) { + super(properties); + } + + @Override + public @NotNull MapCodec codec() { + return PredicateBlock.mapCodec(PredicateLeverBlock::new); + } + + @Override + protected @NotNull VoxelShape getShape( + @NotNull BlockState state, + @NotNull BlockGetter blockGetter, + @NotNull BlockPos pos, + @NotNull CollisionContext context + ) { + if (this.isShaped(state, blockGetter, pos, context)) { + return super.getShape(state, blockGetter, pos, context); + } else { + return Shapes.empty(); + } + } + + @Override + protected @NotNull InteractionResult useWithoutItem( + @NotNull BlockState state, + @NotNull Level level, + @NotNull BlockPos pos, + @NotNull Player player, + @NotNull BlockHitResult hitResult) { + if (level.isClientSide()) { + return super.useWithoutItem(state, level, pos, player, hitResult); + } else { + this.pull(state, level, pos, player); + return InteractionResult.CONSUME; + } + } + + @Override + public void pull( + @NotNull BlockState state, + @NotNull Level level, + @NotNull BlockPos pos, + @Nullable Player player + ) { + if (player == null) return; + + try { + if (level.isClientSide() || this.barricade$test(level, player, state, pos)) { + // Passing the player into pull will prevent them from hearing the sound event. + super.pull(state, level, pos, null); + } + } catch (InvalidContextParameterException e) { + LOG.error("Failed to test condition", e); + } + } +} diff --git a/common/src/main/java/net/modgarden/barricade/data/AdvancedBarrier.java b/common/src/main/java/net/modgarden/barricade/data/AdvancedBarrier.java index f47e28a..717d4fb 100644 --- a/common/src/main/java/net/modgarden/barricade/data/AdvancedBarrier.java +++ b/common/src/main/java/net/modgarden/barricade/data/AdvancedBarrier.java @@ -16,7 +16,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.modgarden.barricade.Barricade; -import net.modgarden.barricade.block.PredicateBarrierBlock; +import net.modgarden.barricade.block.PredicateBlock; import net.modgarden.barricade.registry.BarricadeRegistries; import net.modgarden.silicate.api.condition.GameCondition; import net.modgarden.silicate.api.exception.InvalidContextParameterException; @@ -69,7 +69,7 @@ public boolean test( BlockPos pos ) throws InvalidContextParameterException { return condition.isPresent() && condition.get().value().test( - PredicateBarrierBlock.newContext(level, entity, state, pos) + PredicateBlock.newContext(level, entity, state, pos) ); } diff --git a/common/src/main/java/net/modgarden/barricade/item/AdvancedBarrierBlockItem.java b/common/src/main/java/net/modgarden/barricade/item/AdvancedBarrierBlockItem.java index e657da1..31cb039 100644 --- a/common/src/main/java/net/modgarden/barricade/item/AdvancedBarrierBlockItem.java +++ b/common/src/main/java/net/modgarden/barricade/item/AdvancedBarrierBlockItem.java @@ -20,13 +20,15 @@ import java.util.HashSet; import java.util.Set; -public class AdvancedBarrierBlockItem extends EntityCheckBarrierBlockItem { +public class AdvancedBarrierBlockItem extends OperatorBlockItem { public AdvancedBarrierBlockItem(Block block, Properties properties) { super(block, properties); } @Override protected boolean canPlace(@NotNull BlockPlaceContext context, @NotNull BlockState state) { + if (!super.canPlace(context, state)) return false; + ItemStack stack = context.getItemInHand(); boolean collision; if (!stack.has(BarricadeComponents.ADVANCED_BARRIER)) { diff --git a/common/src/main/java/net/modgarden/barricade/item/DirectionalBarrierBlockItem.java b/common/src/main/java/net/modgarden/barricade/item/DirectionalBarrierBlockItem.java index 9a24cef..4400645 100644 --- a/common/src/main/java/net/modgarden/barricade/item/DirectionalBarrierBlockItem.java +++ b/common/src/main/java/net/modgarden/barricade/item/DirectionalBarrierBlockItem.java @@ -1,19 +1,18 @@ package net.modgarden.barricade.item; -import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; +import net.modgarden.barricade.block.DirectionalBarrierBlock; import org.jetbrains.annotations.NotNull; -public class DirectionalBarrierBlockItem extends BlockItem { - public DirectionalBarrierBlockItem(Block block, Properties properties) { +public class DirectionalBarrierBlockItem extends OperatorBlockItem { + public DirectionalBarrierBlockItem(DirectionalBarrierBlock block, Properties properties) { super(block, properties); } // Make sure that no matter the directional context, block placements are consistently declined if an entity is in the block. @Override protected boolean canPlace(@NotNull BlockPlaceContext context, @NotNull BlockState state) { - return (!mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())); + return super.canPlace(context, state) && (!mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())); } } diff --git a/common/src/main/java/net/modgarden/barricade/item/EntityCheckBarrierBlockItem.java b/common/src/main/java/net/modgarden/barricade/item/EntityCheckBarrierBlockItem.java index 7f1a1a2..ffd1908 100644 --- a/common/src/main/java/net/modgarden/barricade/item/EntityCheckBarrierBlockItem.java +++ b/common/src/main/java/net/modgarden/barricade/item/EntityCheckBarrierBlockItem.java @@ -1,6 +1,5 @@ package net.modgarden.barricade.item; -import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; @@ -8,14 +7,14 @@ import net.minecraft.world.phys.shapes.Shapes; import org.jetbrains.annotations.NotNull; -public class EntityCheckBarrierBlockItem extends BlockItem { - public EntityCheckBarrierBlockItem(Block block, Properties properties) { +public class EntityCheckBarrierBlockItem extends OperatorBlockItem { + public EntityCheckBarrierBlockItem(T block, Properties properties) { super(block, properties); } @Override protected boolean canPlace(@NotNull BlockPlaceContext context, @NotNull BlockState state) { - return (!mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().getEntities(null, Shapes.block().move(context.getClickedPos().getX(), context.getClickedPos().getY(), context.getClickedPos().getZ()).bounds()).stream().allMatch(entity -> + return super.canPlace(context, state) && (!mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().getEntities(null, Shapes.block().move(context.getClickedPos().getX(), context.getClickedPos().getY(), context.getClickedPos().getZ()).bounds()).stream().allMatch(entity -> state.getCollisionShape(context.getLevel(), context.getClickedPos(), CollisionContext.of(entity)).isEmpty()); } } diff --git a/common/src/main/java/net/modgarden/barricade/item/OperatorBlockItem.java b/common/src/main/java/net/modgarden/barricade/item/OperatorBlockItem.java new file mode 100644 index 0000000..4134913 --- /dev/null +++ b/common/src/main/java/net/modgarden/barricade/item/OperatorBlockItem.java @@ -0,0 +1,28 @@ +package net.modgarden.barricade.item; + +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; + +public class OperatorBlockItem extends BlockItem { + public OperatorBlockItem(T block, Properties properties) { + super(block, properties); + } + + @Override + protected boolean canPlace(@NotNull BlockPlaceContext context, @NotNull BlockState state) { + if (super.canPlace(context, state) && context.getPlayer() != null) { + return context.getPlayer().getAbilities().instabuild; + } else { + return false; + } + } + + @SuppressWarnings("unchecked") // It is illegal to have a this.block field not of type T + @Override + public @NotNull T getBlock() { + return (T) super.getBlock(); + } +} diff --git a/common/src/main/java/net/modgarden/barricade/mixin/BlockBehaviourAccessor.java b/common/src/main/java/net/modgarden/barricade/mixin/BlockBehaviourAccessor.java new file mode 100644 index 0000000..d2ec519 --- /dev/null +++ b/common/src/main/java/net/modgarden/barricade/mixin/BlockBehaviourAccessor.java @@ -0,0 +1,17 @@ +package net.modgarden.barricade.mixin; + +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import static net.modgarden.barricade.Barricade.MIXIN_NOT_APPLIED; + +@Mixin(BlockBehaviour.class) +public interface BlockBehaviourAccessor { + @Invoker + static RecordCodecBuilder invokePropertiesCodec() { + throw new IllegalStateException(MIXIN_NOT_APPLIED); + } +} diff --git a/common/src/main/java/net/modgarden/barricade/mixin/client/ClientLevelMixin.java b/common/src/main/java/net/modgarden/barricade/mixin/client/ClientLevelMixin.java index 32fd8f7..2d54e2e 100644 --- a/common/src/main/java/net/modgarden/barricade/mixin/client/ClientLevelMixin.java +++ b/common/src/main/java/net/modgarden/barricade/mixin/client/ClientLevelMixin.java @@ -95,7 +95,7 @@ public class ClientLevelMixin { BarrierRenderUtils.createAdvancedParticle(blockEntity.getData().directions(), blockEntity.getData().icon().orElse(null), particleOptions -> original.call(instance, particleOptions, x, y, z, xSpeed, ySpeed, zSpeed), blockPos.immutable()); return; } else if (blockState.getBlock() instanceof PredicateBarrierBlock predicateBarrierBlock) { - BarrierRenderUtils.createAdvancedParticle(new BlockedDirections(EnumSet.allOf(Direction.class)), predicateBarrierBlock.icon(), particleOptions -> original.call(instance, particleOptions, x, y, z, xSpeed, ySpeed, zSpeed), blockPos.immutable()); + BarrierRenderUtils.createAdvancedParticle(new BlockedDirections(EnumSet.allOf(Direction.class)), predicateBarrierBlock.barricade$icon(), particleOptions -> original.call(instance, particleOptions, x, y, z, xSpeed, ySpeed, zSpeed), blockPos.immutable()); return; } original.call(instance, particleData, x, y, z, xSpeed, ySpeed, zSpeed); diff --git a/common/src/main/java/net/modgarden/barricade/mixin/self/BarricadeMixin.java b/common/src/main/java/net/modgarden/barricade/mixin/self/BarricadeMixin.java new file mode 100644 index 0000000..1905205 --- /dev/null +++ b/common/src/main/java/net/modgarden/barricade/mixin/self/BarricadeMixin.java @@ -0,0 +1,22 @@ +package net.modgarden.barricade.mixin.self; + +import net.modgarden.barricade.Barricade; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Shadow; + +/** + * Hacks for hotswapping. + */ +@Mixin(Barricade.class) +public class BarricadeMixin { + /** + * Fixes an {@link IllegalAccessError} when hotswapping. + */ + @Mutable + @Final + @Shadow + public static Logger LOG; +} diff --git a/common/src/main/java/net/modgarden/barricade/mixin/self/PredicateBlocksMixin.java b/common/src/main/java/net/modgarden/barricade/mixin/self/PredicateBlocksMixin.java new file mode 100644 index 0000000..1257a06 --- /dev/null +++ b/common/src/main/java/net/modgarden/barricade/mixin/self/PredicateBlocksMixin.java @@ -0,0 +1,99 @@ +package net.modgarden.barricade.mixin.self; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockState; +import net.modgarden.barricade.block.PredicateBarrierBlock; +import net.modgarden.barricade.block.PredicateBlock; +import net.modgarden.barricade.block.PredicateButtonBlock; +import net.modgarden.barricade.block.PredicateLeverBlock; +import net.modgarden.silicate.api.SilicateRegistries; +import net.modgarden.silicate.api.condition.GameCondition; +import net.modgarden.silicate.api.context.GameContext; +import net.modgarden.silicate.api.exception.InvalidContextParameterException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.function.Function; + +@Mixin({PredicateBarrierBlock.class, PredicateLeverBlock.class, PredicateButtonBlock.class}) +public class PredicateBlocksMixin implements PredicateBlock { + @Unique + private ResourceLocation barricade$icon; + @Unique + private Function>> barricade$registryToCondition; + @Unique + private Holder> barricade$condition; + + @Inject( + method = "(Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/resources/ResourceKey;)V", + at = @At("CTOR_HEAD") + ) + private void init(BlockBehaviour.Properties properties, ResourceLocation icon, ResourceKey> conditionTemplate, CallbackInfo ci) { + this.barricade$icon = icon; + this.barricade$registryToCondition = registryAccess -> { + Holder> condition = registryAccess.registryOrThrow(SilicateRegistries.CONDITION_TEMPLATE).getHolderOrThrow(conditionTemplate); + barricade$condition = condition; + return condition; + }; + } + + @Inject( + method = "(Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/core/Holder;)V", + at = @At("CTOR_HEAD") + ) + private void init(BlockBehaviour.Properties properties, ResourceLocation icon, Holder> condition, CallbackInfo ci) { + this.barricade$icon = icon; + this.barricade$registryToCondition = registryAccess -> condition; + this.barricade$condition = condition; + } + + @Override + public ResourceLocation barricade$icon() { + return barricade$icon; + } + + @Override + public Holder> barricade$condition(RegistryAccess registries) { + return barricade$registryToCondition.apply(registries); + } + + @Override + public @Nullable Holder> barricade$rawCondition() { + return barricade$condition; + } + + @Override + public boolean barricade$test( + @Nullable Level level, + @NotNull Entity entity, + BlockState state, + BlockPos pos + ) throws InvalidContextParameterException { + // Inverted for compatibility with the old Predicate Barrier Block system + return !barricade$test(PredicateBlock.newContext(level, entity, state, pos)); + } + + @Override + public final boolean barricade$test(GameContext context) { + if (context.getLevel() == null) { + // IntelliJ doesn't see the null check. + //noinspection DataFlowIssue + return this.barricade$rawCondition() != null && this.barricade$rawCondition().value().test(context); + } + + Holder> condition = this.barricade$condition(context.getLevel().registryAccess()); + return condition.value().test(context); + } +} diff --git a/common/src/main/java/net/modgarden/barricade/registry/BarricadeBlocks.java b/common/src/main/java/net/modgarden/barricade/registry/BarricadeBlocks.java index 22e6e45..9d6eea3 100644 --- a/common/src/main/java/net/modgarden/barricade/registry/BarricadeBlocks.java +++ b/common/src/main/java/net/modgarden/barricade/registry/BarricadeBlocks.java @@ -4,77 +4,115 @@ import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockBehaviour; import net.modgarden.barricade.Barricade; -import net.modgarden.barricade.block.AdvancedBarrierBlock; -import net.modgarden.barricade.block.DirectionalBarrierBlock; -import net.modgarden.barricade.block.PredicateBarrierBlock; +import net.modgarden.barricade.block.*; import net.modgarden.barricade.data.BlockedDirections; import net.modgarden.silicate.api.SilicateRegistries; +import net.modgarden.silicate.api.condition.GameCondition; +import org.jetbrains.annotations.NotNull; public class BarricadeBlocks { - public static final AdvancedBarrierBlock ADVANCED_BARRIER = new AdvancedBarrierBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER).dynamicShape()); + public static final AdvancedBarrierBlock ADVANCED_BARRIER = new AdvancedBarrierBlock(barrierProps()); - public static final DirectionalBarrierBlock DOWN_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.DOWN), BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER).dynamicShape()); - public static final DirectionalBarrierBlock UP_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.UP), BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER).dynamicShape()); - public static final DirectionalBarrierBlock SOUTH_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.SOUTH), BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER).dynamicShape()); - public static final DirectionalBarrierBlock NORTH_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.NORTH), BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER).dynamicShape()); - public static final DirectionalBarrierBlock EAST_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.EAST), BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER).dynamicShape()); - public static final DirectionalBarrierBlock WEST_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.WEST), BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER).dynamicShape()); - public static final DirectionalBarrierBlock HORIZONTAL_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH), BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER).dynamicShape()); - public static final DirectionalBarrierBlock VERTICAL_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.UP, Direction.DOWN), BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER).dynamicShape()); + public static final DirectionalBarrierBlock DOWN_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.DOWN), barrierProps()); + public static final DirectionalBarrierBlock UP_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.UP), barrierProps()); + public static final DirectionalBarrierBlock SOUTH_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.SOUTH), barrierProps()); + public static final DirectionalBarrierBlock NORTH_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.NORTH), barrierProps()); + public static final DirectionalBarrierBlock EAST_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.EAST), barrierProps()); + public static final DirectionalBarrierBlock WEST_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.WEST), barrierProps()); + public static final DirectionalBarrierBlock HORIZONTAL_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH), barrierProps()); + public static final DirectionalBarrierBlock VERTICAL_BARRIER = new DirectionalBarrierBlock(BlockedDirections.of(Direction.UP, Direction.DOWN), barrierProps()); // Predicate Barriers public static final PredicateBarrierBlock CREATIVE_ONLY_BARRIER = new PredicateBarrierBlock( - BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER) - .dynamicShape(), + barrierProps(), Barricade.asResource("barricade/icon/iron_sword"), - ResourceKey.create(SilicateRegistries.CONDITION_TEMPLATE, Barricade.asResource("creative_only")) + conditionTemplate("creative_only") ); public static final PredicateBarrierBlock PLAYER_BARRIER = new PredicateBarrierBlock( - BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER) - .dynamicShape(), + barrierProps(), Barricade.asResource("barricade/icon/steve"), - ResourceKey.create(SilicateRegistries.CONDITION_TEMPLATE, Barricade.asResource("player")) + conditionTemplate("player") ); public static final PredicateBarrierBlock MOB_BARRIER = new PredicateBarrierBlock( - BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER) - .dynamicShape(), + barrierProps(), Barricade.asResource("barricade/icon/pig"), - ResourceKey.create(SilicateRegistries.CONDITION_TEMPLATE, Barricade.asResource("mob")) + conditionTemplate("mob") ); public static final PredicateBarrierBlock PASSIVE_BARRIER = new PredicateBarrierBlock( - BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER) - .dynamicShape(), + barrierProps(), Barricade.asResource("barricade/icon/parrot"), - ResourceKey.create(SilicateRegistries.CONDITION_TEMPLATE, Barricade.asResource("passive")) + conditionTemplate("passive") ); public static final PredicateBarrierBlock HOSTILE_BARRIER = new PredicateBarrierBlock( - BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER) - .dynamicShape(), + barrierProps(), Barricade.asResource("barricade/icon/creeper"), - ResourceKey.create(SilicateRegistries.CONDITION_TEMPLATE, Barricade.asResource("hostile")) + conditionTemplate("hostile") + ); + + // Predicate Levers + public static final PredicateLeverBlock CREATIVE_ONLY_LEVER = new PredicateLeverBlock( + leverProps(), + Barricade.asResource("barricade/icon/iron_sword"), + conditionTemplate("creative_only") + ); + + // Predicate Buttons + public static final PredicateButtonBlock CREATIVE_ONLY_BUTTON = new PredicateButtonBlock( + buttonProps(), + Barricade.asResource("barricade/icon/iron_sword"), + conditionTemplate("creative_only") ); public static void registerAll() { - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("advanced_barrier"), ADVANCED_BARRIER); - - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("down_barrier"), DOWN_BARRIER); - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("up_barrier"), UP_BARRIER); - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("south_barrier"), SOUTH_BARRIER); - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("north_barrier"), NORTH_BARRIER); - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("east_barrier"), EAST_BARRIER); - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("west_barrier"), WEST_BARRIER); - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("horizontal_barrier"), HORIZONTAL_BARRIER); - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("vertical_barrier"), VERTICAL_BARRIER); - - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("player_barrier"), PLAYER_BARRIER); - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("mob_barrier"), MOB_BARRIER); - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("passive_barrier"), PASSIVE_BARRIER); - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("hostile_barrier"), HOSTILE_BARRIER); - - Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource("creative_only_barrier"), CREATIVE_ONLY_BARRIER); + register("advanced_barrier", ADVANCED_BARRIER); + + register("down_barrier", DOWN_BARRIER); + register("up_barrier", UP_BARRIER); + register("south_barrier", SOUTH_BARRIER); + register("north_barrier", NORTH_BARRIER); + register("east_barrier", EAST_BARRIER); + register("west_barrier", WEST_BARRIER); + register("horizontal_barrier", HORIZONTAL_BARRIER); + register("vertical_barrier", VERTICAL_BARRIER); + + register("player_barrier", PLAYER_BARRIER); + register("mob_barrier", MOB_BARRIER); + register("passive_barrier", PASSIVE_BARRIER); + register("hostile_barrier", HOSTILE_BARRIER); + + register("creative_only_barrier", CREATIVE_ONLY_BARRIER); + + register("creative_only_lever", CREATIVE_ONLY_LEVER); + + register("creative_only_button", CREATIVE_ONLY_BUTTON); + } + + private static void register(String name, Block block) { + Registry.register(BuiltInRegistries.BLOCK, Barricade.asResource(name), block); + } + + private static ResourceKey> conditionTemplate(String name) { + return ResourceKey.create( + SilicateRegistries.CONDITION_TEMPLATE, + Barricade.asResource(name) + ); + } + + private static BlockBehaviour.@NotNull Properties barrierProps() { + return BlockBehaviour.Properties.ofFullCopy(Blocks.BARRIER) + .dynamicShape(); + } + + private static BlockBehaviour.@NotNull Properties leverProps() { + return BlockBehaviour.Properties.ofFullCopy(Blocks.LEVER); + } + + private static BlockBehaviour.@NotNull Properties buttonProps() { + return BlockBehaviour.Properties.ofFullCopy(Blocks.STONE_BUTTON); } } diff --git a/common/src/main/java/net/modgarden/barricade/registry/BarricadeItems.java b/common/src/main/java/net/modgarden/barricade/registry/BarricadeItems.java index 11a4b81..1bf9f73 100644 --- a/common/src/main/java/net/modgarden/barricade/registry/BarricadeItems.java +++ b/common/src/main/java/net/modgarden/barricade/registry/BarricadeItems.java @@ -5,56 +5,82 @@ import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.Rarity; +import net.minecraft.world.level.block.Block; import net.modgarden.barricade.Barricade; +import net.modgarden.barricade.block.DirectionalBarrierBlock; +import net.modgarden.barricade.block.PredicateBarrierBlock; +import net.modgarden.barricade.block.PredicateButtonBlock; +import net.modgarden.barricade.block.PredicateLeverBlock; import net.modgarden.barricade.item.AdvancedBarrierBlockItem; import net.modgarden.barricade.item.DirectionalBarrierBlockItem; import net.modgarden.barricade.item.EntityCheckBarrierBlockItem; +import net.modgarden.barricade.item.OperatorBlockItem; import org.jetbrains.annotations.NotNull; public class BarricadeItems { - public static final BlockItem ADVANCED_BARRIER = new AdvancedBarrierBlockItem(BarricadeBlocks.ADVANCED_BARRIER, barrierProps()); - - public static final BlockItem HORIZONTAL_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.HORIZONTAL_BARRIER, barrierProps()); - public static final BlockItem VERTICAL_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.VERTICAL_BARRIER, barrierProps()); - public static final BlockItem DOWN_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.DOWN_BARRIER, barrierProps()); - public static final BlockItem UP_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.UP_BARRIER, barrierProps()); - public static final BlockItem SOUTH_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.SOUTH_BARRIER, barrierProps()); - public static final BlockItem NORTH_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.NORTH_BARRIER, barrierProps()); - public static final BlockItem EAST_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.EAST_BARRIER, barrierProps()); - public static final BlockItem WEST_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.WEST_BARRIER, barrierProps()); - - public static final BlockItem PLAYER_BARRIER = new EntityCheckBarrierBlockItem(BarricadeBlocks.PLAYER_BARRIER, barrierProps()); - public static final BlockItem MOB_BARRIER = new EntityCheckBarrierBlockItem(BarricadeBlocks.MOB_BARRIER, barrierProps()); - public static final BlockItem PASSIVE_BARRIER = new EntityCheckBarrierBlockItem(BarricadeBlocks.PASSIVE_BARRIER, barrierProps()); - public static final BlockItem HOSTILE_BARRIER = new EntityCheckBarrierBlockItem(BarricadeBlocks.HOSTILE_BARRIER, barrierProps()); + public static final OperatorBlockItem ADVANCED_BARRIER = new AdvancedBarrierBlockItem(BarricadeBlocks.ADVANCED_BARRIER, barrierProps()); + + public static final OperatorBlockItem HORIZONTAL_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.HORIZONTAL_BARRIER, barrierProps()); + public static final OperatorBlockItem VERTICAL_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.VERTICAL_BARRIER, barrierProps()); + public static final OperatorBlockItem DOWN_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.DOWN_BARRIER, barrierProps()); + public static final OperatorBlockItem UP_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.UP_BARRIER, barrierProps()); + public static final OperatorBlockItem SOUTH_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.SOUTH_BARRIER, barrierProps()); + public static final OperatorBlockItem NORTH_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.NORTH_BARRIER, barrierProps()); + public static final OperatorBlockItem EAST_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.EAST_BARRIER, barrierProps()); + public static final OperatorBlockItem WEST_BARRIER = new DirectionalBarrierBlockItem(BarricadeBlocks.WEST_BARRIER, barrierProps()); // Predicate Barriers - public static final BlockItem CREATIVE_ONLY_BARRIER = new BlockItem( + public static final OperatorBlockItem PLAYER_BARRIER = new EntityCheckBarrierBlockItem<>(BarricadeBlocks.PLAYER_BARRIER, barrierProps()); + public static final OperatorBlockItem MOB_BARRIER = new EntityCheckBarrierBlockItem<>(BarricadeBlocks.MOB_BARRIER, barrierProps()); + public static final OperatorBlockItem PASSIVE_BARRIER = new EntityCheckBarrierBlockItem<>(BarricadeBlocks.PASSIVE_BARRIER, barrierProps()); + public static final OperatorBlockItem HOSTILE_BARRIER = new EntityCheckBarrierBlockItem<>(BarricadeBlocks.HOSTILE_BARRIER, barrierProps()); + + public static final OperatorBlockItem CREATIVE_ONLY_BARRIER = new OperatorBlockItem<>( BarricadeBlocks.CREATIVE_ONLY_BARRIER, barrierProps() ); + // Predicate Levers + public static final OperatorBlockItem CREATIVE_ONLY_LEVER = new OperatorBlockItem<>( + BarricadeBlocks.CREATIVE_ONLY_LEVER, + barrierProps() + ); + + // Predicate Buttons + public static final OperatorBlockItem CREATIVE_ONLY_BUTTON = new OperatorBlockItem<>( + BarricadeBlocks.CREATIVE_ONLY_BUTTON, + barrierProps() + ); + public static void registerAll() { - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("advanced_barrier"), ADVANCED_BARRIER); - - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("down_barrier"), DOWN_BARRIER); - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("up_barrier"), UP_BARRIER); - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("south_barrier"), SOUTH_BARRIER); - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("north_barrier"), NORTH_BARRIER); - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("east_barrier"), EAST_BARRIER); - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("west_barrier"), WEST_BARRIER); - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("horizontal_barrier"), HORIZONTAL_BARRIER); - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("vertical_barrier"), VERTICAL_BARRIER); - - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("player_barrier"), PLAYER_BARRIER); - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("mob_barrier"), MOB_BARRIER); - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("passive_barrier"), PASSIVE_BARRIER); - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("hostile_barrier"), HOSTILE_BARRIER); - - Registry.register(BuiltInRegistries.ITEM, Barricade.asResource("creative_only_barrier"), CREATIVE_ONLY_BARRIER); + register("advanced_barrier", ADVANCED_BARRIER); + + register("down_barrier", DOWN_BARRIER); + register("up_barrier", UP_BARRIER); + register("south_barrier", SOUTH_BARRIER); + register("north_barrier", NORTH_BARRIER); + register("east_barrier", EAST_BARRIER); + register("west_barrier", WEST_BARRIER); + register("horizontal_barrier", HORIZONTAL_BARRIER); + register("vertical_barrier", VERTICAL_BARRIER); + + register("player_barrier", PLAYER_BARRIER); + register("mob_barrier", MOB_BARRIER); + register("passive_barrier", PASSIVE_BARRIER); + register("hostile_barrier", HOSTILE_BARRIER); + + register("creative_only_barrier", CREATIVE_ONLY_BARRIER); + + register("creative_only_lever", CREATIVE_ONLY_LEVER); + + register("creative_only_button", CREATIVE_ONLY_BUTTON); + } + + private static void register(String name, BlockItem blockItem) { + Registry.register(BuiltInRegistries.ITEM, Barricade.asResource(name), blockItem); } private static Item.@NotNull Properties barrierProps() { return new Item.Properties().rarity(Rarity.EPIC); } -} \ No newline at end of file +} diff --git a/common/src/main/resources/assets/barricade/lang/en_us.json b/common/src/main/resources/assets/barricade/lang/en_us.json index 1607870..2ef1649 100644 --- a/common/src/main/resources/assets/barricade/lang/en_us.json +++ b/common/src/main/resources/assets/barricade/lang/en_us.json @@ -13,6 +13,8 @@ "block.barricade.passive_barrier": "Passive Barrier", "block.barricade.hostile_barrier": "Hostile Barrier", "block.barricade.creative_only_barrier": "Creative-Only Barrier", + "block.barricade.creative_only_lever": "Creative-Only Lever", + "block.barricade.creative_only_button": "Creative-Only Button", "tag.item.barricade.barriers": "Barriers", "resourcePack.barricade.modded_rendering.name": "Barricade Rendering", "resourcePack.barricade.modded_rendering.description": "Enables Barricade's alternative block rendering.", @@ -27,4 +29,4 @@ "command.barricade.visibility.disable.blocks.error.already_disabled": "Operator blocks %s are already invisible", "command.barricade.visibility.disable.all.success": "Made all operator blocks invisible", "command.barricade.visibility.disable.blocks.success": "Made all instances of %s invisible" -} \ No newline at end of file +} diff --git a/common/src/main/resources/barricade.mixins.json b/common/src/main/resources/barricade.mixins.json index ff5c32f..0e0b07f 100644 --- a/common/src/main/resources/barricade.mixins.json +++ b/common/src/main/resources/barricade.mixins.json @@ -6,9 +6,12 @@ "compatibilityLevel": "JAVA_21", "mixins": [ "AbstractArrowMixin", + "BlockBehaviourAccessor", "BlockBehaviourBlockStateBaseMixin", "BlockBehaviourMixin", - "BlockMixin" + "BlockMixin", + "self.BarricadeMixin", + "self.PredicateBlocksMixin" ], "client": [ "client.ClientChunkCacheAccessor", diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts index 429e93d..69ad3d9 100644 --- a/fabric/build.gradle.kts +++ b/fabric/build.gradle.kts @@ -59,6 +59,12 @@ loom { } } runs { + afterEvaluate { + configureEach { + // Class redefinition (for JBR/DCEVM) + vmArg("-XX:+AllowEnhancedClassRedefinition") + } + } named("client") { client() configName = "Fabric Client" diff --git a/fabric/src/datagen/java/net/modgarden/barricade/datagen/BarricadeDataGen.java b/fabric/src/datagen/java/net/modgarden/barricade/datagen/BarricadeDataGen.java index e8151a8..92c77c2 100644 --- a/fabric/src/datagen/java/net/modgarden/barricade/datagen/BarricadeDataGen.java +++ b/fabric/src/datagen/java/net/modgarden/barricade/datagen/BarricadeDataGen.java @@ -3,13 +3,32 @@ import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint; import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; +import net.fabricmc.fabric.api.datagen.v1.provider.FabricModelProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider; +import net.minecraft.core.Direction; import net.minecraft.core.HolderLookup; +import net.minecraft.data.models.BlockModelGenerators; +import net.minecraft.data.models.ItemModelGenerators; +import net.minecraft.data.models.blockstates.MultiVariantGenerator; +import net.minecraft.data.models.blockstates.PropertyDispatch; +import net.minecraft.data.models.blockstates.Variant; +import net.minecraft.data.models.blockstates.VariantProperties; +import net.minecraft.data.models.model.ModelLocationUtils; +import net.minecraft.data.models.model.ModelTemplates; +import net.minecraft.data.models.model.TextureMapping; +import net.minecraft.data.models.model.TexturedModel; +import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; import net.minecraft.tags.EntityTypeTags; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.properties.AttachFace; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.modgarden.barricade.datagen.mixin.BlockFamilyProviderAccessor; +import net.modgarden.barricade.datagen.mixin.BlockModelGeneratorsAccessor; import net.modgarden.barricade.registry.BarricadeBlocks; import net.modgarden.barricade.registry.BarricadeTags; import org.jetbrains.annotations.Nullable; @@ -23,6 +42,86 @@ public void onInitializeDataGenerator(FabricDataGenerator generator) { BlockTagProvider blockTagProvider = pack.addProvider(BlockTagProvider::new); pack.addProvider(EntityTypeTagProvider::new); pack.addProvider((output, registries) -> new ItemTagProvider(output, registries, blockTagProvider)); + pack.addProvider(ModelProvider::new); + } + + private static class ModelProvider extends FabricModelProvider { + public ModelProvider(FabricDataOutput output) { + super(output); + } + + @Override + public void generateBlockStateModels(BlockModelGenerators generators) { + createLever(generators, BarricadeBlocks.CREATIVE_ONLY_LEVER); + family(generators, Blocks.STONE) + .button(BarricadeBlocks.CREATIVE_ONLY_BUTTON); + } + + @Override + public void generateItemModels(ItemModelGenerators generators) { + } + + private static void createLever(BlockModelGenerators generators, Block block) { + ResourceLocation resourceLocation = ModelLocationUtils.getModelLocation(Blocks.LEVER); + ResourceLocation resourceLocation2 = ModelLocationUtils.getModelLocation(Blocks.LEVER, "_on"); + createSimpleFlatItemModel(generators, block, Blocks.LEVER); + generators.blockStateOutput + .accept( + MultiVariantGenerator.multiVariant(block) + .with(BlockModelGenerators.createBooleanModelDispatch(BlockStateProperties.POWERED, resourceLocation, resourceLocation2)) + .with( + PropertyDispatch.properties(BlockStateProperties.ATTACH_FACE, BlockStateProperties.HORIZONTAL_FACING) + .select( + AttachFace.CEILING, + Direction.NORTH, + Variant.variant().with(VariantProperties.X_ROT, VariantProperties.Rotation.R180).with(VariantProperties.Y_ROT, VariantProperties.Rotation.R180) + ) + .select( + AttachFace.CEILING, + Direction.EAST, + Variant.variant().with(VariantProperties.X_ROT, VariantProperties.Rotation.R180).with(VariantProperties.Y_ROT, VariantProperties.Rotation.R270) + ) + .select(AttachFace.CEILING, Direction.SOUTH, Variant.variant().with(VariantProperties.X_ROT, VariantProperties.Rotation.R180)) + .select( + AttachFace.CEILING, + Direction.WEST, + Variant.variant().with(VariantProperties.X_ROT, VariantProperties.Rotation.R180).with(VariantProperties.Y_ROT, VariantProperties.Rotation.R90) + ) + .select(AttachFace.FLOOR, Direction.NORTH, Variant.variant()) + .select(AttachFace.FLOOR, Direction.EAST, Variant.variant().with(VariantProperties.Y_ROT, VariantProperties.Rotation.R90)) + .select(AttachFace.FLOOR, Direction.SOUTH, Variant.variant().with(VariantProperties.Y_ROT, VariantProperties.Rotation.R180)) + .select(AttachFace.FLOOR, Direction.WEST, Variant.variant().with(VariantProperties.Y_ROT, VariantProperties.Rotation.R270)) + .select(AttachFace.WALL, Direction.NORTH, Variant.variant().with(VariantProperties.X_ROT, VariantProperties.Rotation.R90)) + .select( + AttachFace.WALL, + Direction.EAST, + Variant.variant().with(VariantProperties.X_ROT, VariantProperties.Rotation.R90).with(VariantProperties.Y_ROT, VariantProperties.Rotation.R90) + ) + .select( + AttachFace.WALL, + Direction.SOUTH, + Variant.variant().with(VariantProperties.X_ROT, VariantProperties.Rotation.R90).with(VariantProperties.Y_ROT, VariantProperties.Rotation.R180) + ) + .select( + AttachFace.WALL, + Direction.WEST, + Variant.variant().with(VariantProperties.X_ROT, VariantProperties.Rotation.R90).with(VariantProperties.Y_ROT, VariantProperties.Rotation.R270) + ) + ) + ); + } + + private static BlockModelGenerators.BlockFamilyProvider family(BlockModelGenerators generators, Block block) { + TexturedModel texturedModel = ((BlockModelGeneratorsAccessor) generators).getTexturedModels().getOrDefault(block, TexturedModel.CUBE.get(block)); + return BlockFamilyProviderAccessor.init(generators, texturedModel.getMapping()); + } + + private static void createSimpleFlatItemModel(BlockModelGenerators generators, Block flatBlock, Block textureBlock) { + Item item = flatBlock.asItem(); + if (item != Items.AIR) { + ModelTemplates.FLAT_ITEM.create(ModelLocationUtils.getModelLocation(item), TextureMapping.layer0(textureBlock), generators.modelOutput); + } + } } private static class BlockTagProvider extends FabricTagProvider.BlockTagProvider { diff --git a/fabric/src/datagen/java/net/modgarden/barricade/datagen/mixin/BlockFamilyProviderAccessor.java b/fabric/src/datagen/java/net/modgarden/barricade/datagen/mixin/BlockFamilyProviderAccessor.java new file mode 100644 index 0000000..0d73487 --- /dev/null +++ b/fabric/src/datagen/java/net/modgarden/barricade/datagen/mixin/BlockFamilyProviderAccessor.java @@ -0,0 +1,16 @@ +package net.modgarden.barricade.datagen.mixin; + +import net.minecraft.data.models.BlockModelGenerators; +import net.minecraft.data.models.model.TextureMapping; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import static net.modgarden.barricade.Barricade.MIXIN_NOT_APPLIED; + +@Mixin(BlockModelGenerators.BlockFamilyProvider.class) +public interface BlockFamilyProviderAccessor { + @Invoker("") + static BlockModelGenerators.BlockFamilyProvider init(final BlockModelGenerators this$0, final TextureMapping mapping) { + throw new IllegalStateException(MIXIN_NOT_APPLIED); + } +} diff --git a/fabric/src/datagen/java/net/modgarden/barricade/datagen/mixin/BlockModelGeneratorsAccessor.java b/fabric/src/datagen/java/net/modgarden/barricade/datagen/mixin/BlockModelGeneratorsAccessor.java new file mode 100644 index 0000000..7d031ba --- /dev/null +++ b/fabric/src/datagen/java/net/modgarden/barricade/datagen/mixin/BlockModelGeneratorsAccessor.java @@ -0,0 +1,15 @@ +package net.modgarden.barricade.datagen.mixin; + +import net.minecraft.data.models.BlockModelGenerators; +import net.minecraft.data.models.model.TexturedModel; +import net.minecraft.world.level.block.Block; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Map; + +@Mixin(BlockModelGenerators.class) +public interface BlockModelGeneratorsAccessor { + @Accessor + Map getTexturedModels(); +} diff --git a/fabric/src/datagen/resources/barricade.datagen.mixins.json b/fabric/src/datagen/resources/barricade.datagen.mixins.json new file mode 100644 index 0000000..cd503d4 --- /dev/null +++ b/fabric/src/datagen/resources/barricade.datagen.mixins.json @@ -0,0 +1,17 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "net.modgarden.barricade.datagen.mixin", + "refmap": "${mod_id}.refmap.json", + "compatibilityLevel": "JAVA_21", + "mixins": [ + "BlockFamilyProviderAccessor", + "BlockModelGeneratorsAccessor" + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +} + diff --git a/fabric/src/datagen/resources/fabric.mod.json b/fabric/src/datagen/resources/fabric.mod.json index 2bdf5d6..d6641a9 100644 --- a/fabric/src/datagen/resources/fabric.mod.json +++ b/fabric/src/datagen/resources/fabric.mod.json @@ -23,6 +23,9 @@ "net.modgarden.barricade.datagen.BarricadeDataGen" ] }, + "mixins": [ + "${mod_id}.datagen.mixins.json" + ], "depends": { "fabricloader": "${fabric_loader_range}", "fabric-api": "*", diff --git a/fabric/src/main/java/net/modgarden/barricade/fabric/BarricadeFabric.java b/fabric/src/main/java/net/modgarden/barricade/fabric/BarricadeFabric.java index fe810ef..a7499c1 100644 --- a/fabric/src/main/java/net/modgarden/barricade/fabric/BarricadeFabric.java +++ b/fabric/src/main/java/net/modgarden/barricade/fabric/BarricadeFabric.java @@ -59,7 +59,9 @@ public void onInitialize() { BarricadeItems.MOB_BARRIER, BarricadeItems.PASSIVE_BARRIER, BarricadeItems.HOSTILE_BARRIER, - BarricadeItems.CREATIVE_ONLY_BARRIER); + BarricadeItems.CREATIVE_ONLY_BARRIER, + BarricadeItems.CREATIVE_ONLY_LEVER, + BarricadeItems.CREATIVE_ONLY_BUTTON); }); } } diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index e470ee1..c1f0c2b 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -55,6 +55,9 @@ neoForge { systemProperty("forge.logging.markers", "REGISTRIES") systemProperty("forge.logging.console.level", "debug") systemProperty("neoforge.enabledGameTestNamespaces", Properties.MOD_ID) + + // Class redefinition (for JBR/DCEVM) + jvmArgument("-XX:+AllowEnhancedClassRedefinition") } create("client") { client() diff --git a/neoforge/src/main/java/net/modgarden/barricade/neoforge/BarricadeNeoForge.java b/neoforge/src/main/java/net/modgarden/barricade/neoforge/BarricadeNeoForge.java index bed670e..a024df6 100644 --- a/neoforge/src/main/java/net/modgarden/barricade/neoforge/BarricadeNeoForge.java +++ b/neoforge/src/main/java/net/modgarden/barricade/neoforge/BarricadeNeoForge.java @@ -91,7 +91,9 @@ public static void buildCreativeModeTabs(BuildCreativeModeTabContentsEvent event BarricadeItems.MOB_BARRIER, BarricadeItems.PASSIVE_BARRIER, BarricadeItems.HOSTILE_BARRIER, - BarricadeItems.CREATIVE_ONLY_BARRIER + BarricadeItems.CREATIVE_ONLY_BARRIER, + BarricadeItems.CREATIVE_ONLY_LEVER, + BarricadeItems.CREATIVE_ONLY_BUTTON ); for (Item item : items) {