diff --git a/src/generated/resources/.cache/09230360b5e965ba1bee059b2d819a45920e92bd b/src/generated/resources/.cache/09230360b5e965ba1bee059b2d819a45920e92bd index 91cbd439d16..0ed29952aff 100644 --- a/src/generated/resources/.cache/09230360b5e965ba1bee059b2d819a45920e92bd +++ b/src/generated/resources/.cache/09230360b5e965ba1bee059b2d819a45920e92bd @@ -1,4 +1,4 @@ -// 1.21.1 2025-11-02T10:48:42.61324115 Create's Wiki Block Info Provider +// 1.21.1 2026-07-19T13:01:25.699353107 Create's Wiki Block Info Provider f7c5a556b1485698a47e098a98b9568110bd2907 data/create/.wiki/block_info/acacia_window.json 242ad940aee145de757a2baead60e779cb269340 data/create/.wiki/block_info/acacia_window_pane.json 316dde19f6eb5e8a28675870f6e727eb0bdfcfe2 data/create/.wiki/block_info/adjustable_chain_gearshift.json @@ -240,6 +240,7 @@ e0b89caf7a560c75cb5bd98ba7bbdf76620ac228 data/create/.wiki/block_info/elevator_p 316dde19f6eb5e8a28675870f6e727eb0bdfcfe2 data/create/.wiki/block_info/encased_chain_drive.json 316dde19f6eb5e8a28675870f6e727eb0bdfcfe2 data/create/.wiki/block_info/encased_fan.json 44ff927e10096a9e038344509b5dfbfc0ba2514a data/create/.wiki/block_info/encased_fluid_pipe.json +316dde19f6eb5e8a28675870f6e727eb0bdfcfe2 data/create/.wiki/block_info/entity_observer.json b856a1a87bf6b4f674d88a56363fce5b64ff10fc data/create/.wiki/block_info/experience_block.json e08896c876723ba9c2678e5fa9b341ff907da7af data/create/.wiki/block_info/exposed_copper_shingle_slab.json e08896c876723ba9c2678e5fa9b341ff907da7af data/create/.wiki/block_info/exposed_copper_shingle_stairs.json diff --git a/src/generated/resources/.cache/af1b4964b4b67530aeb67585e9573385e8cab38a b/src/generated/resources/.cache/af1b4964b4b67530aeb67585e9573385e8cab38a index 98257af932b..0bb99e6695f 100644 --- a/src/generated/resources/.cache/af1b4964b4b67530aeb67585e9573385e8cab38a +++ b/src/generated/resources/.cache/af1b4964b4b67530aeb67585e9573385e8cab38a @@ -1,4 +1,4 @@ -// 1.21.1 2026-03-06T13:40:00.170210212 Registrate Provider for create [Registries, Data Maps, Recipes, Advancements, Loot Tables, Tags (blocks), Tags (enchantments), Tags (items), Tags (fluids), Tags (entity_types), generic_server_provider, Blockstates, Item models, Lang (en_us/en_ud), generic_client_provider] +// 1.21.1 2026-07-19T13:01:25.681753905 Registrate Provider for create [Registries, Data Maps, Recipes, Advancements, Loot Tables, Tags (blocks), Tags (enchantments), Tags (items), Tags (fluids), Tags (entity_types), generic_server_provider, Blockstates, Item models, Lang (en_us/en_ud), generic_client_provider] 60bbdf92d2ac9824ea6144955c74043a6005f79d assets/create/blockstates/acacia_window.json 6a67703c2697d81b7dc83e9d72a66f9c9ff08383 assets/create/blockstates/acacia_window_pane.json c3ae87b62e81d8e9476eccd793bb1548d74c66a1 assets/create/blockstates/adjustable_chain_gearshift.json @@ -240,6 +240,7 @@ f7f5df9086c71688cbdb5d05c394dc5acb8fb338 assets/create/blockstates/elevator_cont 2fa96f480365dcbd867635eaa665d1ad5936ca65 assets/create/blockstates/encased_chain_drive.json d47bc65703e9582cc710e6408fb565e16d3514a6 assets/create/blockstates/encased_fan.json 651f9fdb11f56d887d131be8f936f508d0b2fc1d assets/create/blockstates/encased_fluid_pipe.json +adaddbfa7b7738a05c5dd00f52c13a5e5767003b assets/create/blockstates/entity_observer.json 489ad4daeaed702d231a3f175f7b66846f5789a6 assets/create/blockstates/experience_block.json 74c8a72db3dd3fa919e29baaa8c5865f13490461 assets/create/blockstates/exposed_copper_shingle_slab.json 4e0b5a9be15f0c2861f5f6bd71bd9c2a4db2a21d assets/create/blockstates/exposed_copper_shingle_stairs.json @@ -642,8 +643,8 @@ b0d8f08968763a5f74e5cd5644377a76a9f39753 assets/create/blockstates/yellow_toolbo fe8c497aacc641c2f01cec90bba9f19e59cc2ed2 assets/create/blockstates/yellow_valve_handle.json e819e93fdcbe9fd9c050a052d2718ff3b3539365 assets/create/blockstates/zinc_block.json 64121dcb216381c83b4fe28aa361ea07c24c9ad0 assets/create/blockstates/zinc_ore.json -cfc04c8bcd7c2935a5b658166cb755299679b729 assets/create/lang/en_ud.json -2157d86a90660702b4581768ef9e8e6385c53eb5 assets/create/lang/en_us.json +1475234ff986a00e5236ddd6815ee4d97eb883de assets/create/lang/en_ud.json +43b163d4a29b03f31fd3e1c71eacf46b4868d58e assets/create/lang/en_us.json a97e1060e00ae701a02e39cd4ef8054cf345fac4 assets/create/models/block/acacia_window.json 103e032c0b1a0a6a27c67da8c91179a564bd281c assets/create/models/block/acacia_window_pane_noside.json fb00b627abda76ad4fea867ca57dbfadd24fffa3 assets/create/models/block/acacia_window_pane_noside_alt.json @@ -2142,6 +2143,7 @@ d6c1c5ff9506a60fbdde4580dad39d97fc1832d3 assets/create/models/item/elevator_pull badd4326fac0b0a1590a2e9bce7c2cdd4e4562f3 assets/create/models/item/empty_schematic.json 5daa4b49db850923319916aaa9842c33f99e0a00 assets/create/models/item/encased_chain_drive.json 7ec3ed4aaab72d76f6414447bbb3ad7887adf61f assets/create/models/item/encased_fan.json +2d4e708713189fe7e2fd55ca3f30bb7cf9b83eb2 assets/create/models/item/entity_observer.json 3e1fdcc80fd68199b1890bcc830f78c48e7c0e43 assets/create/models/item/experience_block.json 9775e83414c0febb5c5b832437b0580e91bcbff3 assets/create/models/item/experience_nugget.json 721c8ac46bf23abec2bbf4cff6dbfdf96cc569a6 assets/create/models/item/exposed_copper_shingle_slab.json @@ -3638,6 +3640,7 @@ e4c0fa9229143078e12da226804e3e92e49a31a3 data/create/loot_table/blocks/elevator_ dfe0af3ff61ed2b3082e49c745d8a3e0c5973f4b data/create/loot_table/blocks/encased_chain_drive.json a2e9a8a10b7fc730c1d7c8db3b529e7a37b683f5 data/create/loot_table/blocks/encased_fan.json 7ede9f64839f51e6a2eb05b08577d2873f281401 data/create/loot_table/blocks/encased_fluid_pipe.json +ab8641e64fe20ec04868b223f014b7d59fc3b722 data/create/loot_table/blocks/entity_observer.json 4869211639326efaabd1aba1067bfbb3ab012884 data/create/loot_table/blocks/experience_block.json 9dbd37ef5ff549f10475101205c1a9d4a44140bc data/create/loot_table/blocks/exposed_copper_shingle_slab.json d2c9abd9260eb82ea1c2eeae5e2d6abd0b4d3ce8 data/create/loot_table/blocks/exposed_copper_shingle_stairs.json @@ -4893,8 +4896,8 @@ ebd7b09daf2f64c0c04d821696b0e145683d8693 data/minecraft/tags/block/combination_s f8bd9b33238ab9f2f2a83b63bf0c52fbf705b452 data/minecraft/tags/block/impermeable.json eb080d6f0f7a4fa5e723010e1fcfa781e4d30249 data/minecraft/tags/block/inside_step_sound_blocks.json 515a1c773e617dd7e38aa1b893acc7db2dd30e08 data/minecraft/tags/block/lush_ground_replaceable.json -435e59881e2d9a8cae6c23fc6ce6d43111d40277 data/minecraft/tags/block/mineable/axe.json -47df6c90d9474d7a708063b0207e520ad01f1998 data/minecraft/tags/block/mineable/pickaxe.json +914755f2162b27889f4972c4c343a13053c167c5 data/minecraft/tags/block/mineable/axe.json +950bb88d7539adcea1e61f2bb22bca0e30cd67ec data/minecraft/tags/block/mineable/pickaxe.json 515a1c773e617dd7e38aa1b893acc7db2dd30e08 data/minecraft/tags/block/moss_replaceable.json 0c13aae0eeb99e89febe8dbe5e002af2ff843a9e data/minecraft/tags/block/needs_iron_tool.json 3cb2a92cbdf32ed5978f740dc378d363306c3e84 data/minecraft/tags/block/needs_stone_tool.json diff --git a/src/generated/resources/.cache/eaed56ca9d9781c7626be345dd9f2c9a1fad638e b/src/generated/resources/.cache/eaed56ca9d9781c7626be345dd9f2c9a1fad638e index bb4d50ce85a..e4ecad875ec 100644 --- a/src/generated/resources/.cache/eaed56ca9d9781c7626be345dd9f2c9a1fad638e +++ b/src/generated/resources/.cache/eaed56ca9d9781c7626be345dd9f2c9a1fad638e @@ -1,4 +1,4 @@ -// 1.21.1 2026-03-06T13:40:00.199931125 Create's Generated Registry Entries +// 1.21.1 2026-07-19T13:01:25.701433995 Create's Generated Registry Entries abb9dd2c98388abb430343d4ac02d460e5edc086 data/create/create/potato_projectile/type/apple.json 1a20cb4e64dc07918a28fbccc73102bca3560f16 data/create/create/potato_projectile/type/baked_potato.json 8450576952f7723d22250da6f554dd0fda4e9fce data/create/create/potato_projectile/type/beetroot.json @@ -7,7 +7,7 @@ abb9dd2c98388abb430343d4ac02d460e5edc086 data/create/create/potato_projectile/ty 6cef3daecf686b417c6dfbe02556fcdff9b1e417 data/create/create/potato_projectile/type/carrot.json af17d72549ee9421d2643a215ffc2291874fff93 data/create/create/potato_projectile/type/chocolate_berry.json 8cb4811601d46db5fdc0291edce3ec2f3a64e902 data/create/create/potato_projectile/type/chorus_fruit.json -69138506c1b02aa4e2456cc1912ddb70f8a1e42a data/create/create/potato_projectile/type/enchanted_golden_apple.json +3aae8bc72d76a801c36b871eedd121ddc9cab364 data/create/create/potato_projectile/type/enchanted_golden_apple.json e3ab3c4bd70ad742d37091ae05774aadffb1d1d5 data/create/create/potato_projectile/type/fallback.json 98bf0ce51484c5a9709fc69d046d0c70d987cfdd data/create/create/potato_projectile/type/fish.json afe4e7cc87110d6f045f6672fb312a09290ca04a data/create/create/potato_projectile/type/glistering_melon.json @@ -19,7 +19,7 @@ c6234751ccad5111857b0ae9e297e42f529ad32a data/create/create/potato_projectile/ty 352402ba2fff3f23af178d15d61b0ba0a151097a data/create/create/potato_projectile/type/melon_slice.json cbfd3028ad878bddbdaeb0eec0cd5a1c50d4c901 data/create/create/potato_projectile/type/poison_potato.json 38116c664c63ca9da0ea043edc16a3ce9264c706 data/create/create/potato_projectile/type/potato.json -347a4a63c1cc99e293876fc2329f8db0f39272ba data/create/create/potato_projectile/type/pufferfish.json +d9658cdde7b85160ec59f6c66f76454f90541355 data/create/create/potato_projectile/type/pufferfish.json 63e2df2c83982204bc92479b1df26561922e795d data/create/create/potato_projectile/type/pumpkin_block.json 7d58a0671c55e40cdb728c60152665c89209fb91 data/create/create/potato_projectile/type/pumpkin_pie.json 30bf0b35aeff136251d3bfe2af04fd89ccf953de data/create/create/potato_projectile/type/suspicious_stew.json diff --git a/src/generated/resources/assets/create/blockstates/entity_observer.json b/src/generated/resources/assets/create/blockstates/entity_observer.json new file mode 100644 index 00000000000..baf271c204e --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/entity_observer.json @@ -0,0 +1,110 @@ +{ + "variants": { + "facing=east,powered=false,target=ceiling": { + "model": "create:block/entity_observer/block", + "x": 270, + "y": 90 + }, + "facing=east,powered=false,target=floor": { + "model": "create:block/entity_observer/block", + "x": 90, + "y": 90 + }, + "facing=east,powered=false,target=wall": { + "model": "create:block/entity_observer/block", + "y": 90 + }, + "facing=east,powered=true,target=ceiling": { + "model": "create:block/entity_observer/block_powered", + "x": 270, + "y": 90 + }, + "facing=east,powered=true,target=floor": { + "model": "create:block/entity_observer/block_powered", + "x": 90, + "y": 90 + }, + "facing=east,powered=true,target=wall": { + "model": "create:block/entity_observer/block_powered", + "y": 90 + }, + "facing=north,powered=false,target=ceiling": { + "model": "create:block/entity_observer/block", + "x": 270 + }, + "facing=north,powered=false,target=floor": { + "model": "create:block/entity_observer/block", + "x": 90 + }, + "facing=north,powered=false,target=wall": { + "model": "create:block/entity_observer/block" + }, + "facing=north,powered=true,target=ceiling": { + "model": "create:block/entity_observer/block_powered", + "x": 270 + }, + "facing=north,powered=true,target=floor": { + "model": "create:block/entity_observer/block_powered", + "x": 90 + }, + "facing=north,powered=true,target=wall": { + "model": "create:block/entity_observer/block_powered" + }, + "facing=south,powered=false,target=ceiling": { + "model": "create:block/entity_observer/block", + "x": 270, + "y": 180 + }, + "facing=south,powered=false,target=floor": { + "model": "create:block/entity_observer/block", + "x": 90, + "y": 180 + }, + "facing=south,powered=false,target=wall": { + "model": "create:block/entity_observer/block", + "y": 180 + }, + "facing=south,powered=true,target=ceiling": { + "model": "create:block/entity_observer/block_powered", + "x": 270, + "y": 180 + }, + "facing=south,powered=true,target=floor": { + "model": "create:block/entity_observer/block_powered", + "x": 90, + "y": 180 + }, + "facing=south,powered=true,target=wall": { + "model": "create:block/entity_observer/block_powered", + "y": 180 + }, + "facing=west,powered=false,target=ceiling": { + "model": "create:block/entity_observer/block", + "x": 270, + "y": 270 + }, + "facing=west,powered=false,target=floor": { + "model": "create:block/entity_observer/block", + "x": 90, + "y": 270 + }, + "facing=west,powered=false,target=wall": { + "model": "create:block/entity_observer/block", + "y": 270 + }, + "facing=west,powered=true,target=ceiling": { + "model": "create:block/entity_observer/block_powered", + "x": 270, + "y": 270 + }, + "facing=west,powered=true,target=floor": { + "model": "create:block/entity_observer/block_powered", + "x": 90, + "y": 270 + }, + "facing=west,powered=true,target=wall": { + "model": "create:block/entity_observer/block_powered", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/lang/en_ud.json b/src/generated/resources/assets/create/lang/en_ud.json index 2596b21522c..694dd278652 100644 --- a/src/generated/resources/assets/create/lang/en_ud.json +++ b/src/generated/resources/assets/create/lang/en_ud.json @@ -467,6 +467,7 @@ "block.create.encased_chain_drive": "ǝʌıɹᗡ uıɐɥƆ pǝsɐɔuƎ", "block.create.encased_fan": "uɐℲ pǝsɐɔuƎ", "block.create.encased_fluid_pipe": "ǝdıԀ pınןℲ pǝsɐɔuƎ", + "block.create.entity_observer": "ɹǝʌɹǝsqO ʎʇıʇuƎ", "block.create.experience_block": "ǝɔuǝıɹǝdxƎ ɟo ʞɔoןᗺ", "block.create.exposed_copper_shingle_slab": "qɐןS ǝןbuıɥS ɹǝddoƆ pǝsodxƎ", "block.create.exposed_copper_shingle_stairs": "sɹıɐʇS ǝןbuıɥS ɹǝddoƆ pǝsodxƎ", diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 930893da30f..915fbc22b63 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -467,6 +467,7 @@ "block.create.encased_chain_drive": "Encased Chain Drive", "block.create.encased_fan": "Encased Fan", "block.create.encased_fluid_pipe": "Encased Fluid Pipe", + "block.create.entity_observer": "Entity Observer", "block.create.experience_block": "Block of Experience", "block.create.exposed_copper_shingle_slab": "Exposed Copper Shingle Slab", "block.create.exposed_copper_shingle_stairs": "Exposed Copper Shingle Stairs", diff --git a/src/generated/resources/assets/create/models/item/entity_observer.json b/src/generated/resources/assets/create/models/item/entity_observer.json new file mode 100644 index 00000000000..f71302645ed --- /dev/null +++ b/src/generated/resources/assets/create/models/item/entity_observer.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/entity_observer/block" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/.wiki/block_info/entity_observer.json b/src/generated/resources/data/create/.wiki/block_info/entity_observer.json new file mode 100644 index 00000000000..e96aad8d696 --- /dev/null +++ b/src/generated/resources/data/create/.wiki/block_info/entity_observer.json @@ -0,0 +1,9 @@ +{ + "blast_resistance": 6.0, + "flammable": false, + "hardness": 1.5, + "ignited_by_lava": false, + "luminous": false, + "stackable": 64, + "waterloggable": false +} \ No newline at end of file diff --git a/src/generated/resources/data/create/create/potato_projectile/type/enchanted_golden_apple.json b/src/generated/resources/data/create/create/potato_projectile/type/enchanted_golden_apple.json index 3debb2bf5c8..d03c568b4a1 100644 --- a/src/generated/resources/data/create/create/potato_projectile/type/enchanted_golden_apple.json +++ b/src/generated/resources/data/create/create/potato_projectile/type/enchanted_golden_apple.json @@ -12,8 +12,8 @@ "duration": 400, "id": "minecraft:regeneration", "neoforge:cures": [ - "protected_by_totem", - "milk" + "milk", + "protected_by_totem" ], "show_icon": true } @@ -23,8 +23,8 @@ "duration": 6000, "id": "minecraft:resistance", "neoforge:cures": [ - "protected_by_totem", - "milk" + "milk", + "protected_by_totem" ], "show_icon": true } @@ -34,8 +34,8 @@ "duration": 6000, "id": "minecraft:fire_resistance", "neoforge:cures": [ - "protected_by_totem", - "milk" + "milk", + "protected_by_totem" ], "show_icon": true } @@ -46,8 +46,8 @@ "duration": 2400, "id": "minecraft:absorption", "neoforge:cures": [ - "protected_by_totem", - "milk" + "milk", + "protected_by_totem" ], "show_icon": true } diff --git a/src/generated/resources/data/create/create/potato_projectile/type/pufferfish.json b/src/generated/resources/data/create/create/potato_projectile/type/pufferfish.json index 2443f6f79ef..bec2be8d68e 100644 --- a/src/generated/resources/data/create/create/potato_projectile/type/pufferfish.json +++ b/src/generated/resources/data/create/create/potato_projectile/type/pufferfish.json @@ -12,9 +12,9 @@ "duration": 1200, "id": "minecraft:poison", "neoforge:cures": [ - "protected_by_totem", "honey", - "milk" + "milk", + "protected_by_totem" ], "show_icon": true } @@ -25,8 +25,8 @@ "duration": 300, "id": "minecraft:hunger", "neoforge:cures": [ - "protected_by_totem", - "milk" + "milk", + "protected_by_totem" ], "show_icon": true } @@ -36,8 +36,8 @@ "duration": 300, "id": "minecraft:nausea", "neoforge:cures": [ - "protected_by_totem", - "milk" + "milk", + "protected_by_totem" ], "show_icon": true } diff --git a/src/generated/resources/data/create/loot_table/blocks/entity_observer.json b/src/generated/resources/data/create/loot_table/blocks/entity_observer.json new file mode 100644 index 00000000000..3427dda529f --- /dev/null +++ b/src/generated/resources/data/create/loot_table/blocks/entity_observer.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:entity_observer" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "create:blocks/entity_observer" +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/mineable/axe.json b/src/generated/resources/data/minecraft/tags/block/mineable/axe.json index 9189599f806..956477853dc 100644 --- a/src/generated/resources/data/minecraft/tags/block/mineable/axe.json +++ b/src/generated/resources/data/minecraft/tags/block/mineable/axe.json @@ -88,6 +88,7 @@ "create:mechanical_arm", "create:railway_casing", "create:content_observer", + "create:entity_observer", "create:stockpile_switch", "create:creative_crate", "create:white_postbox", diff --git a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json index 07d3648425c..a0fdcdd71a9 100644 --- a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json +++ b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json @@ -128,6 +128,7 @@ "create:andesite_tunnel", "create:brass_tunnel", "create:content_observer", + "create:entity_observer", "create:stockpile_switch", "create:creative_crate", "create:item_vault", diff --git a/src/main/java/com/simibubi/create/AllBlockEntityTypes.java b/src/main/java/com/simibubi/create/AllBlockEntityTypes.java index bd2bf7a5ae6..76511a1abec 100644 --- a/src/main/java/com/simibubi/create/AllBlockEntityTypes.java +++ b/src/main/java/com/simibubi/create/AllBlockEntityTypes.java @@ -201,6 +201,7 @@ import com.simibubi.create.content.redstone.diodes.PulseTimerBlockEntity; import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity; import com.simibubi.create.content.redstone.displayLink.LinkBulbRenderer; +import com.simibubi.create.content.redstone.entityObserver.EntityObserverBlockEntity; import com.simibubi.create.content.redstone.link.RedstoneLinkBlockEntity; import com.simibubi.create.content.redstone.link.controller.LecternControllerBlockEntity; import com.simibubi.create.content.redstone.link.controller.LecternControllerRenderer; @@ -341,7 +342,7 @@ public class AllBlockEntityTypes { .validBlocks(AllBlocks.HAND_CRANK) .renderer(() -> HandCrankRenderer::new) .register(); - + public static final BlockEntityEntry VALVE_HANDLE = REGISTRATE .blockEntity("valve_handle", ValveHandleBlockEntity::new) .visual(() -> ValveHandleVisual::new) @@ -794,7 +795,7 @@ public class AllBlockEntityTypes { .validBlocks(AllBlocks.ANALOG_LEVER) .renderer(() -> AnalogLeverRenderer::new) .register(); - + public static final BlockEntityEntry PLACARD = REGISTRATE .blockEntity("placard", PlacardBlockEntity::new) .validBlocks(AllBlocks.PLACARD) @@ -874,6 +875,12 @@ public class AllBlockEntityTypes { .renderer(() -> SmartBlockEntityRenderer::new) .register(); + public static final BlockEntityEntry ENTITY_OBSERVER = REGISTRATE + .blockEntity("entity_observer", EntityObserverBlockEntity::new) + .validBlocks(AllBlocks.ENTITY_OBSERVER) + .renderer(() -> SmartBlockEntityRenderer::new) + .register(); + public static final BlockEntityEntry PULSE_EXTENDER = REGISTRATE .blockEntity("pulse_extender", PulseExtenderBlockEntity::new) .visual(() -> BrassDiodeVisual::new, false) @@ -940,7 +947,7 @@ public class AllBlockEntityTypes { .validBlocksDeferred(TrackMaterial::allBlocks) .renderer(() -> TrackRenderer::new) .register(); - + public static final BlockEntityEntry FAKE_TRACK = REGISTRATE .blockEntity("fake_track", FakeTrackBlockEntity::new) .validBlocks(AllBlocks.FAKE_TRACK) @@ -991,7 +998,7 @@ public class AllBlockEntityTypes { .renderer(() -> TrackObserverRenderer::new) .validBlocks(AllBlocks.TRACK_OBSERVER) .register(); - + public static final BlockEntityEntry CLIPBOARD = REGISTRATE .blockEntity("clipboard", ClipboardBlockEntity::new) .validBlocks(AllBlocks.CLIPBOARD) diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 4335fb2c745..da06f24be3c 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -228,6 +228,8 @@ import com.simibubi.create.content.redstone.diodes.ToggleLatchGenerator; import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockItem; +import com.simibubi.create.content.redstone.entityObserver.EntityObserverBlock; +import com.simibubi.create.content.redstone.entityObserver.EntityObserverGenerator; import com.simibubi.create.content.redstone.link.RedstoneLinkBlock; import com.simibubi.create.content.redstone.link.RedstoneLinkGenerator; import com.simibubi.create.content.redstone.link.controller.LecternControllerBlock; @@ -1809,6 +1811,24 @@ public class AllBlocks { .transform(customItemModel("_", "block")) .register(); + public static final BlockEntry ENTITY_OBSERVER = + REGISTRATE.block("entity_observer", EntityObserverBlock::new) + .initialProperties(SharedProperties::stone) + .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN) + .noOcclusion()) + .properties(p -> p.isRedstoneConductor(($1, $2, $3) -> false)) + .transform(axeOrPickaxe()) + .blockstate(new EntityObserverGenerator()::generate) + .transform(displaySource(AllDisplaySources.COUNT_ITEMS)) + .transform(displaySource(AllDisplaySources.LIST_ITEMS)) + .transform(displaySource(AllDisplaySources.COUNT_FLUIDS)) + .transform(displaySource(AllDisplaySources.LIST_FLUIDS)) + .transform(displaySource(AllDisplaySources.READ_PACKAGE_ADDRESS)) + .lang("Entity Observer") + .item() + .transform(customItemModel("_", "block")) + .register(); + public static final BlockEntry THRESHOLD_SWITCH = REGISTRATE.block("stockpile_switch", ThresholdSwitchBlock::new) .initialProperties(SharedProperties::stone) diff --git a/src/main/java/com/simibubi/create/content/redstone/entityObserver/EntityObserverBlock.java b/src/main/java/com/simibubi/create/content/redstone/entityObserver/EntityObserverBlock.java new file mode 100644 index 00000000000..bd03879a69a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/entityObserver/EntityObserverBlock.java @@ -0,0 +1,158 @@ +package com.simibubi.create.content.redstone.entityObserver; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.fluids.FluidTransportBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.logistics.funnel.FunnelBlockEntity; +import com.simibubi.create.content.redstone.DirectedDirectionalBlock; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; + +import net.createmod.catnip.data.Iterate; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +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.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.AttachFace; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; + +import net.neoforged.neoforge.capabilities.Capabilities; + +public class EntityObserverBlock extends DirectedDirectionalBlock implements IBE { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + public EntityObserverBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(POWERED, false)); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(POWERED)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + BlockState state = defaultBlockState(); + + Direction preferredFacing = null; + for (Direction face : context.getNearestLookingDirections()) { + BlockPos offsetPos = context.getClickedPos() + .relative(face); + Level world = context.getLevel(); + boolean canDetect = false; + BlockEntity blockEntity = world.getBlockEntity(offsetPos); + + if (BlockEntityBehaviour.get(blockEntity, TransportedItemStackHandlerBehaviour.TYPE) != null) + canDetect = true; + else if (BlockEntityBehaviour.get(blockEntity, FluidTransportBehaviour.TYPE) != null) + canDetect = true; + else if (blockEntity != null && ( + context.getLevel().getCapability(Capabilities.ItemHandler.BLOCK, blockEntity.getBlockPos(), null) != null || + context.getLevel().getCapability(Capabilities.FluidHandler.BLOCK, blockEntity.getBlockPos(), null) != null + )) + canDetect = true; + else if (blockEntity instanceof FunnelBlockEntity) + canDetect = true; + + if (canDetect) { + preferredFacing = face; + break; + } + } + + if (preferredFacing == null) { + Direction facing = context.getNearestLookingDirection(); + preferredFacing = context.getPlayer() != null && context.getPlayer() + .isShiftKeyDown() ? facing : facing.getOpposite(); + } + + if (preferredFacing.getAxis() == Axis.Y) { + state = state.setValue(TARGET, preferredFacing == Direction.UP ? AttachFace.CEILING : AttachFace.FLOOR); + preferredFacing = context.getHorizontalDirection(); + } + + return state.setValue(FACING, preferredFacing); + } + + @Override + public boolean isSignalSource(BlockState state) { + return state.getValue(POWERED); + } + + @Override + public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { + return isSignalSource(blockState) && (side == null || side != getTargetDirection(blockState) + .getOpposite()) ? 15 : 0; + } + + @Override + public void tick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random) { + worldIn.setBlock(pos, state.setValue(POWERED, false), Block.UPDATE_CLIENTS); + worldIn.updateNeighborsAt(pos, this); + } + + @Override + public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, Direction side) { + return side != state.getValue(FACING) + .getOpposite(); + } + + @Override + public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + IBE.onRemove(state, worldIn, pos, newState); + } + + @Override + public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + boolean isMoving) { + InvManipulationBehaviour behaviour = BlockEntityBehaviour.get(worldIn, pos, InvManipulationBehaviour.TYPE); + if (behaviour != null) + behaviour.onNeighborChanged(fromPos); + } + + public void onFunnelTransfer(Level world, BlockPos funnelPos, ItemStack transferred) { + for (Direction direction : Iterate.directions) { + BlockPos detectorPos = funnelPos.relative(direction); + BlockState detectorState = world.getBlockState(detectorPos); + if (!AllBlocks.SMART_OBSERVER.has(detectorState)) + continue; + if (EntityObserverBlock.getTargetDirection(detectorState) != direction.getOpposite()) + continue; + withBlockEntityDo(world, detectorPos, be -> { + FilteringBehaviour filteringBehaviour = BlockEntityBehaviour.get(be, FilteringBehaviour.TYPE); + if (filteringBehaviour == null) + return; + if (!filteringBehaviour.test(transferred)) + return; + be.activate(4); + }); + } + } + + @Override + public Class getBlockEntityClass() { + return EntityObserverBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ENTITY_OBSERVER.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/entityObserver/EntityObserverBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/entityObserver/EntityObserverBlockEntity.java new file mode 100644 index 00000000000..e554d50a528 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/entityObserver/EntityObserverBlockEntity.java @@ -0,0 +1,238 @@ +package com.simibubi.create.content.redstone.entityObserver; + +import java.util.List; + +import com.simibubi.create.content.fluids.FluidTransportBehaviour; +import com.simibubi.create.content.fluids.PipeConnection.Flow; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorBlockEntity; +import com.simibubi.create.content.kinetics.chainConveyor.ChainConveyorPackage; +import com.simibubi.create.content.redstone.DirectedDirectionalBlock; +import com.simibubi.create.content.redstone.FilteredDetectorFilterSlot; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.CapManipulationBehaviourBase.InterfaceProvider; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.TankManipulationBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryTrackerBehaviour; + +import net.createmod.catnip.data.Iterate; +import net.createmod.catnip.math.BlockFace; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.Clearable; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.MinecartChest; +import net.minecraft.world.phys.AABB; + +public class EntityObserverBlockEntity extends SmartBlockEntity implements Clearable { + private static final int DEFAULT_DELAY = 6; + private FilteringBehaviour filtering; + private InvManipulationBehaviour observedInventory; + private TankManipulationBehaviour observedTank; + + private VersionedInventoryTrackerBehaviour invVersionTracker; + private boolean sustainSignal; + + public int turnOffTicks = 0; + + public EntityObserverBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + setLazyTickRate(20); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot(false)) + .withCallback($ -> invVersionTracker.reset())); + behaviours.add(invVersionTracker = new VersionedInventoryTrackerBehaviour(this)); + + InterfaceProvider towardBlockFacing = + (w, p, s) -> new BlockFace(p, DirectedDirectionalBlock.getTargetDirection(s)); + + behaviours.add(observedInventory = new InvManipulationBehaviour(this, towardBlockFacing).bypassSidedness()); + behaviours.add(observedTank = new TankManipulationBehaviour(this, towardBlockFacing).bypassSidedness()); + } + + private boolean checkEntities(BlockPos targetPos) { + if (level == null) + return false; + + AABB scanBox = new AABB(targetPos); + List entities = level.getEntitiesOfClass(Entity.class, scanBox, e -> true); + + boolean noFilter = filtering.getFilter().isEmpty(); + + for (Entity entity : entities) { + if (noFilter) + return true; + + if (entity instanceof ItemEntity itemEntity) { + if (filtering.test(itemEntity.getItem())) + return true; + continue; + } + + if (entity instanceof MinecartChest chestMinecart) { + if (matchesEntityItem(chestMinecart)) + return true; + for (int slot = 0; slot < chestMinecart.getContainerSize(); slot++) { + ItemStack stack = chestMinecart.getItem(slot); + if (!stack.isEmpty() && filtering.test(stack)) + return true; + } + continue; + } + + if (entity instanceof AbstractMinecart minecart) { + if (matchesEntityItem(minecart)) + return true; + } + } + + return false; + } + + private boolean matchesEntityItem(Entity entity) { + ItemStack representative = entity.getPickResult(); + return representative != null && !representative.isEmpty() && filtering.test(representative); + } + + @Override + public void tick() { + super.tick(); + + if (level.isClientSide()) + return; + + BlockState state = getBlockState(); + if (turnOffTicks > 0) { + turnOffTicks--; + if (turnOffTicks == 0) + level.scheduleTick(worldPosition, state.getBlock(), 1); + } + + if (!isActive()) + return; + + BlockPos targetPos = worldPosition.relative(EntityObserverBlock.getTargetDirection(state)); + if (checkEntities(targetPos)) { + activate(3); + return; + } + + Block block = level.getBlockState(targetPos) + .getBlock(); + + // Detect items on belt + TransportedItemStackHandlerBehaviour behaviour = + BlockEntityBehaviour.get(level, targetPos, TransportedItemStackHandlerBehaviour.TYPE); + if (behaviour != null) { + behaviour.handleCenteredProcessingOnAllItems(.45f, stack -> { + if (!filtering.test(stack.stack) || turnOffTicks == 6) + return TransportedResult.doNothing(); + activate(); + return TransportedResult.doNothing(); + }); + return; + } + + // Detect fluids in pipe + FluidTransportBehaviour fluidBehaviour = + BlockEntityBehaviour.get(level, targetPos, FluidTransportBehaviour.TYPE); + if (fluidBehaviour != null) { + for (Direction side : Iterate.directions) { + Flow flow = fluidBehaviour.getFlow(side); + if (flow == null || !flow.inbound || !flow.complete) + continue; + if (!filtering.test(flow.fluid)) + continue; + activate(); + return; + } + return; + } + + // Detect packages looping on a chain conveyor + if (level.getBlockEntity(targetPos) instanceof ChainConveyorBlockEntity ccbe) { + for (ChainConveyorPackage box : ccbe.getLoopingPackages()) + if (filtering.test(box.item)) { + activate(); + return; + } + return; + } + + if (observedInventory.hasInventory()) { + boolean skipInv = invVersionTracker.stillWaiting(observedInventory); + invVersionTracker.awaitNewVersion(observedInventory); + + if (skipInv && sustainSignal) + turnOffTicks = DEFAULT_DELAY; + + if (!skipInv) { + sustainSignal = false; + if (!observedInventory.simulate() + .extract() + .isEmpty()) { + sustainSignal = true; + activate(); + return; + } + } + } + + if (!observedTank.simulate() + .extractAny() + .isEmpty()) { + activate(); + return; + } + } + + public void activate() { + activate(DEFAULT_DELAY); + } + + public void activate(int ticks) { + BlockState state = getBlockState(); + turnOffTicks = ticks; + if (state.getValue(EntityObserverBlock.POWERED)) + return; + level.setBlockAndUpdate(worldPosition, state.setValue(EntityObserverBlock.POWERED, true)); + level.updateNeighborsAt(worldPosition, state.getBlock()); + } + + private boolean isActive() { + return true; + } + + @Override + public void write(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) { + compound.putInt("TurnOff", turnOffTicks); + super.write(compound, registries, clientPacket); + } + + @Override + protected void read(CompoundTag compound, HolderLookup.Provider registries, boolean clientPacket) { + super.read(compound, registries, clientPacket); + turnOffTicks = compound.getInt("TurnOff"); + } + + @Override + public void clearContent() { + filtering.setFilter(ItemStack.EMPTY); + } +} diff --git a/src/main/java/com/simibubi/create/content/redstone/entityObserver/EntityObserverGenerator.java b/src/main/java/com/simibubi/create/content/redstone/entityObserver/EntityObserverGenerator.java new file mode 100644 index 00000000000..edaddaf1a46 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/entityObserver/EntityObserverGenerator.java @@ -0,0 +1,36 @@ +package com.simibubi.create.content.redstone.entityObserver; + +import com.simibubi.create.content.redstone.thresholdSwitch.ThresholdSwitchBlock; +import com.simibubi.create.foundation.data.AssetLookup; +import com.simibubi.create.foundation.data.SpecialBlockStateGen; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.neoforge.client.model.generators.ModelFile; + +public class EntityObserverGenerator extends SpecialBlockStateGen { + + @Override + protected int getXRotation(BlockState state) { + return switch (state.getValue(EntityObserverBlock.TARGET)) { + case CEILING -> -90; + case WALL -> 0; + case FLOOR -> 90; + }; + } + + @Override + protected int getYRotation(BlockState state) { + return horizontalAngle(state.getValue(ThresholdSwitchBlock.FACING)) + 180; + } + + @Override + public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, + BlockState state) { + return AssetLookup.forPowered(ctx, prov) + .apply(state); + } + +} diff --git a/src/main/resources/assets/create/models/block/entity_observer/block.json b/src/main/resources/assets/create/models/block/entity_observer/block.json new file mode 100644 index 00000000000..13c94c9065c --- /dev/null +++ b/src/main/resources/assets/create/models/block/entity_observer/block.json @@ -0,0 +1,26 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "create:block/entity_observer", + "2": "create:block/entity_observer_front", + "4": "create:block/entity_observer_top", + "6": "create:block/entity_observer_bottom", + "7": "create:block/entity_observer_side", + "particle": "create:block/entity_observer" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 16, 16], + "faces": { + "north": {"uv": [0, 0, 16, 16], "texture": "#2"}, + "east": {"uv": [0, 0, 16, 16], "texture": "#7"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#0"}, + "west": {"uv": [0, 0, 16, 16], "texture": "#7"}, + "up": {"uv": [0, 0, 16, 16], "rotation": 180, "texture": "#4"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#6"} + } + } + ] +} diff --git a/src/main/resources/assets/create/models/block/entity_observer/block_powered.json b/src/main/resources/assets/create/models/block/entity_observer/block_powered.json new file mode 100644 index 00000000000..e0763d52f91 --- /dev/null +++ b/src/main/resources/assets/create/models/block/entity_observer/block_powered.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/entity_observer/block", + "textures": { + "0": "create:block/entity_observer_powered", + "7": "create:block/entity_observer_side_powered", + "particle": "create:block/entity_observer_powered" + } +} diff --git a/src/main/resources/assets/create/textures/block/entity_observer.png b/src/main/resources/assets/create/textures/block/entity_observer.png new file mode 100644 index 00000000000..c86c215f1de Binary files /dev/null and b/src/main/resources/assets/create/textures/block/entity_observer.png differ diff --git a/src/main/resources/assets/create/textures/block/entity_observer_bottom.png b/src/main/resources/assets/create/textures/block/entity_observer_bottom.png new file mode 100644 index 00000000000..240682b53ef Binary files /dev/null and b/src/main/resources/assets/create/textures/block/entity_observer_bottom.png differ diff --git a/src/main/resources/assets/create/textures/block/entity_observer_front.png b/src/main/resources/assets/create/textures/block/entity_observer_front.png new file mode 100644 index 00000000000..db763b867ef Binary files /dev/null and b/src/main/resources/assets/create/textures/block/entity_observer_front.png differ diff --git a/src/main/resources/assets/create/textures/block/entity_observer_powered.png b/src/main/resources/assets/create/textures/block/entity_observer_powered.png new file mode 100644 index 00000000000..b4e645b07ac Binary files /dev/null and b/src/main/resources/assets/create/textures/block/entity_observer_powered.png differ diff --git a/src/main/resources/assets/create/textures/block/entity_observer_side.png b/src/main/resources/assets/create/textures/block/entity_observer_side.png new file mode 100644 index 00000000000..476d9df6867 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/entity_observer_side.png differ diff --git a/src/main/resources/assets/create/textures/block/entity_observer_side_powered.png b/src/main/resources/assets/create/textures/block/entity_observer_side_powered.png new file mode 100644 index 00000000000..b97f10a7efb Binary files /dev/null and b/src/main/resources/assets/create/textures/block/entity_observer_side_powered.png differ diff --git a/src/main/resources/assets/create/textures/block/entity_observer_top.png b/src/main/resources/assets/create/textures/block/entity_observer_top.png new file mode 100644 index 00000000000..d08a4139813 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/entity_observer_top.png differ