merge changes from 1.20.1/feature-dev

This commit is contained in:
zelophed 2023-11-17 16:37:37 +01:00
commit 0e69448d0a
205 changed files with 73724 additions and 67918 deletions

View file

@ -49,6 +49,8 @@ body:
label: Mod Version
description: The version of the mod you were using when the bug occured
options:
- "0.5.1f"
- "0.5.1e"
- "0.5.1d"
- "0.5.1c"
- "0.5.1b"

View file

@ -258,6 +258,8 @@ dependencies {
// runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.1.1.252")
// runtimeOnly fg.deobf("maven.modrinth:rubidium:0.5.3")
// implementation fg.deobf("com.railwayteam.railways:railways-1.18.2-1.1.1:all") { transitive = false }
// runtimeOnly fg.deobf("maven.modrinth:aether:1.19.2-1.0.0-beta.1.1-forge")
// runtimeOnly fg.deobf("maven.modrinth:spark:1.10.38-forge")
// https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497
// Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings

View file

@ -10,6 +10,7 @@
"translation": "src/main/resources/assets/create/lang/%locale_with_underscore%.json",
"languages_mapping": {
"locale_with_underscore": {
"be": "be_by",
"cs": "cs_cz",
"cy": "cy_gb",
"da": "da_dk",
@ -18,6 +19,7 @@
"es-CL": "es_cl",
"es-ES": "es_es",
"es-MX": "es_mx",
"et": "et_ee",
"fa": "fa_ir",
"fi": "fi_fi",
"fr": "fr_fr",
@ -41,6 +43,7 @@
"tok": "tok",
"tr": "tr_tr",
"uk": "uk_ua",
"vi": "vi_vn",
"zh-CN": "zh_cn",
"zh-TW": "zh_tw",
}

View file

@ -4,7 +4,7 @@ org.gradle.jvmargs = -Xmx3G
org.gradle.daemon = false
# mod version info
mod_version = 0.5.1.e
mod_version = 0.6.0
artifact_minecraft_version = 1.20.1
minecraft_version = 1.20.1
@ -23,13 +23,13 @@ use_parchment = true
# dependency versions
registrate_version = MC1.20-1.3.3
flywheel_minecraft_version = 1.20.1
flywheel_version = 0.6.10-6
flywheel_version = 0.6.10-7
jei_minecraft_version = 1.20.1
jei_version = 15.2.0.22
curios_minecraft_version = 1.20.1
curios_version = 5.2.0-beta.3
catnip_version = 0.7.4
ponder_version = 0.7.4
curios_version = 5.3.1
catnip_version = 0.7.5
ponder_version = 0.7.5
cc_tweaked_enable = true
cc_tweaked_minecraft_version = 1.20.1

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-07-04T18:31:12.3951444 Create's Sequenced Assembly Recipes
// 1.20.1 2023-09-20T19:40:25.4471912 Create's Sequenced Assembly Recipes
dbaca5a5aa312f3bc7b826e51e665d32e798a5d7 data/create/recipes/sequenced_assembly/precision_mechanism.json
0cdbd4f583aa0a2aa8f3ca2827199bede1732722 data/create/recipes/sequenced_assembly/sturdy_sheet.json
1274315b5c570722d6f5b2ed7f5e53fe01b6288a data/create/recipes/sequenced_assembly/track.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-08-22T15:37:03.5601186 Registrate Provider for create [Recipes, Advancements, Loot Tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), Blockstates, Item models, Lang (en_us/en_ud)]
// 1.20.1 2023-11-17T16:06:13.2756739 Registrate Provider for create [Recipes, Advancements, Loot Tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), Blockstates, Item models, Lang (en_us/en_ud)]
60bbdf92d2ac9824ea6144955c74043a6005f79d assets/create/blockstates/acacia_window.json
6a67703c2697d81b7dc83e9d72a66f9c9ff08383 assets/create/blockstates/acacia_window_pane.json
c3ae87b62e81d8e9476eccd793bb1548d74c66a1 assets/create/blockstates/adjustable_chain_gearshift.json
@ -585,8 +585,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
3a1e0c68a9f1d6a252f47b3f7311278711f2aae0 assets/create/lang/en_ud.json
a0c0e4f23540bef4b1796ad9f4e4ace609d2919b assets/create/lang/en_us.json
807ea2be63882ed9e2d14267abf902a4c9313027 assets/create/lang/en_ud.json
50e19fb11134116092d9f05811ff63bc116a997c 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
@ -4171,6 +4171,10 @@ f1a03ac86925e26cbec6aeeada2eafb40008fc8e data/create/recipes/weathered_copper_ti
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/blocks/contraption_inventory_deny.json
c7ec0dbc18e9c1b58e568ed925287b89df11a136 data/create/tags/blocks/copycat_allow.json
876eb9210f4a14898a2fe6d225699c66b5bdfeef data/create/tags/blocks/copycat_deny.json
f675c20350ed60da4878b5d6301f02c8c05624bd data/create/tags/blocks/fan_processing_catalysts/blasting.json
0592b99f657415f6546564ed8efa1fcbef07ba15 data/create/tags/blocks/fan_processing_catalysts/haunting.json
9386dd9a1d234813f9b8ae4ec88866d396aa1d37 data/create/tags/blocks/fan_processing_catalysts/smoking.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/blocks/fan_processing_catalysts/splashing.json
6858173c670bb593664ac3c62ded726d57d581f1 data/create/tags/blocks/fan_transparent.json
2589b135c0e96ad29076569e144528fe32ea5b39 data/create/tags/blocks/girdable_tracks.json
a1e21c22f32354fd1a82a1b0a59dd786c0deaba0 data/create/tags/blocks/movable_empty_collider.json
@ -4185,9 +4189,14 @@ a5874f73c7dc0a3ae12999e6ae8abf45bc7fb9be data/create/tags/blocks/passive_boiler_
da739ad2160e7df4e0e5cc89587670ce5e9450c3 data/create/tags/blocks/valve_handles.json
72143286fb5cb372a0696550e2eac76ca50e6fbc data/create/tags/blocks/windmill_sails.json
58987ea71d488cc48192ceb00c00aa2903e51304 data/create/tags/blocks/wrench_pickup.json
76c0522664726c09461ad4565b6fba80b4f816b2 data/create/tags/entity_types/blaze_burner_capturable.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/entity_types/ignore_seat.json
894e1e4fd1e32712abdda18ec64ab13750d3c039 data/create/tags/fluids/bottomless/allow.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/fluids/bottomless/deny.json
e191d5f912e05091b3a0b1df17f4c4181e04d96f data/create/tags/fluids/fan_processing_catalysts/blasting.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/fluids/fan_processing_catalysts/haunting.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/fluids/fan_processing_catalysts/smoking.json
c9ae54a7510073b17edf82f7591e14bdb2c51837 data/create/tags/fluids/fan_processing_catalysts/splashing.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/items/blaze_burner_fuel/regular.json
8ba98bf390a326abeebfd5d84be5f740c935a8b6 data/create/tags/items/blaze_burner_fuel/special.json
8b6c0b444b15f7fb2d55b9cbcb68537c1269f877 data/create/tags/items/casing.json
@ -4195,8 +4204,8 @@ f43cac8216e2a9347e48cf93a43de95dd810ca20 data/create/tags/items/contraption_cont
d371dfd35e49a7bef19f59c03e7f4ae20992f03d data/create/tags/items/create_ingots.json
910d0f5ccbc4c84b224eca1f1588b1695f41447b data/create/tags/items/crushed_raw_materials.json
0fa526e7e742573b603ad26b09526cf724efa1dc data/create/tags/items/deployable_drink.json
99d3f12c67bd4c1f14fa9e6cbc1de5ed209ef402 data/create/tags/items/modded_stripped_logs.json
b49ad07e47fbb4b12c1d95d72f752e6e6839a815 data/create/tags/items/modded_stripped_wood.json
ab45dc78be188d430c71904015b2b034908db64e data/create/tags/items/modded_stripped_logs.json
864fb582620b267894ad4016af8f0fd793bac5e8 data/create/tags/items/modded_stripped_wood.json
695d75b352fd190b303c724d1aaee9bb786a903b data/create/tags/items/pressurized_air_sources.json
2cd3adffd8b151354df137a990dcb97996a665bb data/create/tags/items/sandpaper.json
79418bd729cef417b322cef9b491e7ae83317d61 data/create/tags/items/seats.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-07-04T18:31:12.3303171 Create's Advancements
// 1.20.1 2023-09-20T19:40:25.3622264 Create's Advancements
2661a689fdcf729494f46e3c719f71c62e31582e data/create/advancements/andesite_alloy.json
fa16c4afe0496edc3f157858a6e0ff177a1622ff data/create/advancements/andesite_casing.json
5a694002d0a663bc869b09d15924a10c43dc522f data/create/advancements/anvil_plough.json
@ -29,7 +29,7 @@ ac78707d112458c7f771260cf65f0e9bc928d1b6 data/create/advancements/deployer.json
48c3af4499797cfb695a235e4527c52c608d40ad data/create/advancements/display_board_0.json
24be041d833017d7e7e02a5a92fd04060ea62594 data/create/advancements/display_link.json
cc2c729cf82a0c80b4966ac6382984da08429b9d data/create/advancements/diving_suit.json
7418171d223567cb52b22f5facef648af04cbae6 data/create/advancements/diving_suit_lava.json
e1af547fd148cf9e60c1725ab03545fe3010eac7 data/create/advancements/diving_suit_lava.json
4d91e6a7bbf08191d8d1e11943650dfc1dc170e6 data/create/advancements/drain.json
dee06f0f78a97a6358b67459d05fb479e5318fe9 data/create/advancements/ejector_maxed.json
3300ee54dc1e9d04fd13a11c971e046d9db24e10 data/create/advancements/encased_fan.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-07-04T18:31:12.4130959 Create's Mechanical Crafting Recipes
// 1.20.1 2023-09-20T19:40:25.4511802 Create's Mechanical Crafting Recipes
f076d64d9f30709bed34775136c9241097b28aa9 data/create/recipes/mechanical_crafting/crushing_wheel.json
694dca9dcff246bb7f560b3304fcc244c53217d5 data/create/recipes/mechanical_crafting/extendo_grip.json
3b2837b08607c1ca466fa3eb418209b2e55da6ba data/create/recipes/mechanical_crafting/potato_cannon.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-07-04T18:31:12.4081093 Create's Standard Recipes
// 1.20.1 2023-09-20T19:40:25.4471912 Create's Standard Recipes
a8cc4af26f6c7c45a9eef12e92af1452fe042454 data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank.json
2c2639c7b307ee7c7a4e97e5efebf496788998ad data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank_from_netherite.json
81dcf0cb1aa99e39bc7d1a386e07cad4cee7d8b9 data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_boots.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-08-25T18:36:29.7642425 Create's Damage Type Tags
// 1.20.1 2023-09-20T19:47:44.9018689 Create's Damage Type Tags
7884716b2f4bb1330ff215366bb4bab06e4728c2 data/minecraft/tags/damage_type/bypasses_armor.json
1fcad1f89265fba8bdb05b03a1dfcc88d7b7a550 data/minecraft/tags/damage_type/is_explosion.json
08324c61115b72bb8a6370d7f34d84d9a31afd16 data/minecraft/tags/damage_type/is_fire.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-08-23T16:29:07.6573146 Create's Processing Recipes
// 1.20.1 2023-09-20T19:40:25.3652491 Create's Processing Recipes
3c94326fb730f68c1e44fe1e2ef09c9db6ffd92b data/create/recipes/compacting/andesite_from_flint.json
8d3d5b31f3601b9f681ff710e0545a483a1494c6 data/create/recipes/compacting/blaze_cake.json
8bd7f4e3a686ab520b2d55594d2018d0e9a50c91 data/create/recipes/compacting/chocolate.json

View file

@ -1,2 +1,2 @@
// 1.20.1 2023-07-04T18:31:12.3492665 Create's Custom Sounds
// 1.20.1 2023-09-20T19:40:25.3732177 Create's Custom Sounds
043955db25ffe58e7debb9a4f11e41a9571376e6 assets/create/sounds.json

View file

@ -1,2 +1,2 @@
// 1.20.1 2023-08-24T21:57:44.7330415 Create's Recipe Serializer Tags
// 1.20.1 2023-09-20T19:40:25.4461939 Create's Recipe Serializer Tags
0d8718f7383761bc5d7bc45306ed266ebf25dc1d data/create/tags/recipe_serializer/automation_ignore.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-08-25T18:36:29.766244 Create's Generated Registry Entries
// 1.20.1 2023-09-20T19:47:44.9028659 Create's Generated Registry Entries
030ede1044384c4117ac1e491bf5c78bbd2842f5 data/create/damage_type/crush.json
92b0416950ffeb3ba68811e587177c2f8811c2c5 data/create/damage_type/cuckoo_surprise.json
d2a4fdb64f4ba817e13a7b20c73fd1ca34b825fc data/create/damage_type/fan_fire.json

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
{
"parent": "create:backtank",
"parent": "create:foods",
"criteria": {
"0": {
"conditions": {},
@ -13,9 +13,9 @@
"translate": "advancement.create.diving_suit_lava.desc"
},
"frame": "goal",
"hidden": true,
"hidden": false,
"icon": {
"item": "create:copper_diving_helmet",
"item": "create:netherite_diving_helmet",
"nbt": "{Damage:0}"
},
"show_toast": true,

View file

@ -0,0 +1,5 @@
{
"values": [
"create:blaze_burner"
]
}

View file

@ -0,0 +1,7 @@
{
"values": [
"create:lit_blaze_burner",
"minecraft:soul_fire",
"minecraft:soul_campfire"
]
}

View file

@ -0,0 +1,8 @@
{
"values": [
"create:blaze_burner",
"create:lit_blaze_burner",
"minecraft:fire",
"minecraft:campfire"
]
}

View file

@ -0,0 +1,3 @@
{
"values": []
}

View file

@ -0,0 +1,5 @@
{
"values": [
"minecraft:blaze"
]
}

View file

@ -0,0 +1,6 @@
{
"values": [
"minecraft:lava",
"minecraft:flowing_lava"
]
}

View file

@ -0,0 +1,3 @@
{
"values": []
}

View file

@ -0,0 +1,3 @@
{
"values": []
}

View file

@ -0,0 +1,6 @@
{
"values": [
"minecraft:water",
"minecraft:flowing_water"
]
}

View file

@ -288,6 +288,70 @@
"id": "blue_skies:stripped_cherry_log",
"required": false
},
{
"id": "environmental:stripped_cherry_log",
"required": false
},
{
"id": "environmental:stripped_willow_log",
"required": false
},
{
"id": "environmental:stripped_wisteria_log",
"required": false
},
{
"id": "atmospheric:stripped_aspen_log",
"required": false
},
{
"id": "atmospheric:stripped_kousa_log",
"required": false
},
{
"id": "atmospheric:stripped_yucca_log",
"required": false
},
{
"id": "atmospheric:stripped_morado_log",
"required": false
},
{
"id": "atmospheric:stripped_rosewood_log",
"required": false
},
{
"id": "atmospheric:stripped_grimwood_log",
"required": false
},
{
"id": "goodending:stripped_muddy_oak_log",
"required": false
},
{
"id": "goodending:stripped_cypress_log",
"required": false
},
{
"id": "biomemakeover:stripped_blighted_balsa_log",
"required": false
},
{
"id": "biomemakeover:stripped_willow_log",
"required": false
},
{
"id": "biomemakeover:stripped_swamp_cypress_log",
"required": false
},
{
"id": "biomemakeover:stripped_ancient_oak_log",
"required": false
},
{
"id": "infernalexp:stripped_luminous_stem",
"required": false
},
{
"id": "byg:stripped_bulbis_stem",
"required": false

View file

@ -288,6 +288,70 @@
"id": "blue_skies:stripped_cherry_wood",
"required": false
},
{
"id": "environmental:stripped_cherry_wood",
"required": false
},
{
"id": "environmental:stripped_willow_wood",
"required": false
},
{
"id": "environmental:stripped_wisteria_wood",
"required": false
},
{
"id": "atmospheric:stripped_aspen_wood",
"required": false
},
{
"id": "atmospheric:stripped_kousa_wood",
"required": false
},
{
"id": "atmospheric:stripped_yucca_wood",
"required": false
},
{
"id": "atmospheric:stripped_morado_wood",
"required": false
},
{
"id": "atmospheric:stripped_rosewood",
"required": false
},
{
"id": "atmospheric:stripped_grimwood",
"required": false
},
{
"id": "goodending:stripped_muddy_oak_wood",
"required": false
},
{
"id": "goodending:stripped_cypress_wood",
"required": false
},
{
"id": "biomemakeover:stripped_blighted_balsa_wood",
"required": false
},
{
"id": "biomemakeover:stripped_willow_wood",
"required": false
},
{
"id": "biomemakeover:stripped_swamp_cypress_wood",
"required": false
},
{
"id": "biomemakeover:stripped_ancient_oak_wood",
"required": false
},
{
"id": "infernalexp:stripped_luminous_hyphae",
"required": false
},
{
"id": "byg:stripped_bulbis_wood",
"required": false

View file

@ -310,8 +310,10 @@ import net.minecraftforge.common.Tags;
import net.minecraftforge.common.util.ForgeSoundType;
public class AllBlocks {
static { REGISTRATE.useCreativeTab(AllCreativeModeTabs.MAIN_TAB); }
static {
REGISTRATE.setCreativeTab(AllCreativeModeTabs.BASE_CREATIVE_TAB);
}
// Schematics
@ -339,7 +341,7 @@ public class AllBlocks {
public static final BlockEntry<SchematicTableBlock> SCHEMATIC_TABLE =
REGISTRATE.block("schematic_table", SchematicTableBlock::new)
.initialProperties(() -> Blocks.LECTERN)
.properties(p -> p.mapColor(MapColor.PODZOL))
.properties(p -> p.mapColor(MapColor.PODZOL).forceSolidOn())
.transform(axeOrPickaxe())
.blockstate((ctx, prov) -> prov.horizontalBlock(ctx.getEntry(), prov.models()
.getExistingFile(ctx.getId()), 0))
@ -350,7 +352,7 @@ public class AllBlocks {
public static final BlockEntry<ShaftBlock> SHAFT = REGISTRATE.block("shaft", ShaftBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.METAL))
.properties(p -> p.mapColor(MapColor.METAL).forceSolidOn())
.transform(BlockStressDefaults.setNoImpact())
.transform(pickaxeOnly())
.blockstate(BlockStateGen.axisBlockProvider(false))
@ -360,8 +362,7 @@ public class AllBlocks {
public static final BlockEntry<CogWheelBlock> COGWHEEL = REGISTRATE.block("cogwheel", CogWheelBlock::small)
.initialProperties(SharedProperties::stone)
.properties(p -> p.sound(SoundType.WOOD))
.properties(p -> p.mapColor(MapColor.DIRT))
.properties(p -> p.sound(SoundType.WOOD).mapColor(MapColor.DIRT))
.transform(BlockStressDefaults.setNoImpact())
.transform(axeOrPickaxe())
.blockstate(BlockStateGen.axisBlockProvider(false))
@ -373,8 +374,7 @@ public class AllBlocks {
public static final BlockEntry<CogWheelBlock> LARGE_COGWHEEL =
REGISTRATE.block("large_cogwheel", CogWheelBlock::large)
.initialProperties(SharedProperties::stone)
.properties(p -> p.sound(SoundType.WOOD))
.properties(p -> p.mapColor(MapColor.DIRT))
.properties(p -> p.sound(SoundType.WOOD).mapColor(MapColor.DIRT))
.transform(axeOrPickaxe())
.transform(BlockStressDefaults.setNoImpact())
.blockstate(BlockStateGen.axisBlockProvider(false))
@ -440,8 +440,7 @@ public class AllBlocks {
public static final BlockEntry<GearboxBlock> GEARBOX = REGISTRATE.block("gearbox", GearboxBlock::new)
.initialProperties(SharedProperties::stone)
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.mapColor(MapColor.PODZOL))
.properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL))
.transform(BlockStressDefaults.setNoImpact())
.transform(axeOrPickaxe())
.onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(AllSpriteShifts.ANDESITE_CASING)))
@ -454,8 +453,7 @@ public class AllBlocks {
public static final BlockEntry<ClutchBlock> CLUTCH = REGISTRATE.block("clutch", ClutchBlock::new)
.initialProperties(SharedProperties::stone)
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.mapColor(MapColor.PODZOL))
.properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL))
.addLayer(() -> RenderType::cutoutMipped)
.transform(BlockStressDefaults.setNoImpact())
.transform(axeOrPickaxe())
@ -466,8 +464,7 @@ public class AllBlocks {
public static final BlockEntry<GearshiftBlock> GEARSHIFT = REGISTRATE.block("gearshift", GearshiftBlock::new)
.initialProperties(SharedProperties::stone)
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.mapColor(MapColor.PODZOL))
.properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL))
.addLayer(() -> RenderType::cutoutMipped)
.transform(BlockStressDefaults.setNoImpact())
.transform(axeOrPickaxe())
@ -479,8 +476,7 @@ public class AllBlocks {
public static final BlockEntry<ChainDriveBlock> ENCASED_CHAIN_DRIVE =
REGISTRATE.block("encased_chain_drive", ChainDriveBlock::new)
.initialProperties(SharedProperties::stone)
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.mapColor(MapColor.PODZOL))
.properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL))
.transform(BlockStressDefaults.setNoImpact())
.transform(axeOrPickaxe())
.blockstate((c, p) -> new ChainDriveGenerator((state, suffix) -> p.models()
@ -492,8 +488,7 @@ public class AllBlocks {
public static final BlockEntry<ChainGearshiftBlock> ADJUSTABLE_CHAIN_GEARSHIFT =
REGISTRATE.block("adjustable_chain_gearshift", ChainGearshiftBlock::new)
.initialProperties(SharedProperties::stone)
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.mapColor(MapColor.NETHER))
.properties(p -> p.noOcclusion().mapColor(MapColor.NETHER))
.transform(BlockStressDefaults.setNoImpact())
.transform(axeOrPickaxe())
.blockstate((c, p) -> new ChainDriveGenerator((state, suffix) -> {
@ -524,7 +519,7 @@ public class AllBlocks {
public static final BlockEntry<CreativeMotorBlock> CREATIVE_MOTOR =
REGISTRATE.block("creative_motor", CreativeMotorBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.COLOR_PURPLE))
.properties(p -> p.mapColor(MapColor.COLOR_PURPLE).forceSolidOn())
.tag(AllBlockTags.SAFE_NBT.tag)
.transform(pickaxeOnly())
.blockstate(new CreativeMotorGenerator()::generate)
@ -537,8 +532,7 @@ public class AllBlocks {
public static final BlockEntry<WaterWheelBlock> WATER_WHEEL = REGISTRATE.block("water_wheel", WaterWheelBlock::new)
.initialProperties(SharedProperties::wooden)
.properties(p -> p.mapColor(MapColor.DIRT))
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.noOcclusion().mapColor(MapColor.DIRT))
.transform(axeOrPickaxe())
.blockstate(
(c, p) -> BlockStateGen.directionalBlockIgnoresWaterlogged(c, p, s -> AssetLookup.partialBaseModel(c, p)))
@ -552,8 +546,7 @@ public class AllBlocks {
public static final BlockEntry<LargeWaterWheelBlock> LARGE_WATER_WHEEL =
REGISTRATE.block("large_water_wheel", LargeWaterWheelBlock::new)
.initialProperties(SharedProperties::wooden)
.properties(p -> p.mapColor(MapColor.DIRT))
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.noOcclusion().mapColor(MapColor.DIRT))
.transform(axeOrPickaxe())
.blockstate((c, p) -> axisBlock(c, p,
s -> s.getValue(LargeWaterWheelBlock.EXTENSION) ? AssetLookup.partialBaseModel(c, p, "extension")
@ -569,8 +562,7 @@ public class AllBlocks {
.initialProperties(SharedProperties::wooden)
.blockstate((c, p) -> p.getVariantBuilder(c.get())
.forAllStatesExcept(BlockStateGen.mapToAir(p), WaterWheelStructuralBlock.FACING))
.properties(p -> p.mapColor(MapColor.DIRT))
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.noOcclusion().mapColor(MapColor.DIRT))
.transform(axeOrPickaxe())
.lang("Large Water Wheel")
.register();
@ -675,8 +667,7 @@ public class AllBlocks {
public static final BlockEntry<MechanicalPressBlock> MECHANICAL_PRESS =
REGISTRATE.block("mechanical_press", MechanicalPressBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.PODZOL))
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL))
.transform(axeOrPickaxe())
.blockstate(BlockStateGen.horizontalBlockProvider(true))
.transform(BlockStressDefaults.setImpact(8.0))
@ -687,8 +678,7 @@ public class AllBlocks {
public static final BlockEntry<MechanicalMixerBlock> MECHANICAL_MIXER =
REGISTRATE.block("mechanical_mixer", MechanicalMixerBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.STONE))
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.noOcclusion().mapColor(MapColor.STONE))
.transform(axeOrPickaxe())
.blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p)))
.addLayer(() -> RenderType::cutoutMipped)
@ -699,8 +689,7 @@ public class AllBlocks {
public static final BlockEntry<BasinBlock> BASIN = REGISTRATE.block("basin", BasinBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.mapColor(MapColor.COLOR_GRAY).sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly())
.blockstate(new BasinGenerator()::generate)
.addLayer(() -> RenderType::cutoutMipped)
@ -712,11 +701,10 @@ public class AllBlocks {
public static final BlockEntry<BlazeBurnerBlock> BLAZE_BURNER =
REGISTRATE.block("blaze_burner", BlazeBurnerBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY))
.properties(p -> p.lightLevel(BlazeBurnerBlock::getLight))
.properties(p -> p.mapColor(MapColor.COLOR_GRAY).lightLevel(BlazeBurnerBlock::getLight))
.transform(pickaxeOnly())
.addLayer(() -> RenderType::cutoutMipped)
.tag(AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag)
.tag(AllBlockTags.FAN_PROCESSING_CATALYSTS_BLASTING.tag, AllBlockTags.FAN_PROCESSING_CATALYSTS_SMOKING.tag, AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag)
.loot((lt, block) -> lt.add(block, BlazeBurnerBlock.buildLootTable()))
.blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p)))
.onRegister(movementBehaviour(new BlazeBurnerMovementBehaviour()))
@ -729,11 +717,10 @@ public class AllBlocks {
public static final BlockEntry<LitBlazeBurnerBlock> LIT_BLAZE_BURNER =
REGISTRATE.block("lit_blaze_burner", LitBlazeBurnerBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.COLOR_LIGHT_GRAY))
.properties(p -> p.lightLevel(LitBlazeBurnerBlock::getLight))
.properties(p -> p.mapColor(MapColor.COLOR_LIGHT_GRAY).lightLevel(LitBlazeBurnerBlock::getLight))
.transform(pickaxeOnly())
.addLayer(() -> RenderType::cutoutMipped)
.tag(AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag)
.tag(AllBlockTags.FAN_PROCESSING_CATALYSTS_HAUNTING.tag, AllBlockTags.FAN_PROCESSING_CATALYSTS_SMOKING.tag, AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag)
.loot((lt, block) -> lt.dropOther(block, AllItems.EMPTY_BLAZE_BURNER.get()))
.blockstate((c, p) -> p.getVariantBuilder(c.get())
.forAllStates(state -> ConfiguredModel.builder()
@ -758,8 +745,7 @@ public class AllBlocks {
public static final BlockEntry<EjectorBlock> WEIGHTED_EJECTOR =
REGISTRATE.block("weighted_ejector", EjectorBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY))
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.noOcclusion().mapColor(MapColor.COLOR_GRAY))
.transform(axeOrPickaxe())
.blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p), 180))
.transform(BlockStressDefaults.setImpact(2.0))
@ -769,10 +755,8 @@ public class AllBlocks {
.register();
public static final BlockEntry<ChuteBlock> CHUTE = REGISTRATE.block("chute", ChuteBlock::new)
.addLayer(() -> RenderType::cutoutMipped)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.mapColor(MapColor.COLOR_GRAY).sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly())
.addLayer(() -> RenderType::cutoutMipped)
.blockstate(new ChuteGenerator()::generate)
@ -781,12 +765,12 @@ public class AllBlocks {
.register();
public static final BlockEntry<SmartChuteBlock> SMART_CHUTE = REGISTRATE.block("smart_chute", SmartChuteBlock::new)
.addLayer(() -> RenderType::cutoutMipped)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.noOcclusion())
.properties(p -> p.isRedstoneConductor((level, pos, state) -> false))
.properties(p -> p.mapColor(MapColor.COLOR_GRAY)
.sound(SoundType.NETHERITE_BLOCK)
.noOcclusion()
.isRedstoneConductor((level, pos, state) -> false))
.addLayer(() -> RenderType::cutoutMipped)
.transform(pickaxeOnly())
.blockstate((c, p) -> BlockStateGen.simpleBlock(c, p, AssetLookup.forPowered(c, p)))
.item()
@ -835,6 +819,7 @@ public class AllBlocks {
public static final BlockEntry<FluidPipeBlock> FLUID_PIPE = REGISTRATE.block("fluid_pipe", FluidPipeBlock::new)
.initialProperties(SharedProperties::copperMetal)
.properties(p -> p.forceSolidOn())
.transform(pickaxeOnly())
.blockstate(BlockStateGen.pipe())
.onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new))
@ -845,8 +830,7 @@ public class AllBlocks {
public static final BlockEntry<EncasedPipeBlock> ENCASED_FLUID_PIPE =
REGISTRATE.block("encased_fluid_pipe", p -> new EncasedPipeBlock(p, AllBlocks.COPPER_CASING::get))
.initialProperties(SharedProperties::copperMetal)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_LIGHT_GRAY))
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.noOcclusion().mapColor(MapColor.TERRACOTTA_LIGHT_GRAY))
.transform(axeOrPickaxe())
.blockstate(BlockStateGen.encasedPipe())
.onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(AllSpriteShifts.COPPER_CASING)))
@ -860,6 +844,7 @@ public class AllBlocks {
public static final BlockEntry<GlassFluidPipeBlock> GLASS_FLUID_PIPE =
REGISTRATE.block("glass_fluid_pipe", GlassFluidPipeBlock::new)
.initialProperties(SharedProperties::copperMetal)
.properties(p -> p.forceSolidOn())
.addLayer(() -> RenderType::cutoutMipped)
.transform(pickaxeOnly())
.blockstate((c, p) -> {
@ -935,8 +920,7 @@ public class AllBlocks {
public static final BlockEntry<FluidTankBlock> FLUID_TANK = REGISTRATE.block("fluid_tank", FluidTankBlock::regular)
.initialProperties(SharedProperties::copperMetal)
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.isRedstoneConductor((p1, p2, p3) -> true))
.properties(p -> p.noOcclusion().isRedstoneConductor((p1, p2, p3) -> true))
.transform(pickaxeOnly())
.blockstate(new FluidTankGenerator()::generate)
.onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::standard))
@ -950,8 +934,7 @@ public class AllBlocks {
public static final BlockEntry<FluidTankBlock> CREATIVE_FLUID_TANK =
REGISTRATE.block("creative_fluid_tank", FluidTankBlock::creative)
.initialProperties(SharedProperties::copperMetal)
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.mapColor(MapColor.COLOR_PURPLE))
.properties(p -> p.noOcclusion().mapColor(MapColor.COLOR_PURPLE))
.transform(pickaxeOnly())
.tag(AllBlockTags.SAFE_NBT.tag)
.blockstate(new FluidTankGenerator("creative_")::generate)
@ -1030,7 +1013,7 @@ public class AllBlocks {
public static final BlockEntry<WhistleExtenderBlock> STEAM_WHISTLE_EXTENSION =
REGISTRATE.block("steam_whistle_extension", WhistleExtenderBlock::new)
.initialProperties(SharedProperties::copperMetal)
.properties(p -> p.mapColor(MapColor.GOLD))
.properties(p -> p.mapColor(MapColor.GOLD).forceSolidOn())
.transform(pickaxeOnly())
.blockstate(BlockStateGen.whistleExtender())
.register();
@ -1038,7 +1021,7 @@ public class AllBlocks {
public static final BlockEntry<PoweredShaftBlock> POWERED_SHAFT =
REGISTRATE.block("powered_shaft", PoweredShaftBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.METAL))
.properties(p -> p.mapColor(MapColor.METAL).forceSolidOn())
.transform(pickaxeOnly())
.blockstate(BlockStateGen.axisBlockProvider(false))
.loot((lt, block) -> lt.dropOther(block, AllBlocks.SHAFT.get()))
@ -1065,8 +1048,7 @@ public class AllBlocks {
public static final BlockEntry<PistonExtensionPoleBlock> PISTON_EXTENSION_POLE =
REGISTRATE.block("piston_extension_pole", PistonExtensionPoleBlock::new)
.initialProperties(() -> Blocks.PISTON_HEAD)
.properties(p -> p.sound(SoundType.SCAFFOLDING))
.properties(p -> p.mapColor(MapColor.DIRT))
.properties(p -> p.sound(SoundType.SCAFFOLDING).mapColor(MapColor.DIRT).forceSolidOn())
.transform(axeOrPickaxe())
.blockstate(BlockStateGen.directionalBlockProviderIgnoresWaterlogged(false))
.simpleItem()
@ -1086,8 +1068,7 @@ public class AllBlocks {
public static final BlockEntry<GantryCarriageBlock> GANTRY_CARRIAGE =
REGISTRATE.block("gantry_carriage", GantryCarriageBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.PODZOL))
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL))
.transform(axeOrPickaxe())
.blockstate(BlockStateGen.directionalAxisBlockProvider())
.item()
@ -1097,7 +1078,7 @@ public class AllBlocks {
public static final BlockEntry<GantryShaftBlock> GANTRY_SHAFT =
REGISTRATE.block("gantry_shaft", GantryShaftBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.NETHER))
.properties(p -> p.mapColor(MapColor.NETHER).forceSolidOn())
.transform(axeOrPickaxe())
.blockstate((c, p) -> p.directionalBlock(c.get(), s -> {
boolean isPowered = s.getValue(GantryShaftBlock.POWERED);
@ -1192,8 +1173,7 @@ public class AllBlocks {
public static final BlockEntry<CartAssemblerBlock> CART_ASSEMBLER =
REGISTRATE.block("cart_assembler", CartAssemblerBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY))
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.noOcclusion().mapColor(MapColor.COLOR_GRAY))
.transform(axeOrPickaxe())
.blockstate(BlockStateGen.cartAssembler())
.addLayer(() -> RenderType::cutoutMipped)
@ -1349,8 +1329,7 @@ public class AllBlocks {
public static final BlockEntry<ElevatorContactBlock> ELEVATOR_CONTACT =
REGISTRATE.block("elevator_contact", ElevatorContactBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW))
.properties(p -> p.lightLevel(ElevatorContactBlock::getLight))
.properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW).lightLevel(ElevatorContactBlock::getLight))
.transform(axeOrPickaxe())
.blockstate((c, p) -> p.directionalBlock(c.get(), state -> {
Boolean calling = state.getValue(ElevatorContactBlock.CALLING);
@ -1367,7 +1346,7 @@ public class AllBlocks {
public static final BlockEntry<HarvesterBlock> MECHANICAL_HARVESTER =
REGISTRATE.block("mechanical_harvester", HarvesterBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.METAL))
.properties(p -> p.mapColor(MapColor.METAL).forceSolidOn())
.transform(axeOrPickaxe())
.onRegister(movementBehaviour(new HarvesterMovementBehaviour()))
.blockstate(BlockStateGen.horizontalBlockProvider(true))
@ -1380,7 +1359,7 @@ public class AllBlocks {
public static final BlockEntry<PloughBlock> MECHANICAL_PLOUGH =
REGISTRATE.block("mechanical_plough", PloughBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY))
.properties(p -> p.mapColor(MapColor.COLOR_GRAY).forceSolidOn())
.transform(axeOrPickaxe())
.onRegister(movementBehaviour(new PloughMovementBehaviour()))
.blockstate(BlockStateGen.horizontalBlockProvider(false))
@ -1405,8 +1384,8 @@ public class AllBlocks {
public static final BlockEntry<SailBlock> SAIL_FRAME = REGISTRATE.block("sail_frame", p -> SailBlock.frame(p))
.initialProperties(SharedProperties::wooden)
.properties(p -> p.mapColor(MapColor.DIRT))
.properties(p -> p.sound(SoundType.SCAFFOLDING)
.properties(p -> p.mapColor(MapColor.DIRT)
.sound(SoundType.SCAFFOLDING)
.noOcclusion())
.transform(axeOnly())
.blockstate(BlockStateGen.directionalBlockProvider(false))
@ -1419,8 +1398,8 @@ public class AllBlocks {
public static final BlockEntry<SailBlock> SAIL =
REGISTRATE.block("white_sail", p -> SailBlock.withCanvas(p, DyeColor.WHITE))
.initialProperties(SharedProperties::wooden)
.properties(p -> p.mapColor(MapColor.SNOW))
.properties(p -> p.sound(SoundType.SCAFFOLDING)
.properties(p -> p.mapColor(MapColor.SNOW)
.sound(SoundType.SCAFFOLDING)
.noOcclusion())
.transform(axeOnly())
.blockstate(BlockStateGen.directionalBlockProvider(false))
@ -1437,8 +1416,8 @@ public class AllBlocks {
String colourName = colour.getSerializedName();
return REGISTRATE.block(colourName + "_sail", p -> SailBlock.withCanvas(p, colour))
.initialProperties(SharedProperties::wooden)
.properties(p -> p.mapColor(colour.getMapColor()))
.properties(p -> p.sound(SoundType.SCAFFOLDING)
.properties(p -> p.mapColor(colour.getMapColor())
.sound(SoundType.SCAFFOLDING)
.noOcclusion())
.transform(axeOnly())
.blockstate((c, p) -> p.directionalBlock(c.get(), p.models()
@ -1460,8 +1439,7 @@ public class AllBlocks {
.register();
public static final BlockEntry<CasingBlock> COPPER_CASING = REGISTRATE.block("copper_casing", CasingBlock::new)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_LIGHT_GRAY))
.properties(p -> p.sound(SoundType.COPPER))
.properties(p -> p.mapColor(MapColor.TERRACOTTA_LIGHT_GRAY).sound(SoundType.COPPER))
.transform(BuilderTransformers.casing(() -> AllSpriteShifts.COPPER_CASING))
.register();
@ -1483,8 +1461,7 @@ public class AllBlocks {
public static final BlockEntry<MechanicalCrafterBlock> MECHANICAL_CRAFTER =
REGISTRATE.block("mechanical_crafter", MechanicalCrafterBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW))
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.noOcclusion().mapColor(MapColor.TERRACOTTA_YELLOW))
.transform(axeOrPickaxe())
.blockstate(BlockStateGen.horizontalBlockProvider(true))
.transform(BlockStressDefaults.setImpact(2.0))
@ -1509,8 +1486,7 @@ public class AllBlocks {
public static final BlockEntry<FlywheelBlock> FLYWHEEL = REGISTRATE.block("flywheel", FlywheelBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW))
.properties(BlockBehaviour.Properties::noOcclusion)
.properties(p -> p.noOcclusion().mapColor(MapColor.TERRACOTTA_YELLOW))
.transform(axeOrPickaxe())
.transform(BlockStressDefaults.setNoImpact())
.blockstate(BlockStateGen.axisBlockProvider(true))
@ -1551,7 +1527,8 @@ public class AllBlocks {
.properties(p -> p.mapColor(MapColor.METAL)
.strength(0.8F)
.sound(SoundType.METAL)
.noOcclusion())
.noOcclusion()
.forceSolidOn())
.addLayer(() -> RenderType::cutoutMipped)
.transform(pickaxeOnly())
.onRegister(CreateRegistrate.blockModel(() -> TrackModel::new))
@ -1578,15 +1555,13 @@ public class AllBlocks {
public static final BlockEntry<CasingBlock> RAILWAY_CASING = REGISTRATE.block("railway_casing", CasingBlock::new)
.transform(BuilderTransformers.layeredCasing(() -> AllSpriteShifts.RAILWAY_CASING_SIDE,
() -> AllSpriteShifts.RAILWAY_CASING))
.properties(p -> p.mapColor(MapColor.TERRACOTTA_CYAN))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.mapColor(MapColor.TERRACOTTA_CYAN).sound(SoundType.NETHERITE_BLOCK))
.lang("Train Casing")
.register();
public static final BlockEntry<StationBlock> TRACK_STATION = REGISTRATE.block("track_station", StationBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.PODZOL))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.mapColor(MapColor.PODZOL).sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly())
.blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
.onRegister(assignDataBehaviour(new StationSummaryDisplaySource(), "station_summary"))
@ -1598,9 +1573,9 @@ public class AllBlocks {
public static final BlockEntry<SignalBlock> TRACK_SIGNAL = REGISTRATE.block("track_signal", SignalBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.PODZOL))
.properties(p -> p.noOcclusion())
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.mapColor(MapColor.PODZOL)
.noOcclusion()
.sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly())
.blockstate((c, p) -> p.getVariantBuilder(c.get())
.forAllStates(state -> ConfiguredModel.builder()
@ -1615,9 +1590,9 @@ public class AllBlocks {
public static final BlockEntry<TrackObserverBlock> TRACK_OBSERVER =
REGISTRATE.block("track_observer", TrackObserverBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.PODZOL))
.properties(p -> p.noOcclusion())
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.mapColor(MapColor.PODZOL)
.noOcclusion()
.sound(SoundType.NETHERITE_BLOCK))
.blockstate((c, p) -> BlockStateGen.simpleBlock(c, p, AssetLookup.forPowered(c, p)))
.transform(pickaxeOnly())
.onRegister(assignDataBehaviour(new ObservedTrainNameSource(), "observed_train_name"))
@ -1640,8 +1615,7 @@ public class AllBlocks {
public static final BlockEntry<ControlsBlock> TRAIN_CONTROLS = REGISTRATE.block("controls", ControlsBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN).sound(SoundType.NETHERITE_BLOCK))
.addLayer(() -> RenderType::cutoutMipped)
.transform(pickaxeOnly())
.blockstate((c, p) -> p.horizontalBlock(c.get(),
@ -1656,8 +1630,7 @@ public class AllBlocks {
public static final BlockEntry<ItemVaultBlock> ITEM_VAULT = REGISTRATE.block("item_vault", ItemVaultBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BLUE))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BLUE).sound(SoundType.NETHERITE_BLOCK)
.explosionResistance(1200))
.transform(pickaxeOnly())
.blockstate((c, p) -> p.getVariantBuilder(c.get())
@ -1742,8 +1715,7 @@ public class AllBlocks {
public static final BlockEntry<SmartObserverBlock> SMART_OBSERVER =
REGISTRATE.block("content_observer", SmartObserverBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN))
.properties(p -> p.noOcclusion())
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN).noOcclusion())
.transform(axeOrPickaxe())
.blockstate(new SmartObserverGenerator()::generate)
.onRegister(assignDataBehaviour(new ItemCountDisplaySource(), "count_items"))
@ -1758,8 +1730,7 @@ public class AllBlocks {
public static final BlockEntry<ThresholdSwitchBlock> THRESHOLD_SWITCH =
REGISTRATE.block("stockpile_switch", ThresholdSwitchBlock::new)
.initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN))
.properties(p -> p.noOcclusion())
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN).noOcclusion())
.transform(axeOrPickaxe())
.blockstate(new ThresholdSwitchGenerator()::generate)
.onRegister(assignDataBehaviour(new FillLevelDisplaySource(), "fill_level"))
@ -1802,8 +1773,7 @@ public class AllBlocks {
public static final BlockEntry<NixieTubeBlock> ORANGE_NIXIE_TUBE =
REGISTRATE.block("nixie_tube", p -> new NixieTubeBlock(p, DyeColor.ORANGE))
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.lightLevel($ -> 5))
.properties(p -> p.mapColor(DyeColor.ORANGE))
.properties(p -> p.lightLevel($ -> 5).mapColor(DyeColor.ORANGE).forceSolidOn())
.transform(pickaxeOnly())
.blockstate(new NixieTubeGenerator()::generate)
.addLayer(() -> RenderType::translucent)
@ -1817,8 +1787,7 @@ public class AllBlocks {
String colourName = colour.getSerializedName();
return REGISTRATE.block(colourName + "_nixie_tube", p -> new NixieTubeBlock(p, colour))
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(colour))
.properties(p -> p.lightLevel($ -> 5))
.properties(p -> p.lightLevel($ -> 5).mapColor(colour).forceSolidOn())
.transform(pickaxeOnly())
.blockstate(new NixieTubeGenerator()::generate)
.loot((p, b) -> p.dropOther(b, ORANGE_NIXIE_TUBE.get()))
@ -1844,7 +1813,7 @@ public class AllBlocks {
public static final BlockEntry<RedstoneLinkBlock> REDSTONE_LINK =
REGISTRATE.block("redstone_link", RedstoneLinkBlock::new)
.initialProperties(SharedProperties::wooden)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN))
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN).forceSolidOn())
.transform(axeOrPickaxe())
.tag(AllBlockTags.BRITTLE.tag, AllBlockTags.SAFE_NBT.tag)
.blockstate(new RedstoneLinkGenerator()::generate)
@ -1866,6 +1835,7 @@ public class AllBlocks {
public static final BlockEntry<PlacardBlock> PLACARD = REGISTRATE.block("placard", PlacardBlock::new)
.initialProperties(SharedProperties::copperMetal)
.properties(p -> p.forceSolidOn())
.transform(pickaxeOnly())
.blockstate((c, p) -> p.horizontalFaceBlock(c.get(), AssetLookup.standardModel(c, p)))
.simpleItem()
@ -1935,14 +1905,14 @@ public class AllBlocks {
public static final BlockEntry<PeculiarBellBlock> PECULIAR_BELL =
REGISTRATE.block("peculiar_bell", PeculiarBellBlock::new)
.properties(p -> p.mapColor(MapColor.GOLD))
.properties(p -> p.mapColor(MapColor.GOLD).forceSolidOn())
.transform(BuilderTransformers.bell())
.onRegister(movementBehaviour(new BellMovementBehaviour()))
.register();
public static final BlockEntry<HauntedBellBlock> HAUNTED_BELL =
REGISTRATE.block("haunted_bell", HauntedBellBlock::new)
.properties(p -> p.mapColor(MapColor.SAND))
.properties(p -> p.mapColor(MapColor.SAND).forceSolidOn())
.transform(BuilderTransformers.bell())
.onRegister(movementBehaviour(new HauntedBellMovementBehaviour()))
.register();
@ -1951,8 +1921,7 @@ public class AllBlocks {
String colourName = colour.getSerializedName();
return REGISTRATE.block(colourName + "_toolbox", p -> new ToolboxBlock(p, colour))
.initialProperties(SharedProperties::wooden)
.properties(p -> p.sound(SoundType.WOOD))
.properties(p -> p.mapColor(colour))
.properties(p -> p.sound(SoundType.WOOD).mapColor(colour).forceSolidOn())
.addLayer(() -> RenderType::cutoutMipped)
.loot((lt, block) -> {
Builder builder = LootTable.lootTable();
@ -1984,6 +1953,7 @@ public class AllBlocks {
public static final BlockEntry<ClipboardBlock> CLIPBOARD = REGISTRATE.block("clipboard", ClipboardBlock::new)
.initialProperties(SharedProperties::wooden)
.properties(p -> p.forceSolidOn())
.transform(axeOrPickaxe())
.tag(AllBlockTags.SAFE_NBT.tag)
.blockstate((c, p) -> p.horizontalFaceBlock(c.get(),
@ -1996,8 +1966,10 @@ public class AllBlocks {
.register();
// Materials
static { REGISTRATE.useCreativeTab(AllCreativeModeTabs.BUILDING_BLOCKS_TAB); }
static {
REGISTRATE.setCreativeTab(AllCreativeModeTabs.PALETTES_CREATIVE_TAB);
}
public static final BlockEntry<MetalLadderBlock> ANDESITE_LADDER =
REGISTRATE.block("andesite_ladder", MetalLadderBlock::new)
@ -2047,10 +2019,9 @@ public class AllBlocks {
public static final BlockEntry<GirderBlock> METAL_GIRDER = REGISTRATE.block("metal_girder", GirderBlock::new)
.initialProperties(SharedProperties::softMetal)
.blockstate(GirderBlockStateGenerator::blockState)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.mapColor(MapColor.COLOR_GRAY).sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly())
.blockstate(GirderBlockStateGenerator::blockState)
.onRegister(CreateRegistrate.blockModel(() -> ConnectedGirderModel::new))
.item()
.transform(customItemModel())
@ -2059,10 +2030,9 @@ public class AllBlocks {
public static final BlockEntry<GirderEncasedShaftBlock> METAL_GIRDER_ENCASED_SHAFT =
REGISTRATE.block("metal_girder_encased_shaft", GirderEncasedShaftBlock::new)
.initialProperties(SharedProperties::softMetal)
.blockstate(GirderBlockStateGenerator::blockStateWithShaft)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.mapColor(MapColor.COLOR_GRAY).sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly())
.blockstate(GirderBlockStateGenerator::blockStateWithShaft)
.loot((p, b) -> p.add(b, p.createSingleItemTable(METAL_GIRDER.get())
.withPool(p.applyExplosionCondition(SHAFT.get(), LootPool.lootPool()
.setRolls(ConstantValue.exactly(1.0F))
@ -2081,6 +2051,7 @@ public class AllBlocks {
public static final BlockEntry<CopycatStepBlock> COPYCAT_STEP =
REGISTRATE.block("copycat_step", CopycatStepBlock::new)
.properties(p -> p.forceSolidOn())
.transform(BuilderTransformers.copycat())
.onRegister(CreateRegistrate.blockModel(() -> CopycatStepModel::new))
.item()
@ -2203,8 +2174,8 @@ public class AllBlocks {
public static final BlockEntry<Block> ZINC_ORE = REGISTRATE.block("zinc_ore", Block::new)
.initialProperties(() -> Blocks.GOLD_ORE)
.properties(p -> p.mapColor(MapColor.METAL))
.properties(p -> p.requiresCorrectToolForDrops()
.properties(p -> p.mapColor(MapColor.METAL)
.requiresCorrectToolForDrops()
.sound(SoundType.STONE))
.transform(pickaxeOnly())
.loot((lt, b) -> lt.add(b,
@ -2220,8 +2191,8 @@ public class AllBlocks {
public static final BlockEntry<Block> DEEPSLATE_ZINC_ORE = REGISTRATE.block("deepslate_zinc_ore", Block::new)
.initialProperties(() -> Blocks.DEEPSLATE_GOLD_ORE)
.properties(p -> p.mapColor(MapColor.STONE))
.properties(p -> p.requiresCorrectToolForDrops()
.properties(p -> p.mapColor(MapColor.STONE)
.requiresCorrectToolForDrops()
.sound(SoundType.DEEPSLATE))
.transform(pickaxeOnly())
.loot((lt, b) -> lt.add(b,
@ -2237,8 +2208,7 @@ public class AllBlocks {
public static final BlockEntry<Block> RAW_ZINC_BLOCK = REGISTRATE.block("raw_zinc_block", Block::new)
.initialProperties(() -> Blocks.RAW_GOLD_BLOCK)
.properties(p -> p.mapColor(MapColor.GLOW_LICHEN))
.properties(p -> p.requiresCorrectToolForDrops())
.properties(p -> p.mapColor(MapColor.GLOW_LICHEN).requiresCorrectToolForDrops())
.transform(pickaxeOnly())
.tag(Tags.Blocks.STORAGE_BLOCKS)
.tag(BlockTags.NEEDS_IRON_TOOL)
@ -2250,8 +2220,7 @@ public class AllBlocks {
public static final BlockEntry<Block> ZINC_BLOCK = REGISTRATE.block("zinc_block", Block::new)
.initialProperties(() -> Blocks.IRON_BLOCK)
.properties(p -> p.mapColor(MapColor.GLOW_LICHEN))
.properties(p -> p.requiresCorrectToolForDrops())
.properties(p -> p.mapColor(MapColor.GLOW_LICHEN).requiresCorrectToolForDrops())
.transform(pickaxeOnly())
.tag(BlockTags.NEEDS_IRON_TOOL)
.tag(Tags.Blocks.STORAGE_BLOCKS)
@ -2264,8 +2233,7 @@ public class AllBlocks {
public static final BlockEntry<Block> ANDESITE_ALLOY_BLOCK = REGISTRATE.block("andesite_alloy_block", Block::new)
.initialProperties(() -> Blocks.ANDESITE)
.properties(p -> p.mapColor(MapColor.STONE))
.properties(p -> p.requiresCorrectToolForDrops())
.properties(p -> p.mapColor(MapColor.STONE).requiresCorrectToolForDrops())
.transform(pickaxeOnly())
.blockstate(simpleCubeAll("andesite_block"))
.tag(Tags.Blocks.STORAGE_BLOCKS)
@ -2277,9 +2245,9 @@ public class AllBlocks {
public static final BlockEntry<Block> INDUSTRIAL_IRON_BLOCK = REGISTRATE.block("industrial_iron_block", Block::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.requiresCorrectToolForDrops())
.properties(p -> p.mapColor(MapColor.COLOR_GRAY)
.sound(SoundType.NETHERITE_BLOCK)
.requiresCorrectToolForDrops())
.transform(pickaxeOnly())
.blockstate((c, p) -> p.simpleBlock(c.get(), p.models()
.cubeColumn(c.getName(), p.modLoc("block/industrial_iron_block"),
@ -2293,8 +2261,7 @@ public class AllBlocks {
public static final BlockEntry<Block> BRASS_BLOCK = REGISTRATE.block("brass_block", Block::new)
.initialProperties(() -> Blocks.IRON_BLOCK)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW))
.properties(p -> p.requiresCorrectToolForDrops())
.properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW).requiresCorrectToolForDrops())
.transform(pickaxeOnly())
.blockstate(simpleCubeAll("brass_block"))
.tag(BlockTags.NEEDS_IRON_TOOL)
@ -2309,12 +2276,12 @@ public class AllBlocks {
public static final BlockEntry<ExperienceBlock> EXPERIENCE_BLOCK =
REGISTRATE.block("experience_block", ExperienceBlock::new)
.initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.PLANT))
.properties(p -> p.sound(new ForgeSoundType(1, .5f, () -> SoundEvents.AMETHYST_BLOCK_BREAK,
() -> SoundEvents.AMETHYST_BLOCK_STEP, () -> SoundEvents.AMETHYST_BLOCK_PLACE,
() -> SoundEvents.AMETHYST_BLOCK_HIT, () -> SoundEvents.AMETHYST_BLOCK_FALL)))
.properties(p -> p.requiresCorrectToolForDrops())
.properties(p -> p.lightLevel(s -> 15))
.properties(p -> p.mapColor(MapColor.PLANT)
.sound(new ForgeSoundType(1, .5f, () -> SoundEvents.AMETHYST_BLOCK_BREAK,
() -> SoundEvents.AMETHYST_BLOCK_STEP, () -> SoundEvents.AMETHYST_BLOCK_PLACE,
() -> SoundEvents.AMETHYST_BLOCK_HIT, () -> SoundEvents.AMETHYST_BLOCK_FALL))
.requiresCorrectToolForDrops()
.lightLevel(s -> 15))
.blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.standardModel(c, p)))
.transform(pickaxeOnly())
.lang("Block of Experience")
@ -2343,8 +2310,7 @@ public class AllBlocks {
public static final BlockEntry<Block> ROSE_QUARTZ_TILES = REGISTRATE.block("rose_quartz_tiles", Block::new)
.initialProperties(() -> Blocks.DEEPSLATE)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_PINK))
.properties(p -> p.requiresCorrectToolForDrops())
.properties(p -> p.mapColor(MapColor.TERRACOTTA_PINK).requiresCorrectToolForDrops())
.transform(pickaxeOnly())
.blockstate(simpleCubeAll("palettes/rose_quartz_tiles"))
.recipe((c, p) -> p.stonecutting(DataIngredient.items(AllItems.POLISHED_ROSE_QUARTZ.get()),
@ -2355,8 +2321,7 @@ public class AllBlocks {
public static final BlockEntry<Block> SMALL_ROSE_QUARTZ_TILES =
REGISTRATE.block("small_rose_quartz_tiles", Block::new)
.initialProperties(() -> Blocks.DEEPSLATE)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_PINK))
.properties(p -> p.requiresCorrectToolForDrops())
.properties(p -> p.mapColor(MapColor.TERRACOTTA_PINK).requiresCorrectToolForDrops())
.transform(pickaxeOnly())
.blockstate(simpleCubeAll("palettes/small_rose_quartz_tiles"))
.recipe((c, p) -> p.stonecutting(DataIngredient.items(AllItems.POLISHED_ROSE_QUARTZ.get()),

View file

@ -7,13 +7,14 @@ import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.apache.commons.lang3.mutable.MutableObject;
import com.simibubi.create.content.contraptions.actors.seat.SeatBlock;
import com.simibubi.create.content.decoration.palettes.AllPaletteBlocks;
import com.simibubi.create.content.equipment.armor.BacktankUtil;
import com.simibubi.create.content.equipment.toolbox.ToolboxBlock;
import com.simibubi.create.content.kinetics.crank.ValveHandleBlock;
import com.simibubi.create.foundation.data.CreateRegistrate;
import com.simibubi.create.foundation.item.TagDependentIngredientItem;
import com.tterrag.registrate.util.entry.BlockEntry;
import com.tterrag.registrate.util.entry.ItemEntry;
@ -25,11 +26,11 @@ import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import net.createmod.catnip.utility.lang.Components;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.CreativeModeTab.DisplayItemsGenerator;
@ -53,45 +54,63 @@ import net.minecraftforge.registries.RegistryObject;
@EventBusSubscriber(bus = Bus.MOD)
public class AllCreativeModeTabs {
private static final DeferredRegister<CreativeModeTab> TAB_REGISTER =
private static final DeferredRegister<CreativeModeTab> REGISTER =
DeferredRegister.create(Registries.CREATIVE_MODE_TAB, Create.ID);
public static final RegistryObject<CreativeModeTab> MAIN_TAB = TAB_REGISTER.register("base",
public static final RegistryObject<CreativeModeTab> BASE_CREATIVE_TAB = REGISTER.register("base",
() -> CreativeModeTab.builder()
.title(Component.translatable("itemGroup.create.base"))
.title(Components.translatable("itemGroup.create.base"))
.withTabsBefore(CreativeModeTabs.SPAWN_EGGS)
.icon(() -> AllBlocks.COGWHEEL.asStack())
.displayItems(new RegistrateDisplayItemsGenerator(true))
.displayItems(new RegistrateDisplayItemsGenerator(true, AllCreativeModeTabs.BASE_CREATIVE_TAB))
.build());
public static final RegistryObject<CreativeModeTab> BUILDING_BLOCKS_TAB = TAB_REGISTER.register("palettes",
public static final RegistryObject<CreativeModeTab> PALETTES_CREATIVE_TAB = REGISTER.register("palettes",
() -> CreativeModeTab.builder()
.title(Component.translatable("itemGroup.create.palettes"))
.withTabsBefore(MAIN_TAB.getKey())
.title(Components.translatable("itemGroup.create.palettes"))
.withTabsBefore(BASE_CREATIVE_TAB.getKey())
.icon(() -> AllPaletteBlocks.ORNATE_IRON_WINDOW.asStack())
.displayItems(new RegistrateDisplayItemsGenerator(false))
.displayItems(new RegistrateDisplayItemsGenerator(false, AllCreativeModeTabs.PALETTES_CREATIVE_TAB))
.build());
public static void register(IEventBus modEventBus) {
TAB_REGISTER.register(modEventBus);
REGISTER.register(modEventBus);
}
public static CreativeModeTab getBaseTab() {
return MAIN_TAB.get();
}
private static class RegistrateDisplayItemsGenerator implements DisplayItemsGenerator {
private static final Predicate<Item> IS_ITEM_3D_PREDICATE;
public static CreativeModeTab getPalettesTab() {
return BUILDING_BLOCKS_TAB.get();
}
public static class RegistrateDisplayItemsGenerator implements DisplayItemsGenerator {
private final boolean mainTab;
public RegistrateDisplayItemsGenerator(boolean mainTab) {
this.mainTab = mainTab;
static {
MutableObject<Predicate<Item>> isItem3d = new MutableObject<>(item -> false);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
isItem3d.setValue(item -> {
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
BakedModel model = itemRenderer.getModel(new ItemStack(item), null, null, 0);
return model.isGui3d();
});
});
IS_ITEM_3D_PREDICATE = isItem3d.getValue();
}
@OnlyIn(Dist.CLIENT)
private static Predicate<Item> makeClient3dItemPredicate() {
return item -> {
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
BakedModel model = itemRenderer.getModel(new ItemStack(item), null, null, 0);
return model.isGui3d();
};
}
private final boolean addItems;
private final RegistryObject<CreativeModeTab> tabFilter;
public RegistrateDisplayItemsGenerator(boolean addItems, RegistryObject<CreativeModeTab> tabFilter) {
this.addItems = addItems;
this.tabFilter = tabFilter;
}
private static Predicate<Item> makeExclusionPredicate() {
Set<Item> exclusions = new ReferenceOpenHashSet<>();
@ -145,22 +164,6 @@ public class AllCreativeModeTabs {
return exclusions::contains;
}
private static Predicate<Item> make3DPredicate(boolean model3d) {
return item -> {
MutableBoolean result = new MutableBoolean(false);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> result.setValue(isItem3d(item) == model3d));
return result.getValue();
};
}
@OnlyIn(Dist.CLIENT)
private static boolean isItem3d(Item item) {
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
BakedModel model = itemRenderer.getModel(new ItemStack(item), null, null, 0);
return model.isGui3d();
}
private static List<ItemOrdering> makeOrderings() {
List<ItemOrdering> orderings = new ReferenceArrayList<>();
@ -253,26 +256,29 @@ public class AllCreativeModeTabs {
}
@Override
public void accept(ItemDisplayParameters pParameters, Output output) {
public void accept(ItemDisplayParameters parameters, Output output) {
Predicate<Item> exclusionPredicate = makeExclusionPredicate();
List<ItemOrdering> orderings = makeOrderings();
Function<Item, ItemStack> stackFunc = makeStackFunc();
Function<Item, TabVisibility> visibilityFunc = makeVisibilityFunc();
RegistryObject<CreativeModeTab> tab = mainTab ? MAIN_TAB : BUILDING_BLOCKS_TAB;
List<Item> items = new LinkedList<>();
items.addAll(collectItems(tab, exclusionPredicate.or(make3DPredicate(false))));
items.addAll(collectBlocks(tab, exclusionPredicate));
items.addAll(collectItems(tab, exclusionPredicate.or(make3DPredicate(true))));
if (addItems) {
items.addAll(collectItems(exclusionPredicate.or(IS_ITEM_3D_PREDICATE.negate())));
}
items.addAll(collectBlocks(exclusionPredicate));
if (addItems) {
items.addAll(collectItems(exclusionPredicate.or(IS_ITEM_3D_PREDICATE)));
}
applyOrderings(items, orderings);
outputAll(output, items, stackFunc, visibilityFunc);
}
private List<Item> collectBlocks(RegistryObject<CreativeModeTab> tab, Predicate<Item> exclusionPredicate) {
private List<Item> collectBlocks(Predicate<Item> exclusionPredicate) {
List<Item> items = new ReferenceArrayList<>();
for (RegistryEntry<Block> entry : Create.REGISTRATE.getAll(Registries.BLOCK)) {
if (!Create.REGISTRATE.isInCreativeTab(entry, tab))
if (!CreateRegistrate.isInCreativeTab(entry, tabFilter))
continue;
Item item = entry.get()
.asItem();
@ -285,14 +291,10 @@ public class AllCreativeModeTabs {
return items;
}
private List<Item> collectItems(RegistryObject<CreativeModeTab> tab, Predicate<Item> exclusionPredicate) {
private List<Item> collectItems(Predicate<Item> exclusionPredicate) {
List<Item> items = new ReferenceArrayList<>();
if (!mainTab)
return items;
for (RegistryEntry<Item> entry : Create.REGISTRATE.getAll(Registries.ITEM)) {
if (!Create.REGISTRATE.isInCreativeTab(entry, tab))
if (!CreateRegistrate.isInCreativeTab(entry, tabFilter))
continue;
Item item = entry.get();
if (item instanceof BlockItem)
@ -345,4 +347,4 @@ public class AllCreativeModeTabs {
}
}
}
}
}

View file

@ -66,8 +66,10 @@ import net.minecraft.world.item.Rarity;
import net.minecraftforge.common.Tags;
public class AllItems {
static { REGISTRATE.useCreativeTab(AllCreativeModeTabs.MAIN_TAB); }
static {
REGISTRATE.setCreativeTab(AllCreativeModeTabs.BASE_CREATIVE_TAB);
}
public static final ItemEntry<Item> WHEAT_FLOUR =
taggedIngredient("wheat_flour", forgeItemTag("flour/wheat"), forgeItemTag("flour")),

View file

@ -91,6 +91,7 @@ import com.simibubi.create.foundation.networking.SimplePacketBase;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import com.simibubi.create.infrastructure.command.HighlightPacket;
import com.simibubi.create.infrastructure.command.SimpleCreateActions;
import com.simibubi.create.infrastructure.debugInfo.ServerDebugInfoPacket;
import net.createmod.catnip.net.ClientboundSimpleActionPacket;
import net.minecraft.core.BlockPos;
@ -205,7 +206,7 @@ public enum AllPackets {
CONTRAPTION_ACTOR_TOGGLE(ContraptionDisableActorPacket.class, ContraptionDisableActorPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_COLLIDER_LOCK(ContraptionColliderLockPacket.class, ContraptionColliderLockPacket::new, PLAY_TO_CLIENT),
ATTACHED_COMPUTER(AttachedComputerPacket.class, AttachedComputerPacket::new, PLAY_TO_CLIENT),
SERVER_DEBUG_INFO(ServerDebugInfoPacket.class, ServerDebugInfoPacket::new, PLAY_TO_CLIENT)
;
static {

View file

@ -6,6 +6,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import com.google.gson.JsonArray;
@ -319,12 +320,10 @@ public class AllSoundEvents {
});
}
public static JsonObject provideLangEntries() {
JsonObject object = new JsonObject();
public static void provideLang(BiConsumer<String, String> consumer) {
for (SoundEntry entry : ALL.values())
if (entry.hasSubtitle())
object.addProperty(entry.getSubtitleKey(), entry.getSubtitle());
return object;
consumer.accept(entry.getSubtitleKey(), entry.getSubtitle());
}
public static SoundEntryProvider provider(DataGenerator generator) {

View file

@ -78,23 +78,27 @@ public class AllTags {
BRITTLE,
CASING,
CONTRAPTION_INVENTORY_DENY,
COPYCAT_ALLOW,
COPYCAT_DENY,
FAN_PROCESSING_CATALYSTS_BLASTING(MOD, "fan_processing_catalysts/blasting"),
FAN_PROCESSING_CATALYSTS_HAUNTING(MOD, "fan_processing_catalysts/haunting"),
FAN_PROCESSING_CATALYSTS_SMOKING(MOD, "fan_processing_catalysts/smoking"),
FAN_PROCESSING_CATALYSTS_SPLASHING(MOD, "fan_processing_catalysts/splashing"),
FAN_TRANSPARENT,
NON_MOVABLE,
GIRDABLE_TRACKS,
MOVABLE_EMPTY_COLLIDER,
NON_MOVABLE,
ORE_OVERRIDE_STONE,
PASSIVE_BOILER_HEATERS,
SAFE_NBT,
SEATS,
TOOLBOXES,
TRACKS,
GIRDABLE_TRACKS,
TREE_ATTACHMENTS,
VALVE_HANDLES,
WINDMILL_SAILS,
WRENCH_PICKUP,
COPYCAT_ALLOW,
COPYCAT_DENY,
CONTRAPTION_INVENTORY_DENY,
RELOCATION_NOT_SUPPORTED(FORGE),
WG_STONE(FORGE),
@ -156,8 +160,10 @@ public class AllTags {
BLAZE_BURNER_FUEL_REGULAR(MOD, "blaze_burner_fuel/regular"),
BLAZE_BURNER_FUEL_SPECIAL(MOD, "blaze_burner_fuel/special"),
CASING,
CONTRAPTION_CONTROLLED,
CREATE_INGOTS,
CRUSHED_RAW_MATERIALS,
DEPLOYABLE_DRINK,
MODDED_STRIPPED_LOGS,
MODDED_STRIPPED_WOOD,
PRESSURIZED_AIR_SOURCES,
@ -169,8 +175,6 @@ public class AllTags {
VALVE_HANDLES,
VANILLA_STRIPPED_LOGS,
VANILLA_STRIPPED_WOOD,
DEPLOYABLE_DRINK,
CONTRAPTION_CONTROLLED,
STRIPPED_LOGS(FORGE),
STRIPPED_WOOD(FORGE),
@ -226,6 +230,10 @@ public class AllTags {
BOTTOMLESS_ALLOW(MOD, "bottomless/allow"),
BOTTOMLESS_DENY(MOD, "bottomless/deny"),
FAN_PROCESSING_CATALYSTS_BLASTING(MOD, "fan_processing_catalysts/blasting"),
FAN_PROCESSING_CATALYSTS_HAUNTING(MOD, "fan_processing_catalysts/haunting"),
FAN_PROCESSING_CATALYSTS_SMOKING(MOD, "fan_processing_catalysts/smoking"),
FAN_PROCESSING_CATALYSTS_SPLASHING(MOD, "fan_processing_catalysts/splashing"),
HONEY(FORGE)
@ -275,6 +283,7 @@ public class AllTags {
public enum AllEntityTags {
BLAZE_BURNER_CAPTURABLE,
IGNORE_SEAT,
;
@ -308,9 +317,12 @@ public class AllTags {
this.alwaysDatagen = alwaysDatagen;
}
public boolean matches(EntityType<?> type) {
return type.is(tag);
}
public boolean matches(Entity entity) {
return entity.getType()
.is(tag);
return matches(entity.getType());
}
private static void init() {}

View file

@ -1,7 +1,6 @@
package com.simibubi.create;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import org.slf4j.Logger;
@ -24,43 +23,30 @@ import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler;
import com.simibubi.create.content.schematics.ServerSchematicLoader;
import com.simibubi.create.content.trains.GlobalRailwayManager;
import com.simibubi.create.content.trains.bogey.BogeySizes;
import com.simibubi.create.content.trains.track.AllPortalTracks;
import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.block.CopperRegistries;
import com.simibubi.create.foundation.data.CreateRegistrate;
import com.simibubi.create.foundation.data.DamageTypeTagGen;
import com.simibubi.create.foundation.data.GeneratedEntriesProvider;
import com.simibubi.create.foundation.data.LangMerger;
import com.simibubi.create.foundation.data.RecipeSerializerTagGen;
import com.simibubi.create.foundation.data.TagGen;
import com.simibubi.create.foundation.data.recipe.MechanicalCraftingRecipeGen;
import com.simibubi.create.foundation.data.recipe.ProcessingRecipeGen;
import com.simibubi.create.foundation.data.recipe.SequencedAssemblyRecipeGen;
import com.simibubi.create.foundation.data.recipe.StandardRecipeGen;
import com.simibubi.create.foundation.gui.CreateTheme;
import com.simibubi.create.foundation.item.ItemDescription;
import com.simibubi.create.foundation.item.KineticStats;
import com.simibubi.create.foundation.item.TooltipModifier;
import com.simibubi.create.foundation.ponder.CreatePonderPlugin;
import com.simibubi.create.foundation.utility.AttachedRegistry;
import com.simibubi.create.foundation.utility.CreateNBTProcessors;
import com.simibubi.create.infrastructure.command.ServerLagger;
import com.simibubi.create.infrastructure.config.AllConfigs;
import com.simibubi.create.infrastructure.data.CreateDatagen;
import com.simibubi.create.infrastructure.worldgen.AllFeatures;
import com.simibubi.create.infrastructure.worldgen.AllPlacementModifiers;
import net.minecraft.core.HolderLookup;
import net.createmod.catnip.utility.lang.LangBuilder;
import net.createmod.ponder.foundation.PonderIndex;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.PackOutput;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.data.event.GatherDataEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.DistExecutor;
@ -74,7 +60,7 @@ public class Create {
public static final String ID = "create";
public static final String NAME = "Create";
public static final String VERSION = "0.5.1e";
public static final String VERSION = "0.6-experimental";
public static final Logger LOGGER = LogUtils.getLogger();
@ -86,6 +72,10 @@ public class Create {
@Deprecated
public static final Random RANDOM = new Random();
/**
* <b>Other mods should not use this field!</b> If you are an addon developer, create your own instance of
* {@link CreateRegistrate}.
*/
public static final CreateRegistrate REGISTRATE = CreateRegistrate.create(ID);
static {
@ -138,6 +128,7 @@ public class Create {
// FIXME: some of these registrations are not thread-safe
AllMovementBehaviours.registerDefaults();
AllInteractionBehaviours.registerDefaults();
AllPortalTracks.registerDefaults();
AllDisplayBehaviours.registerDefaults();
ContraptionMovementSetting.registerDefaults();
AllArmInteractionPointTypes.register();
@ -153,7 +144,7 @@ public class Create {
CopperRegistries.inject();
modEventBus.addListener(Create::init);
modEventBus.addListener(EventPriority.LOW, Create::gatherData);
modEventBus.addListener(EventPriority.LOWEST, CreateDatagen::gatherData);
modEventBus.addListener(AllSoundEvents::register);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus));
@ -180,36 +171,6 @@ public class Create {
});
}
public static void gatherData(GatherDataEvent event) {
TagGen.datagen();
DataGenerator gen = event.getGenerator();
PackOutput output = gen.getPackOutput();
CompletableFuture<HolderLookup.Provider> lookupProvider = event.getLookupProvider();
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> PonderIndex.addPlugin(new CreatePonderPlugin()));
gen.addProvider(event.includeClient(), AllSoundEvents.provider(gen));
GeneratedEntriesProvider generatedEntriesProvider = new GeneratedEntriesProvider(output, lookupProvider);
lookupProvider = generatedEntriesProvider.getRegistryProvider();
gen.addProvider(event.includeServer(), generatedEntriesProvider);
gen.addProvider(event.includeServer(), new RecipeSerializerTagGen(output, lookupProvider, event.getExistingFileHelper()));
gen.addProvider(event.includeServer(), new DamageTypeTagGen(output, lookupProvider, event.getExistingFileHelper()));
gen.addProvider(event.includeServer(), new AllAdvancements(output));
gen.addProvider(event.includeServer(), new StandardRecipeGen(output));
gen.addProvider(event.includeServer(), new MechanicalCraftingRecipeGen(output));
gen.addProvider(event.includeServer(), new SequencedAssemblyRecipeGen(output));
if (event.includeClient()) {
LangMerger.attachToRegistrateProvider(gen, output);
}
if (event.includeServer()) {
ProcessingRecipeGen.registerAll(gen, output);
}
}
public static LangBuilder lang() {
return new LangBuilder(ID);
}

View file

@ -0,0 +1,83 @@
package com.simibubi.create.api.event;
import org.jetbrains.annotations.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluid;
import net.minecraftforge.eventbus.api.Event;
/**
* This Event is fired when two fluids meet in a pipe ({@link Flow})<br>
* or when a fluid in a pipe meets with a fluid in the world
* ({@link Spill}).<br>
* <br>
* If it is not null, the event's BlockState will be placed in world after
* firing.
*/
public class PipeCollisionEvent extends Event {
private final Level level;
private final BlockPos pos;
protected final Fluid firstFluid, secondFluid;
@Nullable
private BlockState state;
protected PipeCollisionEvent(Level level, BlockPos pos, Fluid firstFluid, Fluid secondFluid,
@Nullable BlockState defaultState) {
this.level = level;
this.pos = pos;
this.firstFluid = firstFluid;
this.secondFluid = secondFluid;
this.state = defaultState;
}
public Level getLevel() {
return level;
}
public BlockPos getPos() {
return pos;
}
@Nullable
public BlockState getState() {
return state;
}
public void setState(@Nullable BlockState state) {
this.state = state;
}
public static class Flow extends PipeCollisionEvent {
public Flow(Level level, BlockPos pos, Fluid firstFluid, Fluid secondFluid, @Nullable BlockState defaultState) {
super(level, pos, firstFluid, secondFluid, defaultState);
}
public Fluid getFirstFluid() {
return firstFluid;
}
public Fluid getSecondFluid() {
return secondFluid;
}
}
public static class Spill extends PipeCollisionEvent {
public Spill(Level level, BlockPos pos, Fluid worldFluid, Fluid pipeFluid, @Nullable BlockState defaultState) {
super(level, pos, worldFluid, pipeFluid, defaultState);
}
public Fluid getWorldFluid() {
return firstFluid;
}
public Fluid getPipeFluid() {
return secondFluid;
}
}
}

View file

@ -13,6 +13,7 @@ import net.minecraftforge.registries.ForgeRegistries;
* For compatibility with and without another mod present, we have to define load conditions of the specific code
*/
public enum Mods {
AETHER,
COMPUTERCRAFT,
CONNECTIVITY,
CURIOS,

View file

@ -1,5 +1,18 @@
package com.simibubi.create.content.contraptions;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.UUID;
import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.tuple.MutablePair;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllMovementBehaviours;
@ -24,6 +37,7 @@ import com.simibubi.create.content.trains.entity.Train;
import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.collision.Matrix3d;
import com.simibubi.create.foundation.mixin.accessor.ServerLevelAccessor;
import net.createmod.catnip.utility.VecHelper;
import net.createmod.catnip.utility.math.AngleHelper;
import net.minecraft.client.Minecraft;
@ -64,17 +78,6 @@ import net.minecraftforge.entity.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.network.NetworkHooks;
import net.minecraftforge.network.PacketDistributor;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.tuple.MutablePair;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.UUID;
public abstract class AbstractContraptionEntity extends Entity implements IEntityAdditionalSpawnData {
@ -215,6 +218,9 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
}
public Vec3 getPassengerPosition(Entity passenger, float partialTicks) {
if (contraption == null)
return null;
UUID id = passenger.getUUID();
if (passenger instanceof OrientedContraptionEntity) {
BlockPos localPos = contraption.getBearingPosOf(id);
@ -229,6 +235,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
BlockPos seat = contraption.getSeatOf(id);
if (seat == null)
return null;
Vec3 transformedVector = toGlobalVector(Vec3.atLowerCornerOf(seat)
.add(.5, passenger.getMyRidingOffset() + ySize - .15f, .5), partialTicks)
.add(VecHelper.getCenterOf(BlockPos.ZERO))

View file

@ -1,5 +1,12 @@
package com.simibubi.create.content.contraptions;
import static net.createmod.catnip.utility.math.AngleHelper.angleLerp;
import java.util.Optional;
import java.util.UUID;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllEntityTypes;
@ -10,6 +17,7 @@ import com.simibubi.create.content.contraptions.minecart.capability.MinecartCont
import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlockEntity.CartMovementMode;
import com.simibubi.create.content.contraptions.mounted.MountedContraption;
import com.simibubi.create.foundation.item.ItemHelper;
import net.createmod.catnip.utility.Couple;
import net.createmod.catnip.utility.NBTHelper;
import net.createmod.catnip.utility.VecHelper;
@ -41,12 +49,6 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.LazyOptional;
import javax.annotation.Nullable;
import java.util.Optional;
import java.util.UUID;
import static net.createmod.catnip.utility.math.AngleHelper.angleLerp;
/**
* Ex: Minecarts, Couplings <br>
* Oriented Contraption Entities can rotate freely around two axes
@ -567,6 +569,9 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
private Vec3 getContraptionOffset(float partialTicks, Entity ridingEntity) {
AbstractContraptionEntity parent = (AbstractContraptionEntity) ridingEntity;
Vec3 passengerPosition = parent.getPassengerPosition(this, partialTicks);
if (passengerPosition == null)
return Vec3.ZERO;
double x = passengerPosition.x - Mth.lerp(partialTicks, this.xOld, this.getX());
double y = passengerPosition.y - Mth.lerp(partialTicks, this.yOld, this.getY());
double z = passengerPosition.z - Mth.lerp(partialTicks, this.zOld, this.getZ());

View file

@ -58,7 +58,7 @@ public class PortableStorageInterfaceBlock extends WrenchableDirectionalBlock
public BlockState getStateForPlacement(BlockPlaceContext context) {
Direction direction = context.getNearestLookingDirection();
if (context.getPlayer() != null && context.getPlayer()
.isSteppingCarefully())
.isShiftKeyDown())
direction = direction.getOpposite();
return defaultBlockState().setValue(FACING, direction.getOpposite());
}

View file

@ -118,7 +118,7 @@ public class RollerBlockEntity extends SmartBlockEntity {
protected void acceptSharedValues(int mode, ItemStack filter) {
dontPropagate = true;
this.filtering.setFilter(filter);
this.filtering.setFilter(filter.copy());
this.mode.setValue(mode);
dontPropagate = false;
notifyUpdate();

View file

@ -19,7 +19,7 @@ import com.simibubi.create.content.contraptions.render.ActorInstance;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour;
import com.simibubi.create.content.logistics.filter.FilterItem;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.trains.bogey.StandardBogeyBlock;
import com.simibubi.create.content.trains.entity.Carriage;
import com.simibubi.create.content.trains.entity.CarriageBogey;
@ -36,6 +36,7 @@ import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.infrastructure.config.AllConfigs;
import net.createmod.catnip.utility.Couple;
import net.createmod.catnip.utility.Iterate;
import net.createmod.catnip.utility.Pair;
import net.createmod.catnip.utility.VecHelper;
import net.minecraft.client.renderer.MultiBufferSource;
@ -102,6 +103,11 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override
public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) {
for (Direction side : Iterate.directions)
if (world.getBlockState(breakingPos.relative(side))
.is(BlockTags.PORTALS))
return false;
return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos)
.isEmpty() && !AllBlocks.TRACK.has(state);
}
@ -188,10 +194,10 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
int startingY = 1;
if (!getStateToPaveWith(context).isAir()) {
ItemStack filter = ItemStack.of(context.blockEntityData.getCompound("Filter"));
FilterItemStack filter = context.getFilterFromBE();
if (!ItemHelper
.extract(context.contraption.getSharedInventory(),
stack -> FilterItem.test(context.world, stack, filter), 1, true)
stack -> filter.test(context.world, stack), 1, true)
.isEmpty())
startingY = 0;
}
@ -279,8 +285,15 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
};
rollerScout.travel(train.graph, lengthWiseOffset + 1, steering);
rollerScout.traversalCallback = (edge, coords) -> TrackPaverV2.pave(heightProfile, train.graph, edge,
coords.getFirst(), coords.getSecond());
rollerScout.traversalCallback = (edge, coords) -> {
if (edge == null)
return;
if (edge.isInterDimensional())
return;
if (edge.node1.getLocation().dimension != context.world.dimension())
return;
TrackPaverV2.pave(heightProfile, train.graph, edge, coords.getFirst(), coords.getSecond());
};
rollerScout.travel(train.graph, distanceToTravel, steering);
for (Couple<Integer> entry : heightProfile.keys())
@ -294,6 +307,9 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
BlockState stateToPaveWithAsSlab = getStateToPaveWithAsSlab(context);
RollingMode mode = getMode(context);
if (mode != RollingMode.TUNNEL_PAVE && stateToPaveWith.isAir())
return;
Vec3 directionVec = Vec3.atLowerCornerOf(context.state.getValue(RollerBlock.FACING)
.getClockWise()
.getNormal());
@ -457,9 +473,9 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
.isEmpty())
return PaveResult.FAIL;
ItemStack filter = ItemStack.of(context.blockEntityData.getCompound("Filter"));
FilterItemStack filter = context.getFilterFromBE();
ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(),
stack -> FilterItem.test(context.world, stack, filter), 1, false);
stack -> filter.test(context.world, stack), 1, false);
if (held.isEmpty())
return PaveResult.FAIL;

View file

@ -56,7 +56,7 @@ public class ControlsBlock extends HorizontalDirectionalBlock implements IWrench
Player player = pContext.getPlayer();
state = state.setValue(FACING, horizontalDirection.getOpposite());
if (player != null && player.isSteppingCarefully())
if (player != null && player.isShiftKeyDown())
state = state.setValue(FACING, horizontalDirection);
return state;

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.behaviour;
import java.util.function.UnaryOperator;
import com.simibubi.create.content.contraptions.Contraption;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import net.createmod.catnip.utility.VecHelper;
import net.minecraft.core.BlockPos;
@ -32,6 +33,8 @@ public class MovementContext {
public Contraption contraption;
public Object temporaryData;
private FilterItemStack filter;
public MovementContext(Level world, StructureBlockInfo info, Contraption contraption) {
this.world = world;
this.state = info.state();
@ -47,6 +50,7 @@ public class MovementContext {
position = null;
data = new CompoundTag();
stall = false;
filter = null;
}
public float getAnimationSpeed() {
@ -84,4 +88,10 @@ public class MovementContext {
return nbt;
}
public FilterItemStack getFilterFromBE() {
if (filter != null)
return filter;
return filter = FilterItemStack.of(blockEntityData.getCompound("Filter"));
}
}

View file

@ -1,5 +1,7 @@
package com.simibubi.create.content.contraptions.elevator;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPackets;
import com.simibubi.create.AllSoundEvents;
@ -10,6 +12,7 @@ import com.simibubi.create.content.contraptions.pulley.PulleyBlockEntity;
import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.infrastructure.config.AllConfigs;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
@ -17,8 +20,6 @@ import net.minecraft.util.Mth;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import java.util.List;
public class ElevatorPulleyBlockEntity extends PulleyBlockEntity {
private float prevSpeed;
@ -88,7 +89,7 @@ public class ElevatorPulleyBlockEntity extends PulleyBlockEntity {
if (level.isClientSide())
targetLevel = ec.clientYTarget;
if (!wasArrived && !level.isClientSide()) {
triggerContact(ec, targetLevel);
triggerContact(ec, targetLevel - ec.contactYOffset);
AllSoundEvents.CONTRAPTION_DISASSEMBLE.play(level, null, worldPosition.below((int) offset), 0.75f, 0.8f);
}

View file

@ -1,5 +1,9 @@
package com.simibubi.create.content.contraptions.glue;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllEntityTypes;
import com.simibubi.create.AllItems;
@ -11,6 +15,7 @@ import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock;
import com.simibubi.create.content.schematics.requirement.ISpecialEntityItemRequirement;
import com.simibubi.create.content.schematics.requirement.ItemRequirement;
import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType;
import net.createmod.catnip.utility.Iterate;
import net.createmod.catnip.utility.VecHelper;
import net.minecraft.core.BlockPos;
@ -50,10 +55,6 @@ import net.minecraft.world.phys.Vec3;
import net.minecraftforge.entity.IEntityAdditionalSpawnData;
import net.minecraftforge.network.NetworkHooks;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement {
public static AABB span(BlockPos startPos, BlockPos endPos) {
@ -295,9 +296,12 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
return PushReaction.IGNORE;
}
public void setPortalEntrancePos() {
portalEntrancePos = blockPosition();
}
@Override
public PortalInfo findDimensionEntryPoint(ServerLevel pDestination) {
portalEntrancePos = blockPosition();
return super.findDimensionEntryPoint(pDestination);
}

View file

@ -1,5 +1,9 @@
package com.simibubi.create.content.contraptions.glue;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import com.google.common.base.Objects;
import com.simibubi.create.AllPackets;
import com.simibubi.create.AllSoundEvents;
@ -7,6 +11,7 @@ import com.simibubi.create.AllSpecialTextures;
import com.simibubi.create.content.contraptions.chassis.AbstractChassisBlock;
import com.simibubi.create.foundation.utility.CreateLang;
import com.simibubi.create.foundation.utility.RaycastHelper;
import net.createmod.catnip.CatnipClient;
import net.createmod.catnip.utility.lang.Components;
import net.minecraft.client.Minecraft;
@ -25,10 +30,6 @@ import net.minecraft.world.phys.HitResult.Type;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.ForgeMod;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public class SuperGlueSelectionHandler {
private static final int PASSIVE = 0x4D9162;
@ -120,7 +121,7 @@ public class SuperGlueSelectionHandler {
return;
}
boolean cancel = player.isSteppingCarefully();
boolean cancel = player.isShiftKeyDown();
if (cancel && firstPos == null)
return;
@ -188,6 +189,8 @@ public class SuperGlueSelectionHandler {
if (!isGlue(player.getMainHandItem()))
return false;
if (!player.mayBuild())
return false;
if (attack) {
if (selected == null)
@ -198,7 +201,7 @@ public class SuperGlueSelectionHandler {
return true;
}
if (player.isSteppingCarefully()) {
if (player.isShiftKeyDown()) {
if (firstPos != null) {
discard();
return true;

View file

@ -316,7 +316,7 @@ public abstract class CopycatBlock extends Block implements IBE<CopycatBlockEnti
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos,
Player player) {
BlockState material = getMaterial(level, pos);
if (AllBlocks.COPYCAT_BASE.has(material) || player != null && player.isSteppingCarefully())
if (AllBlocks.COPYCAT_BASE.has(material) || player != null && player.isShiftKeyDown())
return new ItemStack(this);
return material.getCloneItemStack(target, level, pos, player);
}

View file

@ -1,5 +1,8 @@
package com.simibubi.create.content.decoration.girder;
import static net.minecraft.world.level.block.FaceAttachedHorizontalDirectionalBlock.FACE;
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllShapes;
@ -15,6 +18,7 @@ import com.simibubi.create.content.trains.display.FlapDisplayBlock;
import com.simibubi.create.content.trains.track.TrackBlock;
import com.simibubi.create.content.trains.track.TrackShape;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import net.createmod.catnip.utility.Iterate;
import net.createmod.catnip.utility.placement.IPlacementHelper;
import net.createmod.catnip.utility.placement.PlacementHelpers;
@ -60,9 +64,6 @@ import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import static net.minecraft.world.level.block.FaceAttachedHorizontalDirectionalBlock.FACE;
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED;
public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenchable {
private static final int placementHelperId = PlacementHelpers.register(new GirderPlacementHelper());
@ -119,7 +120,7 @@ public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenc
return InteractionResult.SUCCESS;
}
if (AllItems.WRENCH.isIn(itemInHand) && !pPlayer.isSteppingCarefully()) {
if (AllItems.WRENCH.isIn(itemInHand) && !pPlayer.isShiftKeyDown()) {
if (GirderWrenchBehavior.handleClick(pLevel, pPos, pState, pHit))
return InteractionResult.sidedSuccess(pLevel.isClientSide);
return InteractionResult.FAIL;

View file

@ -44,7 +44,7 @@ public class GirderWrenchBehavior {
Player player = mc.player;
ItemStack heldItem = player.getMainHandItem();
if (player.isSteppingCarefully())
if (player.isShiftKeyDown())
return;
if (!AllBlocks.METAL_GIRDER.has(world.getBlockState(pos)))

View file

@ -1,5 +1,13 @@
package com.simibubi.create.content.decoration.palettes;
import static com.simibubi.create.Create.REGISTRATE;
import static com.simibubi.create.foundation.data.WindowGen.customWindowBlock;
import static com.simibubi.create.foundation.data.WindowGen.customWindowPane;
import static com.simibubi.create.foundation.data.WindowGen.framedGlass;
import static com.simibubi.create.foundation.data.WindowGen.framedGlassPane;
import static com.simibubi.create.foundation.data.WindowGen.woodenWindowBlock;
import static com.simibubi.create.foundation.data.WindowGen.woodenWindowPane;
import com.simibubi.create.AllCreativeModeTabs;
import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.Create;
@ -9,6 +17,7 @@ import com.simibubi.create.foundation.data.BlockStateGen;
import com.simibubi.create.foundation.data.WindowGen;
import com.tterrag.registrate.util.DataIngredient;
import com.tterrag.registrate.util.entry.BlockEntry;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.resources.ResourceLocation;
@ -20,17 +29,11 @@ import net.minecraft.world.level.block.state.properties.WoodType;
import net.minecraft.world.level.material.MapColor;
import net.minecraftforge.common.Tags;
import static com.simibubi.create.Create.REGISTRATE;
import static com.simibubi.create.foundation.data.WindowGen.customWindowBlock;
import static com.simibubi.create.foundation.data.WindowGen.customWindowPane;
import static com.simibubi.create.foundation.data.WindowGen.framedGlass;
import static com.simibubi.create.foundation.data.WindowGen.framedGlassPane;
import static com.simibubi.create.foundation.data.WindowGen.woodenWindowBlock;
import static com.simibubi.create.foundation.data.WindowGen.woodenWindowPane;
public class AllPaletteBlocks {
static { REGISTRATE.useCreativeTab(AllCreativeModeTabs.BUILDING_BLOCKS_TAB); }
static {
REGISTRATE.setCreativeTab(AllCreativeModeTabs.PALETTES_CREATIVE_TAB);
}
// Windows and Glass

View file

@ -18,7 +18,7 @@ public class LayeredBlock extends RotatedPillarBlock {
.relative(pContext.getClickedFace()
.getOpposite()));
if (placedOn.getBlock() == this && (pContext.getPlayer() == null || !pContext.getPlayer()
.isSteppingCarefully()))
.isShiftKeyDown()))
stateForPlacement = stateForPlacement.setValue(AXIS, placedOn.getValue(AXIS));
return stateForPlacement;
}

View file

@ -1,5 +1,10 @@
package com.simibubi.create.content.decoration.palettes;
import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly;
import java.util.Arrays;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.data.CreateRegistrate;
import com.tterrag.registrate.builders.BlockBuilder;
@ -10,6 +15,7 @@ import com.tterrag.registrate.providers.RegistrateRecipeProvider;
import com.tterrag.registrate.util.DataIngredient;
import com.tterrag.registrate.util.entry.BlockEntry;
import com.tterrag.registrate.util.nullness.NonnullType;
import net.createmod.catnip.utility.lang.Lang;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.data.recipes.ShapedRecipeBuilder;
@ -27,11 +33,6 @@ import net.minecraft.world.level.block.WallBlock;
import net.minecraft.world.level.block.state.BlockBehaviour.Properties;
import net.minecraftforge.client.model.generators.ModelFile;
import java.util.Arrays;
import java.util.function.Supplier;
import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly;
public abstract class PaletteBlockPartial<B extends Block> {
public static final PaletteBlockPartial<StairBlock> STAIR = new Stairs();
@ -223,7 +224,7 @@ public abstract class PaletteBlockPartial<B extends Block> {
@Override
protected WallBlock createBlock(Supplier<? extends Block> block) {
return new WallBlock(Properties.copy(block.get()));
return new WallBlock(Properties.copy(block.get()).forceSolidOn());
}
@Override

View file

@ -8,6 +8,7 @@ import com.simibubi.create.AllShapes;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.content.equipment.wrench.IWrenchable;
import com.simibubi.create.content.logistics.filter.FilterItem;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement;
import com.simibubi.create.content.schematics.requirement.ItemRequirement;
import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType;
@ -132,9 +133,9 @@ public class PlacardBlock extends FaceAttachedHorizontalDirectionalBlock
return InteractionResult.FAIL;
if (pState.getValue(POWERED))
return InteractionResult.FAIL;
boolean test = inBlock.getItem() instanceof FilterItem ? FilterItem.test(pLevel, inHand, inBlock)
: ItemHandlerHelper.canItemStacksStack(inHand, inBlock);
boolean test = inBlock.getItem() instanceof FilterItem ? FilterItemStack.of(inBlock)
.test(pLevel, inHand) : ItemHandlerHelper.canItemStacksStack(inHand, inBlock);
if (!test) {
AllSoundEvents.DENY.play(pLevel, null, pPos, 1, 1);
return InteractionResult.SUCCESS;

View file

@ -1,6 +1,6 @@
package com.simibubi.create.content.equipment.armor;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllTags.AllItemTags;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.EquipmentSlot;
@ -28,13 +28,13 @@ public final class NetheriteDivingHandler {
ItemStack to = event.getTo();
if (slot == EquipmentSlot.HEAD) {
if (AllItems.NETHERITE_DIVING_HELMET.isIn(to)) {
if (isNetheriteDivingHelmet(to)) {
setBit(entity, slot);
} else {
clearBit(entity, slot);
}
} else if (slot == EquipmentSlot.CHEST) {
if (AllItems.NETHERITE_BACKTANK.isIn(to) && BacktankUtil.hasAirRemaining(to)) {
if (isNetheriteBacktank(to) && BacktankUtil.hasAirRemaining(to)) {
setBit(entity, slot);
} else {
clearBit(entity, slot);
@ -48,6 +48,14 @@ public final class NetheriteDivingHandler {
}
}
public static boolean isNetheriteDivingHelmet(ItemStack stack) {
return stack.getItem() instanceof DivingHelmetItem && isNetheriteArmor(stack);
}
public static boolean isNetheriteBacktank(ItemStack stack) {
return stack.is(AllItemTags.PRESSURIZED_AIR_SOURCES.tag) && isNetheriteArmor(stack);
}
public static boolean isNetheriteArmor(ItemStack stack) {
return stack.getItem() instanceof ArmorItem armorItem && armorItem.getMaterial() == ArmorMaterials.NETHERITE;
}

View file

@ -1,14 +1,24 @@
package com.simibubi.create.content.equipment.blueprint;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import javax.annotation.Nullable;
import org.apache.commons.lang3.Validate;
import com.simibubi.create.AllEntityTypes;
import com.simibubi.create.AllItems;
import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.filter.FilterItem;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.schematics.requirement.ISpecialEntityItemRequirement;
import com.simibubi.create.content.schematics.requirement.ItemRequirement;
import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType;
import com.simibubi.create.foundation.networking.ISyncPersistentData;
import com.simibubi.create.foundation.utility.IInteractionChecker;
import net.createmod.catnip.utility.Couple;
import net.createmod.catnip.utility.VecHelper;
import net.minecraft.core.BlockPos;
@ -60,13 +70,6 @@ import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.InvWrapper;
import net.minecraftforge.network.NetworkHooks;
import org.apache.commons.lang3.Validate;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
public class BlueprintEntity extends HangingEntity
implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement, ISyncPersistentData, IInteractionChecker {
@ -363,14 +366,14 @@ public class BlueprintEntity extends HangingEntity
boolean success = true;
Search: for (int i = 0; i < 9; i++) {
ItemStack requestedItem = items.getStackInSlot(i);
FilterItemStack requestedItem = FilterItemStack.of(items.getStackInSlot(i));
if (requestedItem.isEmpty()) {
craftingGrid.put(i, ItemStack.EMPTY);
continue;
}
for (int slot = 0; slot < playerInv.getSlots(); slot++) {
if (!FilterItem.test(level(), playerInv.getStackInSlot(slot), requestedItem))
if (!requestedItem.test(level(), playerInv.getStackInSlot(slot)))
continue;
ItemStack currentItem = playerInv.extractItem(slot, 1, false);
if (stacksTaken.containsKey(slot))

View file

@ -1,14 +1,23 @@
package com.simibubi.create.content.equipment.blueprint;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllItems;
import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintCraftingInventory;
import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintSection;
import com.simibubi.create.content.logistics.filter.AttributeFilterMenu.WhitelistMode;
import com.simibubi.create.content.logistics.filter.FilterItem;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.logistics.filter.ItemAttribute;
import com.simibubi.create.content.trains.track.TrackPlacement.PlacementInfo;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import net.createmod.catnip.gui.element.GuiGameElement;
import net.createmod.catnip.utility.AnimationTickHolder;
import net.createmod.catnip.utility.Pair;
@ -36,13 +45,6 @@ import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.tags.ITag;
import net.minecraftforge.registries.tags.ITagManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class BlueprintOverlayRenderer {
public static final IGuiOverlay OVERLAY = BlueprintOverlayRenderer::renderOverlay;
@ -161,14 +163,14 @@ public class BlueprintOverlayRenderer {
newlyMissing.clear();
Search: for (int i = 0; i < 9; i++) {
ItemStack requestedItem = items.getStackInSlot(i);
FilterItemStack requestedItem = FilterItemStack.of(items.getStackInSlot(i));
if (requestedItem.isEmpty()) {
craftingGrid.put(i, ItemStack.EMPTY);
continue;
}
for (int slot = 0; slot < playerInv.getSlots(); slot++) {
if (!FilterItem.test(mc.level, playerInv.getStackInSlot(slot), requestedItem))
if (!requestedItem.test(mc.level, playerInv.getStackInSlot(slot)))
continue;
ItemStack currentItem = playerInv.extractItem(slot, 1, false);
craftingGrid.put(i, currentItem);
@ -177,7 +179,7 @@ public class BlueprintOverlayRenderer {
}
success = false;
newlyMissing.add(requestedItem);
newlyMissing.add(requestedItem.item());
}
if (success) {

View file

@ -1,11 +1,14 @@
package com.simibubi.create.content.equipment.clipboard;
import java.util.List;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.AllBlockEntityTypes;
import com.simibubi.create.AllShapes;
import com.simibubi.create.content.equipment.wrench.IWrenchable;
import com.simibubi.create.foundation.block.IBE;
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
import net.createmod.catnip.gui.ScreenOpener;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
@ -38,8 +41,6 @@ import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.DistExecutor;
import java.util.List;
public class ClipboardBlock extends FaceAttachedHorizontalDirectionalBlock
implements IBE<ClipboardBlockEntity>, IWrenchable, ProperWaterloggedBlock {
@ -85,7 +86,7 @@ public class ClipboardBlock extends FaceAttachedHorizontalDirectionalBlock
@Override
public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand,
BlockHitResult pHit) {
if (pPlayer.isSteppingCarefully()) {
if (pPlayer.isShiftKeyDown()) {
breakAndCollect(pState, pLevel, pPos, pPlayer);
return InteractionResult.SUCCESS;
}

View file

@ -33,7 +33,7 @@ public class ClipboardBlockItem extends BlockItem {
Player player = context.getPlayer();
if (player == null)
return InteractionResult.PASS;
if (player.isSteppingCarefully())
if (player.isShiftKeyDown())
return super.useOn(context);
return use(context.getLevel(), player, context.getHand()).getResult();
}

View file

@ -141,7 +141,7 @@ public class ClipboardValueSettingsHandler {
Player player = event.getEntity();
if (player != null && player.isSpectator())
return;
if (player.isSteppingCarefully())
if (player.isShiftKeyDown())
return;
if (!(world.getBlockEntity(pos) instanceof SmartBlockEntity smartBE))
return;

View file

@ -45,7 +45,7 @@ public class WrenchItem extends Item {
Block block = state.getBlock();
if (!(block instanceof IWrenchable)) {
if (canWrenchPickup(state))
if (player.isShiftKeyDown() && canWrenchPickup(state))
return onItemUseOnOther(context);
return super.useOn(context);
}

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.fluids;
import com.simibubi.create.AllFluids;
import com.simibubi.create.api.event.PipeCollisionEvent;
import com.simibubi.create.foundation.advancement.AdvancementBehaviour;
import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.fluid.FluidHelper;
@ -14,53 +15,84 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class FluidReactions {
public static void handlePipeFlowCollision(Level world, BlockPos pos, FluidStack fluid, FluidStack fluid2) {
public static void handlePipeFlowCollision(Level level, BlockPos pos, FluidStack fluid, FluidStack fluid2) {
Fluid f1 = fluid.getFluid();
Fluid f2 = fluid2.getFluid();
AdvancementBehaviour.tryAward(world, pos, AllAdvancements.CROSS_STREAMS);
BlockHelper.destroyBlock(world, pos, 1);
AdvancementBehaviour.tryAward(level, pos, AllAdvancements.CROSS_STREAMS);
BlockHelper.destroyBlock(level, pos, 1);
if (f1 == Fluids.WATER && f2 == Fluids.LAVA || f2 == Fluids.WATER && f1 == Fluids.LAVA)
world.setBlockAndUpdate(pos, Blocks.COBBLESTONE.defaultBlockState());
else if (f1 == Fluids.LAVA && FluidHelper.hasBlockState(f2)) {
BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(f2)
.defaultFluidState());
if (lavaInteraction != null)
world.setBlockAndUpdate(pos, lavaInteraction);
PipeCollisionEvent.Flow event = new PipeCollisionEvent.Flow(level, pos, f1, f2, null);
MinecraftForge.EVENT_BUS.post(event);
if (event.getState() != null)
level.setBlockAndUpdate(pos, event.getState());
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void handlePipeFlowCollisionFallback(PipeCollisionEvent.Flow event) {
Fluid f1 = event.getFirstFluid();
Fluid f2 = event.getSecondFluid();
if (f1 == Fluids.WATER && f2 == Fluids.LAVA || f2 == Fluids.WATER && f1 == Fluids.LAVA) {
event.setState(Blocks.COBBLESTONE.defaultBlockState());
} else if (f1 == Fluids.LAVA && FluidHelper.hasBlockState(f2)) {
BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(f2).defaultFluidState());
if (lavaInteraction != null) {
event.setState(lavaInteraction);
}
} else if (f2 == Fluids.LAVA && FluidHelper.hasBlockState(f1)) {
BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(f1)
.defaultFluidState());
if (lavaInteraction != null)
world.setBlockAndUpdate(pos, lavaInteraction);
BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(f1).defaultFluidState());
if (lavaInteraction != null) {
event.setState(lavaInteraction);
}
}
}
public static void handlePipeSpillCollision(Level world, BlockPos pos, Fluid pipeFluid, FluidState worldFluid) {
public static void handlePipeSpillCollision(Level level, BlockPos pos, Fluid pipeFluid, FluidState worldFluid) {
Fluid pf = FluidHelper.convertToStill(pipeFluid);
Fluid wf = worldFluid.getType();
if (FluidHelper.isTag(pf, FluidTags.WATER) && wf == Fluids.LAVA)
world.setBlockAndUpdate(pos, Blocks.OBSIDIAN.defaultBlockState());
else if (pf == Fluids.WATER && wf == Fluids.FLOWING_LAVA)
world.setBlockAndUpdate(pos, Blocks.COBBLESTONE.defaultBlockState());
else if (pf == Fluids.LAVA && wf == Fluids.WATER)
world.setBlockAndUpdate(pos, Blocks.STONE.defaultBlockState());
else if (pf == Fluids.LAVA && wf == Fluids.FLOWING_WATER)
world.setBlockAndUpdate(pos, Blocks.COBBLESTONE.defaultBlockState());
PipeCollisionEvent.Spill event = new PipeCollisionEvent.Spill(level, pos, wf, pf, null);
MinecraftForge.EVENT_BUS.post(event);
if (event.getState() != null) {
level.setBlockAndUpdate(pos, event.getState());
}
}
@SubscribeEvent(priority = EventPriority.HIGH)
public static void handlePipeSpillCollisionFallback(PipeCollisionEvent.Spill event) {
Fluid pf = event.getPipeFluid();
Fluid wf = event.getWorldFluid();
if (FluidHelper.isTag(pf, FluidTags.WATER) && wf == Fluids.LAVA) {
event.setState(Blocks.OBSIDIAN.defaultBlockState());
} else if (pf == Fluids.WATER && wf == Fluids.FLOWING_LAVA) {
event.setState(Blocks.COBBLESTONE.defaultBlockState());
} else if (pf == Fluids.LAVA && wf == Fluids.WATER) {
event.setState(Blocks.STONE.defaultBlockState());
} else if (pf == Fluids.LAVA && wf == Fluids.FLOWING_WATER) {
event.setState(Blocks.COBBLESTONE.defaultBlockState());
}
if (pf == Fluids.LAVA) {
BlockState lavaInteraction = AllFluids.getLavaInteraction(worldFluid);
if (lavaInteraction != null)
world.setBlockAndUpdate(pos, lavaInteraction);
BlockState lavaInteraction = AllFluids.getLavaInteraction(wf.defaultFluidState());
if (lavaInteraction != null) {
event.setState(lavaInteraction);
}
} else if (wf == Fluids.FLOWING_LAVA && FluidHelper.hasBlockState(pf)) {
BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(pf)
.defaultFluidState());
if (lavaInteraction != null)
world.setBlockAndUpdate(pos, lavaInteraction);
BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(pf).defaultFluidState());
if (lavaInteraction != null) {
event.setState(lavaInteraction);
}
}
}

View file

@ -131,7 +131,7 @@ public class PumpBlock extends DirectionalKineticBlock
return toPlace;
if (bestConnectedDirection.getAxis() == targetDirection.getAxis())
return toPlace;
if (player.isSteppingCarefully() && bestConnectedDirection.getAxis() != targetDirection.getAxis())
if (player.isShiftKeyDown() && bestConnectedDirection.getAxis() != targetDirection.getAxis())
return toPlace;
return toPlace.setValue(FACING, bestConnectedDirection);

View file

@ -10,6 +10,7 @@ import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel;
import com.simibubi.create.foundation.utility.AttachedRegistry;
import com.simibubi.create.foundation.utility.BlockHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
@ -71,7 +72,7 @@ public class BoilerHeaters {
});
registerHeaterProvider((level, pos, state) -> {
if (AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state)) {
if (AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) && BlockHelper.isNotUnheated(state)) {
return (level1, pos1, state1) -> 0;
}
return null;

View file

@ -94,7 +94,7 @@ public class BeltBlockEntity extends KineticBlockEntity {
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
super.addBehaviours(behaviours);
behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::canInsertFrom)
.setInsertionHandler(this::tryInsertingFromSide));
.setInsertionHandler(this::tryInsertingFromSide).considerOccupiedWhen(this::isOccupied));
behaviours.add(new TransportedItemStackHandlerBehaviour(this, this::applyToAllItems)
.withStackPlacement(this::getWorldPositionOf));
}
@ -463,6 +463,22 @@ public class BeltBlockEntity extends KineticBlockEntity {
return false;
return getMovementFacing() != side.getOpposite();
}
private boolean isOccupied(Direction side) {
BeltBlockEntity nextBeltController = getControllerBE();
if (nextBeltController == null)
return true;
BeltInventory nextInventory = nextBeltController.getInventory();
if (nextInventory == null)
return true;
if (getSpeed() == 0)
return true;
if (getMovementFacing() == side.getOpposite())
return true;
if (!nextInventory.canInsertAtFromSide(index, side))
return true;
return false;
}
private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) {
BeltBlockEntity nextBeltController = getControllerBE();
@ -492,11 +508,7 @@ public class BeltBlockEntity extends KineticBlockEntity {
}
}
if (getSpeed() == 0)
return inserted;
if (getMovementFacing() == side.getOpposite())
return inserted;
if (!nextInventory.canInsertAtFromSide(index, side))
if (isOccupied(side))
return inserted;
if (simulate)
return empty;

View file

@ -1,11 +1,16 @@
package com.simibubi.create.content.kinetics.belt;
import java.util.Map;
import com.simibubi.create.AllTags.AllItemTags;
import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap;
import net.createmod.catnip.utility.VecHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
import net.minecraft.util.Mth;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
@ -16,9 +21,13 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities;
public class BeltHelper {
public static Map<Item, Boolean> uprightCache = new Object2BooleanOpenHashMap<>();
public static final ResourceManagerReloadListener LISTENER = resourceManager -> uprightCache.clear();
public static boolean isItemUpright(ItemStack stack) {
return stack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM)
.isPresent() || AllItemTags.UPRIGHT_ON_BELT.matches(stack);
return uprightCache.computeIfAbsent(stack.getItem(),
item -> stack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM)
.isPresent() || AllItemTags.UPRIGHT_ON_BELT.matches(stack));
}
public static BeltBlockEntity getSegmentBE(LevelAccessor world, BlockPos pos) {

View file

@ -33,6 +33,7 @@ public class DirectBeltInputBehaviour extends BlockEntityBehaviour {
public static final BehaviourType<DirectBeltInputBehaviour> TYPE = new BehaviourType<>();
private InsertionCallback tryInsert;
private OccupiedPredicate isOccupied;
private AvailabilityPredicate canInsert;
private Supplier<Boolean> supportsBeltFunnels;
@ -40,6 +41,7 @@ public class DirectBeltInputBehaviour extends BlockEntityBehaviour {
super(be);
tryInsert = this::defaultInsertionCallback;
canInsert = d -> true;
isOccupied = d -> false;
supportsBeltFunnels = () -> false;
}
@ -57,6 +59,11 @@ public class DirectBeltInputBehaviour extends BlockEntityBehaviour {
canInsert = pred;
return this;
}
public DirectBeltInputBehaviour considerOccupiedWhen(OccupiedPredicate pred) {
isOccupied = pred;
return this;
}
public DirectBeltInputBehaviour setInsertionHandler(InsertionCallback callback) {
tryInsert = callback;
@ -75,6 +82,10 @@ public class DirectBeltInputBehaviour extends BlockEntityBehaviour {
return canInsert.test(side);
}
public boolean isOccupied(Direction side) {
return isOccupied.test(side);
}
public ItemStack handleInsertion(ItemStack stack, Direction side, boolean simulate) {
return handleInsertion(new TransportedItemStack(stack), side, simulate);
}
@ -93,6 +104,11 @@ public class DirectBeltInputBehaviour extends BlockEntityBehaviour {
public ItemStack apply(TransportedItemStack stack, Direction side, boolean simulate);
}
@FunctionalInterface
public interface OccupiedPredicate {
public boolean test(Direction side);
}
@FunctionalInterface
public interface AvailabilityPredicate {
public boolean test(Direction side);

View file

@ -62,7 +62,9 @@ public class ValveHandleBlock extends HandCrankBlock {
if (!(blockState.getBlock() instanceof ValveHandleBlock vhb))
return;
if (AllItems.WRENCH.isIn(player.getItemInHand(event.getHand())) && player.isSteppingCarefully())
if (!player.mayBuild())
return;
if (AllItems.WRENCH.isIn(player.getItemInHand(event.getHand())) && player.isShiftKeyDown())
return;
if (vhb.clicked(level, pos, blockState, player, event.getHand())) {
@ -90,7 +92,7 @@ public class ValveHandleBlock extends HandCrankBlock {
}
onBlockEntityUse(level, pos,
hcbe -> (hcbe instanceof ValveHandleBlockEntity vhbe) && vhbe.activate(player.isSteppingCarefully())
hcbe -> (hcbe instanceof ValveHandleBlockEntity vhbe) && vhbe.activate(player.isShiftKeyDown())
? InteractionResult.SUCCESS
: InteractionResult.PASS);
return true;

View file

@ -299,9 +299,6 @@ public class DeployerHandler {
return;
if (useItem == DENY)
return;
if (item instanceof BlockItem && !(item instanceof CartAssemblerBlockItem)
&& !clickedState.canBeReplaced(new BlockPlaceContext(itemusecontext)))
return;
// Reposition fire placement for convenience
if (item == Items.FLINT_AND_STEEL) {
@ -323,6 +320,10 @@ public class DeployerHandler {
player.placedTracks = true;
return;
}
if (item instanceof BlockItem && !(item instanceof CartAssemblerBlockItem)
&& !clickedState.canBeReplaced(new BlockPlaceContext(itemusecontext)))
return;
if (item == Items.ENDER_PEARL)
return;
if (AllItemTags.DEPLOYABLE_DRINK.matches(item))

View file

@ -21,7 +21,7 @@ import com.simibubi.create.content.contraptions.render.ActorInstance;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity.Mode;
import com.simibubi.create.content.logistics.filter.FilterItem;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.schematics.SchematicInstances;
import com.simibubi.create.content.schematics.requirement.ItemRequirement;
import com.simibubi.create.content.trains.entity.CarriageContraption;
@ -80,9 +80,9 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
public void activate(MovementContext context, BlockPos pos, DeployerFakePlayer player, Mode mode) {
Level world = context.world;
ItemStack filter = getFilter(context);
if (AllItems.SCHEMATIC.isIn(filter))
activateAsSchematicPrinter(context, pos, player, world, filter);
FilterItemStack filter = context.getFilterFromBE();
if (AllItems.SCHEMATIC.isIn(filter.item()))
activateAsSchematicPrinter(context, pos, player, world, filter.item());
Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(DeployerBlock.FACING)
.getNormal());
@ -221,11 +221,11 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
return;
if (player.getMainHandItem()
.isEmpty()) {
ItemStack filter = getFilter(context);
if (AllItems.SCHEMATIC.isIn(filter))
FilterItemStack filter = context.getFilterFromBE();
if (AllItems.SCHEMATIC.isIn(filter.item()))
return;
ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(),
stack -> FilterItem.test(context.world, stack, filter), 1, false);
stack -> filter.test(context.world, stack), 1, false);
player.setItemInHand(InteractionHand.MAIN_HAND, held);
}
}
@ -235,7 +235,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
if (player == null)
return;
Inventory inv = player.getInventory();
ItemStack filter = getFilter(context);
FilterItemStack filter = context.getFilterFromBE();
for (List<ItemStack> list : Arrays.asList(inv.armor, inv.offhand, inv.items)) {
for (int i = 0; i < list.size(); ++i) {
@ -243,7 +243,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
if (itemstack.isEmpty())
continue;
if (list == inv.items && i == inv.selected && FilterItem.test(context.world, itemstack, filter))
if (list == inv.items && i == inv.selected && filter.test(context.world, itemstack))
continue;
dropItem(context, itemstack);
@ -277,10 +277,6 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
return (DeployerFakePlayer) context.temporaryData;
}
private ItemStack getFilter(MovementContext context) {
return ItemStack.of(context.blockEntityData.getCompound("Filter"));
}
private Mode getMode(MovementContext context) {
return NBTHelper.readEnum(context.blockEntityData, "Mode", Mode.class);
}

View file

@ -32,9 +32,7 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.api.distmarker.Dist;
@ -54,8 +52,6 @@ public class AirCurrent {
new ArrayList<>();
protected List<Entity> caughtEntities = new ArrayList<>();
static boolean isClientPlayerInAirCurrent;
public AirCurrent(IAirCurrentSource source) {
this.source = source;
}
@ -64,21 +60,20 @@ public class AirCurrent {
if (direction == null)
rebuild();
Level world = source.getAirCurrentWorld();
Direction facing = direction;
if (world != null && world.isClientSide) {
float offset = pushing ? 0.5f : maxDistance + .5f;
Vec3 pos = VecHelper.getCenterOf(source.getAirCurrentPos())
.add(Vec3.atLowerCornerOf(facing.getNormal())
.add(Vec3.atLowerCornerOf(direction.getNormal())
.scale(offset));
if (world.random.nextFloat() < AllConfigs.client().fanParticleDensity.get())
world.addParticle(new AirFlowParticleData(source.getAirCurrentPos()), pos.x, pos.y, pos.z, 0, 0, 0);
}
tickAffectedEntities(world, facing);
tickAffectedEntities(world);
tickAffectedHandlers();
}
protected void tickAffectedEntities(Level world, Direction facing) {
protected void tickAffectedEntities(Level world) {
for (Iterator<Entity> iterator = caughtEntities.iterator(); iterator.hasNext();) {
Entity entity = iterator.next();
if (!entity.isAlive() || !entity.getBoundingBox()
@ -87,14 +82,14 @@ public class AirCurrent {
continue;
}
Vec3 center = VecHelper.getCenterOf(source.getAirCurrentPos());
Vec3i flow = (pushing ? facing : facing.getOpposite()).getNormal();
float sneakModifier = entity.isShiftKeyDown() ? 4096f : 512f;
Vec3i flow = (pushing ? direction : direction.getOpposite()).getNormal();
float speed = Math.abs(source.getSpeed());
double entityDistance = entity.position()
.distanceTo(center);
float acceleration = (float) (speed / sneakModifier / (entityDistance / maxDistance));
float sneakModifier = entity.isShiftKeyDown() ? 4096f : 512f;
double entityDistance = VecHelper.alignedDistanceToFace(entity.position(), source.getAirCurrentPos(), direction);
// entityDistanceOld should be removed eventually. Remember that entityDistanceOld cannot be 0 while entityDistance can,
// so division by 0 must be avoided.
double entityDistanceOld = entity.position().distanceTo(VecHelper.getCenterOf(source.getAirCurrentPos()));
float acceleration = (float) (speed / sneakModifier / (entityDistanceOld / maxDistance));
Vec3 previousMotion = entity.getDeltaMovement();
float maxAcceleration = 5;
@ -110,8 +105,7 @@ public class AirCurrent {
if (entity instanceof ServerPlayer)
((ServerPlayer) entity).connection.aboveGroundTickCount = 0;
entityDistance -= .5f;
FanProcessingType processingType = getSegmentAt((float) entityDistance);
FanProcessingType processingType = getTypeAt((float) entityDistance);
if (processingType == AllFanProcessingTypes.NONE)
continue;
@ -131,7 +125,33 @@ public class AirCurrent {
if (world != null)
processingType.affectEntity(entity, world);
}
}
public static boolean isPlayerCreativeFlying(Entity entity) {
if (entity instanceof Player) {
Player player = (Player) entity;
return player.isCreative() && player.getAbilities().flying;
}
return false;
}
public void tickAffectedHandlers() {
for (Pair<TransportedItemStackHandlerBehaviour, FanProcessingType> pair : affectedItemHandlers) {
TransportedItemStackHandlerBehaviour handler = pair.getKey();
Level world = handler.getWorld();
FanProcessingType processingType = pair.getRight();
handler.handleProcessingOnAllItems(transported -> {
if (world.isClientSide) {
processingType.spawnProcessingParticles(world, handler.getWorldPositionOf(transported));
return TransportedResult.doNothing();
}
TransportedResult applyProcessing = FanProcessing.applyProcessing(transported, world, processingType);
if (!applyProcessing.doesNothing() && source instanceof EncasedFanBlockEntity fan)
fan.award(AllAdvancements.FAN_PROCESSING);
return applyProcessing;
});
}
}
public void rebuild() {
@ -154,32 +174,38 @@ public class AirCurrent {
maxDistance = getFlowLimit(world, start, max, facing);
// Determine segments with transported fluids/gases
AirCurrentSegment currentSegment = new AirCurrentSegment();
segments.clear();
currentSegment.startOffset = 0;
AirCurrentSegment currentSegment = null;
FanProcessingType type = AllFanProcessingTypes.NONE;
int limit = (int) (maxDistance + .5f);
int searchStart = pushing ? 0 : limit;
int searchEnd = pushing ? limit : 0;
int limit = getLimit();
int searchStart = pushing ? 1 : limit;
int searchEnd = pushing ? limit : 1;
int searchStep = pushing ? 1 : -1;
int toOffset = pushing ? -1 : 0;
for (int i = searchStart; i * searchStep <= searchEnd * searchStep; i += searchStep) {
BlockPos currentPos = start.relative(direction, i);
FanProcessingType newType = FanProcessingType.getAt(world, currentPos);
if (newType != AllFanProcessingTypes.NONE)
if (newType != AllFanProcessingTypes.NONE) {
type = newType;
if (currentSegment.type != type || currentSegment.startOffset == 0) {
currentSegment.endOffset = i;
if (currentSegment.startOffset != 0)
segments.add(currentSegment);
}
if (currentSegment == null) {
currentSegment = new AirCurrentSegment();
currentSegment.startOffset = i;
currentSegment.startOffset = i + toOffset;
currentSegment.type = type;
} else if (currentSegment.type != type) {
currentSegment.endOffset = i + toOffset;
segments.add(currentSegment);
currentSegment = new AirCurrentSegment();
currentSegment.startOffset = i + toOffset;
currentSegment.type = type;
}
}
currentSegment.endOffset = searchEnd + searchStep;
segments.add(currentSegment);
if (currentSegment != null) {
currentSegment.endOffset = searchEnd + searchStep + toOffset;
segments.add(currentSegment);
}
// Build Bounding Box
if (maxDistance < 0.25f)
@ -194,133 +220,152 @@ public class AirCurrent {
.move(scale);
}
}
findAffectedHandlers();
}
public static float getFlowLimit(Level world, BlockPos start, float max, Direction facing) {
Vec3 directionVec = Vec3.atLowerCornerOf(facing.getNormal());
Vec3 planeVec = VecHelper.axisAlingedPlaneOf(directionVec);
for (int i = 0; i < max; i++) {
BlockPos currentPos = start.relative(facing, i + 1);
if (!world.isLoaded(currentPos)) {
return i;
}
// 4 Rays test for holes in the shapes blocking the flow
float offsetDistance = .25f;
Vec3[] offsets = new Vec3[] { planeVec.multiply(offsetDistance, offsetDistance, offsetDistance),
planeVec.multiply(-offsetDistance, -offsetDistance, offsetDistance),
planeVec.multiply(offsetDistance, -offsetDistance, -offsetDistance),
planeVec.multiply(-offsetDistance, offsetDistance, -offsetDistance), };
float limitedDistance = 0;
// Determine the distance of the air flow
Outer: for (int i = 1; i <= max; i++) {
BlockPos currentPos = start.relative(facing, i);
if (!world.isLoaded(currentPos))
break;
BlockState state = world.getBlockState(currentPos);
BlockState copycatState = CopycatBlock.getMaterial(world, currentPos);
if (shouldAlwaysPass(copycatState.isAir() ? state : copycatState))
if (shouldAlwaysPass(copycatState.isAir() ? state : copycatState)) {
continue;
VoxelShape voxelshape = state.getCollisionShape(world, currentPos, CollisionContext.empty());
if (voxelshape.isEmpty())
continue;
if (voxelshape == Shapes.block()) {
max = i - 1;
break;
}
for (Vec3 offset : offsets) {
Vec3 rayStart = VecHelper.getCenterOf(currentPos)
.subtract(directionVec.scale(.5f + 1 / 32f))
.add(offset);
Vec3 rayEnd = rayStart.add(directionVec.scale(1 + 1 / 32f));
BlockHitResult blockraytraceresult =
world.clipWithInteractionOverride(rayStart, rayEnd, currentPos, voxelshape, state);
if (blockraytraceresult == null)
continue Outer;
double distance = i - 1 + blockraytraceresult.getLocation()
.distanceTo(rayStart);
if (limitedDistance < distance)
limitedDistance = (float) distance;
VoxelShape shape = state.getCollisionShape(world, currentPos);
if (shape.isEmpty()) {
continue;
}
max = limitedDistance;
break;
if (shape == Shapes.block()) {
return i;
}
double shapeDepth = findMaxDepth(shape, facing);
if (shapeDepth == Double.POSITIVE_INFINITY) {
continue;
}
return Math.min((float) (i + shapeDepth + 1/32d), max);
}
return max;
}
private static final double[][] DEPTH_TEST_COORDINATES = {
{ 0.25, 0.25 },
{ 0.25, 0.75 },
{ 0.5, 0.5 },
{ 0.75, 0.25 },
{ 0.75, 0.75 }
};
// Finds the maximum depth of the shape when traveling in the given direction.
// The result is always positive.
// If there is a hole, the result will be Double.POSITIVE_INFINITY.
private static double findMaxDepth(VoxelShape shape, Direction direction) {
Direction.Axis axis = direction.getAxis();
Direction.AxisDirection axisDirection = direction.getAxisDirection();
double maxDepth = 0;
for (double[] coordinates : DEPTH_TEST_COORDINATES) {
double depth;
if (axisDirection == Direction.AxisDirection.POSITIVE) {
double min = shape.min(axis, coordinates[0], coordinates[1]);
if (min == Double.POSITIVE_INFINITY) {
return Double.POSITIVE_INFINITY;
}
depth = min;
} else {
double max = shape.max(axis, coordinates[0], coordinates[1]);
if (max == Double.NEGATIVE_INFINITY) {
return Double.POSITIVE_INFINITY;
}
depth = 1 - max;
}
if (depth > maxDepth) {
maxDepth = depth;
}
}
return maxDepth;
}
private static boolean shouldAlwaysPass(BlockState state) {
return AllTags.AllBlockTags.FAN_TRANSPARENT.matches(state);
}
private int getLimit() {
if ((float) (int) maxDistance == maxDistance) {
return (int) maxDistance;
} else {
return (int) maxDistance + 1;
}
}
public void findAffectedHandlers() {
Level world = source.getAirCurrentWorld();
BlockPos start = source.getAirCurrentPos();
affectedItemHandlers.clear();
int limit = getLimit();
for (int i = 1; i <= limit; i++) {
FanProcessingType segmentType = getTypeAt(i - 1);
for (int offset : Iterate.zeroAndOne) {
BlockPos pos = start.relative(direction, i)
.below(offset);
TransportedItemStackHandlerBehaviour behaviour =
BlockEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE);
if (behaviour != null) {
FanProcessingType type = FanProcessingType.getAt(world, pos);
if (type == AllFanProcessingTypes.NONE)
type = segmentType;
affectedItemHandlers.add(Pair.of(behaviour, type));
}
if (direction.getAxis()
.isVertical())
break;
}
}
}
public void findEntities() {
caughtEntities.clear();
caughtEntities = source.getAirCurrentWorld()
.getEntities(null, bounds);
}
public void findAffectedHandlers() {
Level world = source.getAirCurrentWorld();
BlockPos start = source.getAirCurrentPos();
affectedItemHandlers.clear();
for (int i = 0; i < maxDistance + 1; i++) {
FanProcessingType segmentType = getSegmentAt(i);
for (int offset : Iterate.zeroAndOne) {
BlockPos pos = start.relative(direction, i)
.below(offset);
TransportedItemStackHandlerBehaviour behaviour =
BlockEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE);
if (behaviour == null)
continue;
FanProcessingType type = FanProcessingType.getAt(world, pos);
if (type == AllFanProcessingTypes.NONE)
type = segmentType;
affectedItemHandlers.add(Pair.of(behaviour, type));
if (direction.getAxis()
.isVertical())
break;
}
}
}
public void tickAffectedHandlers() {
for (Pair<TransportedItemStackHandlerBehaviour, FanProcessingType> pair : affectedItemHandlers) {
TransportedItemStackHandlerBehaviour handler = pair.getKey();
Level world = handler.getWorld();
FanProcessingType processingType = pair.getRight();
handler.handleProcessingOnAllItems(transported -> {
if (world.isClientSide) {
processingType.spawnProcessingParticles(world, handler.getWorldPositionOf(transported));
return TransportedResult.doNothing();
public FanProcessingType getTypeAt(float offset) {
if (offset >= 0 && offset <= maxDistance) {
if (pushing) {
for (AirCurrentSegment airCurrentSegment : segments) {
if (offset <= airCurrentSegment.endOffset) {
return airCurrentSegment.type;
}
}
TransportedResult applyProcessing = FanProcessing.applyProcessing(transported, world, processingType);
if (!applyProcessing.doesNothing() && source instanceof EncasedFanBlockEntity fan)
fan.award(AllAdvancements.FAN_PROCESSING);
return applyProcessing;
});
}
}
private static boolean shouldAlwaysPass(BlockState state) {
return AllTags.AllBlockTags.FAN_TRANSPARENT.matches(state);
}
public FanProcessingType getSegmentAt(float offset) {
for (AirCurrentSegment airCurrentSegment : segments) {
if (offset > airCurrentSegment.endOffset && pushing)
continue;
if (offset < airCurrentSegment.endOffset && !pushing)
continue;
return airCurrentSegment.type;
} else {
for (AirCurrentSegment airCurrentSegment : segments) {
if (offset >= airCurrentSegment.endOffset) {
return airCurrentSegment.type;
}
}
}
}
return AllFanProcessingTypes.NONE;
}
public static class AirCurrentSegment {
FanProcessingType type;
int startOffset;
int endOffset;
private static class AirCurrentSegment {
private FanProcessingType type;
private int startOffset;
private int endOffset;
}
private static boolean isClientPlayerInAirCurrent;
@OnlyIn(Dist.CLIENT)
static AirCurrentSound flyingSound;
private static AirCurrentSound flyingSound;
@OnlyIn(Dist.CLIENT)
private static void enableClientPlayerSound(Entity e, float maxVolume) {
@ -345,7 +390,7 @@ public class AirCurrent {
@OnlyIn(Dist.CLIENT)
public static void tickClientPlayerSounds() {
if (!AirCurrent.isClientPlayerInAirCurrent && flyingSound != null)
if (!isClientPlayerInAirCurrent && flyingSound != null)
if (flyingSound.isFaded())
flyingSound.stopSound();
else
@ -353,12 +398,4 @@ public class AirCurrent {
isClientPlayerInAirCurrent = false;
}
public static boolean isPlayerCreativeFlying(Entity entity) {
if (entity instanceof Player) {
Player player = (Player) entity;
return player.isCreative() && player.getAbilities().flying;
}
return false;
}
}

View file

@ -34,9 +34,9 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
selectSprite(7);
Vec3 offset = VecHelper.offsetRandomly(Vec3.ZERO, random, .25f);
this.setPos(x + offset.x, y + offset.y, z + offset.z);
this.xo = x;
this.yo = y;
this.zo = z;
this.xo = this.x;
this.yo = this.y;
this.zo = this.z;
setColor(0xEEEEEE);
setAlpha(.25f);
}
@ -97,15 +97,13 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
this.zd *= 0.7;
}
this.move(this.xd, this.yd, this.zd);
}
}
private FanProcessingType getType(double distance) {
if (source.getAirCurrent() == null)
return AllFanProcessingTypes.NONE;
return source.getAirCurrent().getSegmentAt((float) distance);
return source.getAirCurrent().getTypeAt((float) distance);
}
public int getLightColor(float partialTick) {
@ -124,6 +122,7 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
this.spriteSet = animatedSprite;
}
@Override
public Particle createParticle(AirFlowParticleData data, ClientLevel worldIn, double x, double y, double z,
double xSpeed, double ySpeed, double zSpeed) {
BlockEntity be = worldIn.getBlockEntity(new BlockPos(data.posX, data.posY, data.posZ));

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.kinetics.fan.processing;
import static com.simibubi.create.content.processing.burner.BlazeBurnerBlock.getHeatLevelOf;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -10,8 +8,9 @@ import java.util.Optional;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.AllTags.AllFluidTags;
import com.simibubi.create.Create;
import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe.HauntingWrapper;
import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe.SplashingWrapper;
@ -48,13 +47,10 @@ import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.crafting.SmeltingRecipe;
import net.minecraft.world.item.crafting.SmokingRecipe;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.CampfireBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.RecipeWrapper;
@ -140,9 +136,18 @@ public class AllFanProcessingTypes {
@Override
public boolean isValidAt(Level level, BlockPos pos) {
FluidState fluidState = level.getFluidState(pos);
if (AllFluidTags.FAN_PROCESSING_CATALYSTS_BLASTING.matches(fluidState)) {
return true;
}
BlockState blockState = level.getBlockState(pos);
Block block = blockState.getBlock();
return block == Blocks.LAVA || getHeatLevelOf(blockState).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING);
if (AllBlockTags.FAN_PROCESSING_CATALYSTS_BLASTING.matches(blockState)) {
if (blockState.hasProperty(BlazeBurnerBlock.HEAT_LEVEL) && !blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING)) {
return false;
}
return true;
}
return false;
}
@Override
@ -233,15 +238,21 @@ public class AllFanProcessingTypes {
@Override
public boolean isValidAt(Level level, BlockPos pos) {
FluidState fluidState = level.getFluidState(pos);
if (AllFluidTags.FAN_PROCESSING_CATALYSTS_HAUNTING.matches(fluidState)) {
return true;
}
BlockState blockState = level.getBlockState(pos);
Block block = blockState.getBlock();
return block == Blocks.SOUL_FIRE
|| block == Blocks.SOUL_CAMPFIRE && blockState.getOptionalValue(CampfireBlock.LIT)
.orElse(false)
|| AllBlocks.LIT_BLAZE_BURNER.has(blockState)
&& blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE)
.map(flame -> flame == LitBlazeBurnerBlock.FlameType.SOUL)
.orElse(false);
if (AllBlockTags.FAN_PROCESSING_CATALYSTS_HAUNTING.matches(blockState)) {
if (blockState.is(BlockTags.CAMPFIRES) && blockState.hasProperty(CampfireBlock.LIT) && !blockState.getValue(CampfireBlock.LIT)) {
return false;
}
if (blockState.hasProperty(LitBlazeBurnerBlock.FLAME_TYPE) && blockState.getValue(LitBlazeBurnerBlock.FLAME_TYPE) != LitBlazeBurnerBlock.FlameType.SOUL) {
return false;
}
return true;
}
return false;
}
@Override
@ -347,16 +358,24 @@ public class AllFanProcessingTypes {
@Override
public boolean isValidAt(Level level, BlockPos pos) {
FluidState fluidState = level.getFluidState(pos);
if (AllFluidTags.FAN_PROCESSING_CATALYSTS_SMOKING.matches(fluidState)) {
return true;
}
BlockState blockState = level.getBlockState(pos);
Block block = blockState.getBlock();
return block == Blocks.FIRE
|| blockState.is(BlockTags.CAMPFIRES) && blockState.getOptionalValue(CampfireBlock.LIT)
.orElse(false)
|| AllBlocks.LIT_BLAZE_BURNER.has(blockState)
&& blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE)
.map(flame -> flame == LitBlazeBurnerBlock.FlameType.REGULAR)
.orElse(false)
|| getHeatLevelOf(blockState) == BlazeBurnerBlock.HeatLevel.SMOULDERING;
if (AllBlockTags.FAN_PROCESSING_CATALYSTS_SMOKING.matches(blockState)) {
if (blockState.is(BlockTags.CAMPFIRES) && blockState.hasProperty(CampfireBlock.LIT) && !blockState.getValue(CampfireBlock.LIT)) {
return false;
}
if (blockState.hasProperty(LitBlazeBurnerBlock.FLAME_TYPE) && blockState.getValue(LitBlazeBurnerBlock.FLAME_TYPE) != LitBlazeBurnerBlock.FlameType.REGULAR) {
return false;
}
if (blockState.hasProperty(BlazeBurnerBlock.HEAT_LEVEL) && blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL) != BlazeBurnerBlock.HeatLevel.SMOULDERING) {
return false;
}
return true;
}
return false;
}
@Override
@ -420,8 +439,14 @@ public class AllFanProcessingTypes {
@Override
public boolean isValidAt(Level level, BlockPos pos) {
FluidState fluidState = level.getFluidState(pos);
Fluid fluid = fluidState.getType();
return fluid == Fluids.WATER || fluid == Fluids.FLOWING_WATER;
if (AllFluidTags.FAN_PROCESSING_CATALYSTS_SPLASHING.matches(fluidState)) {
return true;
}
BlockState blockState = level.getBlockState(pos);
if (AllBlockTags.FAN_PROCESSING_CATALYSTS_SPLASHING.matches(blockState)) {
return true;
}
return false;
}
@Override

View file

@ -16,6 +16,8 @@ public class TurntableHandler {
Minecraft mc = Minecraft.getInstance();
BlockPos pos = mc.player.blockPosition();
if (mc.gameMode == null)
return;
if (!AllBlocks.TURNTABLE.has(mc.level.getBlockState(pos)))
return;
if (!mc.player.onGround())

View file

@ -20,6 +20,7 @@ import com.simibubi.create.content.logistics.funnel.FunnelBlock;
import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryTrackerBehaviour;
import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode;
import com.simibubi.create.foundation.particle.AirParticleData;
@ -81,6 +82,8 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
int airCurrentUpdateCooldown;
int entitySearchCooldown;
VersionedInventoryTrackerBehaviour invVersionTracker;
LazyOptional<IItemHandler> capAbove;
LazyOptional<IItemHandler> capBelow;
@ -101,6 +104,7 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen((d) -> canDirectlyInsertCached()));
behaviours.add(invVersionTracker = new VersionedInventoryTrackerBehaviour(this));
registerAwardables(behaviours, AllAdvancements.CHUTE);
}
@ -336,15 +340,20 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
private void handleInput(IItemHandler inv, float startLocation) {
if (inv == null)
return;
if (invVersionTracker.stillWaiting(inv))
return;
Predicate<ItemStack> canAccept = this::canAcceptItem;
int count = getExtractionAmount();
ExtractionCountMode mode = getExtractionMode();
if (mode == ExtractionCountMode.UPTO || !ItemHelper.extract(inv, canAccept, mode, count, true)
.isEmpty()) {
ItemStack extracted = ItemHelper.extract(inv, canAccept, mode, count, false);
if (!extracted.isEmpty())
if (!extracted.isEmpty()) {
setItem(extracted, startLocation);
return;
}
}
invVersionTracker.awaitNewVersion(inv);
}
private boolean handleDownwardOutput(boolean simulate) {
@ -359,12 +368,16 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
if (capBelow.isPresent()) {
if (level.isClientSide && !isVirtual())
return false;
ItemStack remainder = ItemHandlerHelper.insertItemStacked(capBelow.orElse(null), item, simulate);
IItemHandler inv = capBelow.orElse(null);
if (invVersionTracker.stillWaiting(inv))
return false;
ItemStack remainder = ItemHandlerHelper.insertItemStacked(inv, item, simulate);
ItemStack held = getItem();
if (!simulate)
setItem(remainder, itemPosition.getValue(0));
if (remainder.getCount() != held.getCount())
return true;
invVersionTracker.awaitNewVersion(inv);
if (direction == Direction.DOWN)
return false;
}
@ -414,10 +427,16 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
if (level.isClientSide && !isVirtual() && !ChuteBlock.isChute(stateAbove))
return false;
int countBefore = item.getCount();
ItemStack remainder = ItemHandlerHelper.insertItemStacked(capAbove.orElse(null), item, simulate);
IItemHandler inv = capAbove.orElse(null);
if (invVersionTracker.stillWaiting(inv))
return false;
ItemStack remainder = ItemHandlerHelper.insertItemStacked(inv, item, simulate);
if (!simulate)
item = remainder;
return countBefore != remainder.getCount();
if (countBefore != remainder.getCount())
return true;
invVersionTracker.awaitNewVersion(inv);
return false;
}
}
@ -502,6 +521,7 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
public void setItem(ItemStack stack, float insertionPos) {
item = stack;
itemPosition.startWithValue(insertionPos);
invVersionTracker.reset();
if (!level.isClientSide) {
notifyUpdate();
award(AllAdvancements.CHUTE);

View file

@ -51,7 +51,8 @@ public class SmartChuteBlockEntity extends ChuteBlockEntity {
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(filtering =
new FilteringBehaviour(this, new SmartChuteFilterSlotPositioning()).showCountWhen(this::isExtracting));
new FilteringBehaviour(this, new SmartChuteFilterSlotPositioning()).showCountWhen(this::isExtracting)
.withCallback($ -> invVersionTracker.reset()));
super.addBehaviours(behaviours);
}

View file

@ -240,7 +240,7 @@ public class DepotBehaviour extends BlockEntityBehaviour {
public void addSubBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(new DirectBeltInputBehaviour(blockEntity).allowingBeltFunnels()
.setInsertionHandler(this::tryInsertingFromSide));
.setInsertionHandler(this::tryInsertingFromSide).considerOccupiedWhen(this::isOccupied));
transportedHandler = new TransportedItemStackHandlerBehaviour(blockEntity, this::applyToAllItems)
.withStackPlacement(this::getWorldPositionOf);
behaviours.add(transportedHandler);
@ -339,14 +339,20 @@ public class DepotBehaviour extends BlockEntityBehaviour {
return lazyItemHandler.cast();
}
private boolean isOccupied(Direction side) {
if (!getHeldItemStack().isEmpty() && !canMergeItems())
return true;
if (!isOutputEmpty() && !canMergeItems())
return true;
if (!canAcceptItems.get())
return true;
return false;
}
private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) {
ItemStack inserted = transportedStack.stack;
if (!getHeldItemStack().isEmpty() && !canMergeItems())
return inserted;
if (!isOutputEmpty() && !canMergeItems())
return inserted;
if (!canAcceptItems.get())
if (isOccupied(side))
return inserted;
int size = transportedStack.stack.getCount();

View file

@ -8,7 +8,6 @@ import javax.annotation.Nonnull;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllKeys;
import com.simibubi.create.content.fluids.transfer.GenericItemEmptying;
import com.simibubi.create.content.logistics.filter.AttributeFilterMenu.WhitelistMode;
import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.CreateLang;
@ -34,7 +33,6 @@ import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.network.NetworkHooks;
@ -189,146 +187,7 @@ public class FilterItem extends Item implements MenuProvider {
return newInv;
}
public static boolean test(Level world, ItemStack stack, ItemStack filter) {
return test(world, stack, filter, false);
}
public static boolean test(Level world, FluidStack stack, ItemStack filter) {
return test(world, stack, filter, true);
}
public static boolean test(Level world, ItemStack stack, ItemStack filter, boolean matchNBT) {
if (filter.isEmpty())
return true;
if (!(filter.getItem() instanceof FilterItem))
return testDirect(filter, stack, matchNBT);
boolean defaults = !filter.hasTag();
if (defaults) {
return testDirect(filter, stack, matchNBT);
}
if (AllItems.FILTER.get() == filter.getItem()) {
ItemStackHandler filterItems = getFilterItems(filter);
boolean respectNBT = defaults ? false
: filter.getTag()
.getBoolean("RespectNBT");
boolean blacklist = defaults ? false
: filter.getTag()
.getBoolean("Blacklist");
boolean isEmpty = true;
for (int slot = 0; slot < filterItems.getSlots(); slot++) {
ItemStack stackInSlot = filterItems.getStackInSlot(slot);
if (stackInSlot.isEmpty())
continue;
isEmpty = false;
boolean matches = test(world, stack, stackInSlot, respectNBT);
if (matches)
return !blacklist;
}
if (isEmpty) {
return testDirect(filter, stack, matchNBT);
}
return blacklist;
}
if (AllItems.ATTRIBUTE_FILTER.get() == filter.getItem()) {
ListTag attributes = defaults ? new ListTag()
: filter.getTag()
.getList("MatchedAttributes", Tag.TAG_COMPOUND);
if (attributes.isEmpty()) {
return testDirect(filter, stack, matchNBT);
}
WhitelistMode whitelistMode = WhitelistMode.values()[defaults ? 0
: filter.getTag()
.getInt("WhitelistMode")];
for (Tag inbt : attributes) {
CompoundTag compound = (CompoundTag) inbt;
ItemAttribute attribute = ItemAttribute.fromNBT(compound);
if (attribute == null)
continue;
boolean matches = attribute.appliesTo(stack, world) != compound.getBoolean("Inverted");
if (matches) {
switch (whitelistMode) {
case BLACKLIST:
return false;
case WHITELIST_CONJ:
continue;
case WHITELIST_DISJ:
return true;
}
} else {
switch (whitelistMode) {
case BLACKLIST:
continue;
case WHITELIST_CONJ:
return false;
case WHITELIST_DISJ:
continue;
}
}
}
switch (whitelistMode) {
case BLACKLIST:
return true;
case WHITELIST_CONJ:
return true;
case WHITELIST_DISJ:
return false;
}
}
return false;
}
public static boolean test(Level world, FluidStack stack, ItemStack filter, boolean matchNBT) {
if (filter.isEmpty())
return true;
if (stack.isEmpty())
return false;
if (!(filter.getItem() instanceof FilterItem)) {
if (!GenericItemEmptying.canItemBeEmptied(world, filter))
return false;
FluidStack fluidInFilter = GenericItemEmptying.emptyItem(world, filter, true)
.getFirst();
if (fluidInFilter == null)
return false;
if (!matchNBT)
return fluidInFilter.getFluid()
.isSame(stack.getFluid());
boolean fluidEqual = fluidInFilter.isFluidEqual(stack);
return fluidEqual;
}
boolean defaults = !filter.hasTag();
if (AllItems.FILTER.get() == filter.getItem()) {
ItemStackHandler filterItems = getFilterItems(filter);
boolean respectNBT = defaults ? false
: filter.getTag()
.getBoolean("RespectNBT");
boolean blacklist = defaults ? false
: filter.getTag()
.getBoolean("Blacklist");
for (int slot = 0; slot < filterItems.getSlots(); slot++) {
ItemStack stackInSlot = filterItems.getStackInSlot(slot);
if (stackInSlot.isEmpty())
continue;
boolean matches = test(world, stack, stackInSlot, respectNBT);
if (matches)
return !blacklist;
}
return blacklist;
}
return false;
}
private static boolean testDirect(ItemStack filter, ItemStack stack, boolean matchNBT) {
public static boolean testDirect(ItemStack filter, ItemStack stack, boolean matchNBT) {
if (matchNBT) {
return ItemHandlerHelper.canItemStacksStack(filter, stack);
} else {

View file

@ -0,0 +1,235 @@
package com.simibubi.create.content.logistics.filter;
import java.util.ArrayList;
import java.util.List;
import com.simibubi.create.AllItems;
import com.simibubi.create.content.fluids.transfer.GenericItemEmptying;
import net.createmod.catnip.utility.Pair;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.ItemStackHandler;
public class FilterItemStack {
private ItemStack filterItemStack;
private boolean fluidExtracted;
private FluidStack filterFluidStack;
public static FilterItemStack of(ItemStack filter) {
if (filter.hasTag()) {
if (AllItems.FILTER.isIn(filter))
return new ListFilterItemStack(filter);
if (AllItems.ATTRIBUTE_FILTER.isIn(filter))
return new AttributeFilterItemStack(filter);
}
return new FilterItemStack(filter);
}
public static FilterItemStack of(CompoundTag tag) {
return of(ItemStack.of(tag));
}
public static FilterItemStack empty() {
return of(ItemStack.EMPTY);
}
public boolean isEmpty() {
return filterItemStack.isEmpty();
}
public CompoundTag serializeNBT() {
return filterItemStack.serializeNBT();
}
public ItemStack item() {
return filterItemStack;
}
public FluidStack fluid(Level level) {
resolveFluid(level);
return filterFluidStack;
}
public boolean isFilterItem() {
return filterItemStack.getItem() instanceof FilterItem;
}
//
public boolean test(Level world, ItemStack stack) {
return test(world, stack, false);
}
public boolean test(Level world, FluidStack stack) {
return test(world, stack, true);
}
public boolean test(Level world, ItemStack stack, boolean matchNBT) {
if (isEmpty())
return true;
return FilterItem.testDirect(filterItemStack, stack, matchNBT);
}
public boolean test(Level world, FluidStack stack, boolean matchNBT) {
if (isEmpty())
return true;
if (stack.isEmpty())
return false;
resolveFluid(world);
if (filterFluidStack.isEmpty())
return false;
if (!matchNBT)
return filterFluidStack.getFluid()
.isSame(stack.getFluid());
return filterFluidStack.isFluidEqual(stack);
}
//
private void resolveFluid(Level world) {
if (!fluidExtracted) {
fluidExtracted = true;
if (GenericItemEmptying.canItemBeEmptied(world, filterItemStack))
filterFluidStack = GenericItemEmptying.emptyItem(world, filterItemStack, true)
.getFirst();
}
}
protected FilterItemStack(ItemStack filter) {
filterItemStack = filter;
filterFluidStack = FluidStack.EMPTY;
fluidExtracted = false;
}
public static class ListFilterItemStack extends FilterItemStack {
public List<FilterItemStack> containedItems;
public boolean shouldRespectNBT;
public boolean isBlacklist;
protected ListFilterItemStack(ItemStack filter) {
super(filter);
boolean defaults = !filter.hasTag();
containedItems = new ArrayList<>();
ItemStackHandler items = FilterItem.getFilterItems(filter);
for (int i = 0; i < items.getSlots(); i++) {
ItemStack stackInSlot = items.getStackInSlot(i);
if (!stackInSlot.isEmpty())
containedItems.add(FilterItemStack.of(stackInSlot));
}
shouldRespectNBT = !defaults ? false
: filter.getTag()
.getBoolean("RespectNBT");
isBlacklist = defaults ? false
: filter.getTag()
.getBoolean("Blacklist");
}
@Override
public boolean test(Level world, ItemStack stack, boolean matchNBT) {
if (containedItems.isEmpty())
return super.test(world, stack, matchNBT);
for (FilterItemStack filterItemStack : containedItems)
if (filterItemStack.test(world, stack, shouldRespectNBT))
return !isBlacklist;
return isBlacklist;
}
@Override
public boolean test(Level world, FluidStack stack, boolean matchNBT) {
for (FilterItemStack filterItemStack : containedItems)
if (filterItemStack.test(world, stack, shouldRespectNBT))
return !isBlacklist;
return isBlacklist;
}
}
public static class AttributeFilterItemStack extends FilterItemStack {
public enum WhitelistMode {
WHITELIST_DISJ, WHITELIST_CONJ, BLACKLIST;
}
public WhitelistMode whitelistMode;
public List<Pair<ItemAttribute, Boolean>> attributeTests;
protected AttributeFilterItemStack(ItemStack filter) {
super(filter);
boolean defaults = !filter.hasTag();
attributeTests = new ArrayList<>();
whitelistMode = WhitelistMode.values()[defaults ? 0
: filter.getTag()
.getInt("WhitelistMode")];
ListTag attributes = defaults ? new ListTag()
: filter.getTag()
.getList("MatchedAttributes", Tag.TAG_COMPOUND);
for (Tag inbt : attributes) {
CompoundTag compound = (CompoundTag) inbt;
ItemAttribute attribute = ItemAttribute.fromNBT(compound);
if (attribute != null)
attributeTests.add(Pair.of(attribute, compound.getBoolean("Inverted")));
}
}
@Override
public boolean test(Level world, FluidStack stack, boolean matchNBT) {
return false;
}
@Override
public boolean test(Level world, ItemStack stack, boolean matchNBT) {
if (attributeTests.isEmpty())
return super.test(world, stack, matchNBT);
for (Pair<ItemAttribute, Boolean> test : attributeTests) {
ItemAttribute attribute = test.getFirst();
boolean inverted = test.getSecond();
boolean matches = attribute.appliesTo(stack, world) != inverted;
if (matches) {
switch (whitelistMode) {
case BLACKLIST -> {
return false;
}
case WHITELIST_CONJ -> {
continue;
}
case WHITELIST_DISJ -> {
return true;
}
}
} else {
switch (whitelistMode) {
case BLACKLIST, WHITELIST_DISJ -> {
continue;
}
case WHITELIST_CONJ -> {
return false;
}
}
}
}
return switch (whitelistMode) {
case BLACKLIST, WHITELIST_CONJ -> true;
case WHITELIST_DISJ -> false;
};
}
}
}

View file

@ -3,6 +3,8 @@ package com.simibubi.create.content.logistics.funnel;
import java.lang.ref.WeakReference;
import java.util.List;
import org.apache.commons.lang3.mutable.MutableBoolean;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPackets;
@ -18,6 +20,7 @@ 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.InvManipulationBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryTrackerBehaviour;
import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode;
import com.simibubi.create.infrastructure.config.AllConfigs;
@ -42,6 +45,7 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
private FilteringBehaviour filtering;
private InvManipulationBehaviour invManipulation;
private VersionedInventoryTrackerBehaviour invVersionTracker;
private int extractionCooldown;
private WeakReference<ItemEntity> lastObserved; // In-world Extractors only
@ -111,6 +115,9 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
}
private void activateExtractor() {
if (invVersionTracker.stillWaiting(invManipulation))
return;
BlockState blockState = getBlockState();
Direction facing = AbstractFunnelBlock.getFunnelFacing(blockState);
@ -140,8 +147,10 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
ExtractionCountMode mode = getModeToExtract();
ItemStack stack = invManipulation.simulate()
.extract(mode, amountToExtract);
if (stack.isEmpty())
if (stack.isEmpty()) {
invVersionTracker.awaitNewVersion(invManipulation);
return;
}
for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class, area)) {
lastObserved = new WeakReference<>(itemEntity);
return;
@ -189,6 +198,9 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
}
private void activateExtractingBeltFunnel() {
if (invVersionTracker.stillWaiting(invManipulation))
return;
BlockState blockState = getBlockState();
Direction facing = blockState.getValue(BeltFunnelBlock.HORIZONTAL_FACING);
DirectBeltInputBehaviour inputBehaviour =
@ -198,14 +210,24 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
return;
if (!inputBehaviour.canInsertFromSide(facing))
return;
if (inputBehaviour.isOccupied(facing))
return;
int amountToExtract = getAmountToExtract();
ExtractionCountMode mode = getModeToExtract();
ItemStack stack =
invManipulation.extract(mode, amountToExtract, s -> inputBehaviour.handleInsertion(s, facing, true)
.isEmpty());
if (stack.isEmpty())
MutableBoolean deniedByInsertion = new MutableBoolean(false);
ItemStack stack = invManipulation.extract(mode, amountToExtract, s -> {
ItemStack handleInsertion = inputBehaviour.handleInsertion(s, facing, true);
if (handleInsertion.isEmpty())
return true;
deniedByInsertion.setTrue();
return false;
});
if (stack.isEmpty()) {
if (deniedByInsertion.isFalse())
invVersionTracker.awaitNewVersion(invManipulation.getInventory());
return;
}
flap(false);
onTransfer(stack);
inputBehaviour.handleInsertion(stack, facing, false);
@ -237,12 +259,15 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
new InvManipulationBehaviour(this, (w, p, s) -> new BlockFace(p, AbstractFunnelBlock.getFunnelFacing(s)
.getOpposite()));
behaviours.add(invManipulation);
behaviours.add(invVersionTracker = new VersionedInventoryTrackerBehaviour(this));
filtering = new FilteringBehaviour(this, new FunnelFilterSlotPositioning());
filtering.showCountWhen(this::supportsAmountOnFilter);
filtering.onlyActiveWhen(this::supportsFiltering);
filtering.withCallback($ -> invVersionTracker.reset());
behaviours.add(filtering);
behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::supportsDirectBeltInput)
.setInsertionHandler(this::handleDirectBeltInput));
registerAwardables(behaviours, AllAdvancements.FUNNEL);

View file

@ -4,7 +4,7 @@ import java.util.List;
import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour;
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.logistics.filter.FilterItem;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.foundation.item.ItemHelper;
import net.minecraft.core.BlockPos;
@ -71,14 +71,14 @@ public class FunnelMovementBehaviour implements MovementBehaviour {
.isEmpty())
return;
ItemStack filter = getFilter(context);
FilterItemStack filter = context.getFilterFromBE();
int filterAmount = context.blockEntityData.getInt("FilterAmount");
boolean upTo = context.blockEntityData.getBoolean("UpTo");
if (filterAmount <= 0)
filterAmount = hasFilter ? 64 : 1;
ItemStack extract = ItemHelper.extract(context.contraption.getSharedInventory(),
s -> FilterItem.test(world, s, filter),
s -> filter.test(world, s),
upTo ? ItemHelper.ExtractionCountMode.UPTO : ItemHelper.ExtractionCountMode.EXACTLY, filterAmount, false);
if (extract.isEmpty())
@ -97,13 +97,13 @@ public class FunnelMovementBehaviour implements MovementBehaviour {
private void succ(MovementContext context, BlockPos pos) {
Level world = context.world;
List<ItemEntity> items = world.getEntitiesOfClass(ItemEntity.class, new AABB(pos));
ItemStack filter = getFilter(context);
FilterItemStack filter = context.getFilterFromBE();
for (ItemEntity item : items) {
if (!item.isAlive())
continue;
ItemStack toInsert = item.getItem();
if (!filter.isEmpty() && !FilterItem.test(context.world, toInsert, filter))
if (!filter.test(context.world, toInsert))
continue;
ItemStack remainder =
ItemHandlerHelper.insertItemStacked(context.contraption.getSharedInventory(), toInsert, false);
@ -124,8 +124,4 @@ public class FunnelMovementBehaviour implements MovementBehaviour {
return true;
}
private ItemStack getFilter(MovementContext context) {
return hasFilter ? ItemStack.of(context.blockEntityData.getCompound("Filter")) : ItemStack.EMPTY;
}
}

View file

@ -53,7 +53,7 @@ public class ItemVaultBlock extends Block implements IWrenchable, IBE<ItemVaultB
@Override
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
if (pContext.getPlayer() == null || !pContext.getPlayer()
.isSteppingCarefully()) {
.isShiftKeyDown()) {
BlockState placedOn = pContext.getLevel()
.getBlockState(pContext.getClickedPos()
.relative(pContext.getClickedFace()

View file

@ -7,6 +7,7 @@ import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryWrapper;
import com.simibubi.create.infrastructure.config.AllConfigs;
import net.minecraft.core.BlockPos;
@ -260,8 +261,8 @@ public class ItemVaultBlockEntity extends SmartBlockEntity implements IMultiBloc
}
}
CombinedInvWrapper combinedInvWrapper = new CombinedInvWrapper(invs);
itemCapability = LazyOptional.of(() -> combinedInvWrapper);
IItemHandler itemHandler = new VersionedInventoryWrapper(new CombinedInvWrapper(invs));
itemCapability = LazyOptional.of(() -> itemHandler);
}
public static int getMaxLength(int radius) {

View file

@ -54,7 +54,7 @@ public class ItemVaultItem extends BlockItem {
Player player = ctx.getPlayer();
if (player == null)
return;
if (player.isSteppingCarefully())
if (player.isShiftKeyDown())
return;
Direction face = ctx.getClickedFace();
ItemStack stack = ctx.getItemInHand();

View file

@ -34,7 +34,7 @@ public class ExperienceNuggetItem extends Item {
return InteractionResultHolder.consume(itemInHand);
}
int amountUsed = pPlayer.isSteppingCarefully() ? 1 : itemInHand.getCount();
int amountUsed = pPlayer.isShiftKeyDown() ? 1 : itemInHand.getCount();
int total = Mth.ceil(3f * amountUsed);
int maxOrbs = amountUsed == 1 ? 1 : 5;
int valuePer = Math.max(1, 1 + total / maxOrbs);

View file

@ -28,6 +28,7 @@ import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipul
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.item.SmartInventory;
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.CreateLang;
import net.createmod.catnip.utility.AnimationTickHolder;
@ -602,7 +603,7 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
public static HeatLevel getHeatLevelOf(BlockState state) {
if (state.hasProperty(BlazeBurnerBlock.HEAT_LEVEL))
return state.getValue(BlazeBurnerBlock.HEAT_LEVEL);
return AllTags.AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE;
return AllTags.AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) && BlockHelper.isNotUnheated(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE;
}
public Couple<SmartFluidTankBehaviour> getTanks() {

View file

@ -3,17 +3,18 @@ package com.simibubi.create.content.processing.burner;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.annotation.ParametersAreNonnullByDefault;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTags.AllEntityTags;
import net.createmod.catnip.platform.CatnipServices;
import net.createmod.catnip.utility.VecHelper;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.random.WeightedEntry.Wrapper;
@ -21,7 +22,6 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.monster.Blaze;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
@ -91,11 +91,9 @@ public class BlazeBurnerBlockItem extends BlockItem {
possibleSpawns.add(spawner.nextSpawnData);
}
ResourceLocation blazeId = CatnipServices.REGISTRIES.getKeyOrThrow(EntityType.BLAZE);
for (SpawnData e : possibleSpawns) {
ResourceLocation spawnerEntityId = new ResourceLocation(e.entityToSpawn()
.getString("id"));
if (!spawnerEntityId.equals(blazeId))
Optional<EntityType<?>> optionalEntity = EntityType.by(e.entityToSpawn());
if (optionalEntity.isEmpty() || !AllEntityTags.BLAZE_BURNER_CAPTURABLE.matches(optionalEntity.get()))
continue;
spawnCaptureEffects(world, VecHelper.getCenterOf(pos));
@ -114,7 +112,7 @@ public class BlazeBurnerBlockItem extends BlockItem {
InteractionHand hand) {
if (hasCapturedBlaze())
return InteractionResult.PASS;
if (!(entity instanceof Blaze))
if (!AllEntityTags.BLAZE_BURNER_CAPTURABLE.matches(entity))
return InteractionResult.PASS;
Level world = player.level();

View file

@ -33,12 +33,11 @@ public class AnalogLeverInstance extends BlockEntityInstance<AnalogLeverBlockEnt
indicator = mat.getModel(AllPartialModels.ANALOG_LEVER_INDICATOR, blockState)
.createInstance();
transform(indicator);
AttachFace face = blockState.getValue(AnalogLeverBlock.FACE);
rX = face == AttachFace.FLOOR ? 0 : face == AttachFace.WALL ? 90 : 180;
rY = AngleHelper.horizontalAngle(blockState.getValue(AnalogLeverBlock.FACING));
transform(indicator.loadIdentity());
animateLever();
}

View file

@ -139,7 +139,7 @@ public class DisplayLinkBlock extends WrenchableDirectionalBlock implements IBE<
BlockHitResult pHit) {
if (pPlayer == null)
return InteractionResult.PASS;
if (pPlayer.isSteppingCarefully())
if (pPlayer.isShiftKeyDown())
return InteractionResult.PASS;
DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> withBlockEntityDo(pLevel, pPos, be -> this.displayScreen(be, pPlayer)));

View file

@ -57,7 +57,7 @@ public class DisplayLinkBlockItem extends BlockItem {
if (player == null)
return InteractionResult.FAIL;
if (player.isSteppingCarefully() && stack.hasTag()) {
if (player.isShiftKeyDown() && stack.hasTag()) {
if (level.isClientSide)
return InteractionResult.SUCCESS;
player.displayClientMessage(CreateLang.translateDirect("display_link.clear"), true);

View file

@ -83,7 +83,7 @@ public class SmartObserverBlock extends DirectedDirectionalBlock implements IBE<
if (preferredFacing == null) {
Direction facing = context.getNearestLookingDirection();
preferredFacing = context.getPlayer() != null && context.getPlayer()
.isSteppingCarefully() ? facing : facing.getOpposite();
.isShiftKeyDown() ? facing : facing.getOpposite();
}
if (preferredFacing.getAxis() == Axis.Y) {
@ -101,7 +101,7 @@ public class SmartObserverBlock extends DirectedDirectionalBlock implements IBE<
@Override
public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) {
return isSignalSource(blockState) && (side == null || side != blockState.getValue(FACING)
return isSignalSource(blockState) && (side == null || side != getTargetDirection(blockState)
.getOpposite()) ? 15 : 0;
}

View file

@ -14,6 +14,7 @@ import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringB
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.utility.BlockFace;
import net.createmod.catnip.utility.Iterate;
@ -31,6 +32,10 @@ public class SmartObserverBlockEntity extends SmartBlockEntity {
private FilteringBehaviour filtering;
private InvManipulationBehaviour observedInventory;
private TankManipulationBehaviour observedTank;
private VersionedInventoryTrackerBehaviour invVersionTracker;
private boolean sustainSignal;
public int turnOffTicks = 0;
public SmartObserverBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
@ -40,7 +45,9 @@ public class SmartObserverBlockEntity extends SmartBlockEntity {
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot(false)));
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));
@ -105,11 +112,23 @@ public class SmartObserverBlockEntity extends SmartBlockEntity {
return;
}
if (!observedInventory.simulate()
.extract()
.isEmpty()) {
activate();
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()

View file

@ -54,7 +54,7 @@ public class ThresholdSwitchBlock extends DirectedDirectionalBlock implements IB
@Override
public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, Direction side) {
return side != null && side.getOpposite() != state.getValue(FACING);
return side != null && side.getOpposite() != getTargetDirection(state);
}
@Override
@ -64,7 +64,7 @@ public class ThresholdSwitchBlock extends DirectedDirectionalBlock implements IB
@Override
public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) {
if (side == blockState.getValue(FACING)
if (side == getTargetDirection(blockState)
.getOpposite())
return 0;
return getBlockEntityOptional(blockAccess, pos).filter(ThresholdSwitchBlockEntity::isPowered)
@ -121,7 +121,7 @@ public class ThresholdSwitchBlock extends DirectedDirectionalBlock implements IB
if (preferredFacing == null) {
Direction facing = context.getNearestLookingDirection();
preferredFacing = context.getPlayer() != null && context.getPlayer()
.isSteppingCarefully() ? facing : facing.getOpposite();
.isShiftKeyDown() ? facing : facing.getOpposite();
}
if (preferredFacing.getAxis() == Axis.Y) {

View file

@ -12,6 +12,7 @@ import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringB
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.utility.BlockFace;
import net.minecraft.core.BlockPos;
@ -39,6 +40,7 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity {
private FilteringBehaviour filtering;
private InvManipulationBehaviour observedInventory;
private TankManipulationBehaviour observedTank;
private VersionedInventoryTrackerBehaviour invVersionTracker;
public ThresholdSwitchBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
@ -107,18 +109,26 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity {
} else if (observedInventory.hasInventory() || observedTank.hasInventory()) {
if (observedInventory.hasInventory()) {
// Item inventory
IItemHandler inv = observedInventory.getInventory();
for (int slot = 0; slot < inv.getSlots(); slot++) {
ItemStack stackInSlot = inv.getStackInSlot(slot);
int space = Math.min(stackInSlot.getMaxStackSize(), inv.getSlotLimit(slot));
int count = stackInSlot.getCount();
if (space == 0)
continue;
if (invVersionTracker.stillWaiting(inv)) {
occupied = prevLevel;
totalSpace = 1f;
totalSpace += 1;
if (filtering.test(stackInSlot))
occupied += count * (1f / space);
} else {
invVersionTracker.awaitNewVersion(inv);
for (int slot = 0; slot < inv.getSlots(); slot++) {
ItemStack stackInSlot = inv.getStackInSlot(slot);
int space = Math.min(stackInSlot.getMaxStackSize(), inv.getSlotLimit(slot));
int count = stackInSlot.getCount();
if (space == 0)
continue;
totalSpace += 1;
if (filtering.test(stackInSlot))
occupied += count * (1f / space);
}
}
}
@ -195,7 +205,12 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity {
@Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot(true))
.withCallback($ -> this.updateCurrentLevel()));
.withCallback($ -> {
this.updateCurrentLevel();
invVersionTracker.reset();
}));
behaviours.add(invVersionTracker = new VersionedInventoryTrackerBehaviour(this));
InterfaceProvider towardBlockFacing =
(w, p, s) -> new BlockFace(p, DirectedDirectionalBlock.getTargetDirection(s));

View file

@ -188,20 +188,19 @@ public class GlobalRailwayManager {
if (level.dimension() != Level.OVERWORLD)
return;
for (SignalEdgeGroup group : signalEdgeGroups.values()) {
signalEdgeGroups.forEach((id, group) -> {
group.trains.clear();
group.reserved = null;
}
});
for (TrackGraph graph : trackNetworks.values()) {
trackNetworks.forEach((id, graph) -> {
graph.tickPoints(true);
graph.resolveIntersectingEdgeGroups(level);
}
});
tickTrains(level);
for (TrackGraph graph : trackNetworks.values())
graph.tickPoints(false);
trackNetworks.forEach((id, graph) -> graph.tickPoints(false));
GlobalTrainDisplayData.updateTick = level.getGameTime() % 100 == 0;
if (GlobalTrainDisplayData.updateTick)

View file

@ -25,6 +25,7 @@ import com.simibubi.create.content.schematics.requirement.ItemRequirement;
import com.simibubi.create.content.trains.entity.Carriage;
import com.simibubi.create.content.trains.entity.CarriageBogey;
import com.simibubi.create.content.trains.entity.TravellingPoint;
import com.simibubi.create.content.trains.graph.TrackEdge;
import com.simibubi.create.content.trains.track.TrackMaterial;
import com.simibubi.create.foundation.block.IBE;
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
@ -75,7 +76,10 @@ public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> ext
public boolean isOnIncompatibleTrack(Carriage carriage, boolean leading) {
TravellingPoint point = leading ? carriage.getLeadingPoint() : carriage.getTrailingPoint();
CarriageBogey bogey = leading ? carriage.leadingBogey() : carriage.trailingBogey();
return point.edge.getTrackMaterial().trackType != getTrackType(bogey.getStyle());
TrackEdge currentEdge = point.edge;
if (currentEdge == null)
return false;
return currentEdge.getTrackMaterial().trackType != getTrackType(bogey.getStyle());
}
public Set<TrackMaterial.TrackType> getValidPathfindingTypes(BogeyStyle style) {

View file

@ -641,7 +641,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
if (lookAhead != null) {
if (spaceDown) {
carriage.train.manualTick = true;
nav.startNavigation(lookAhead, -1, false);
nav.startNavigation(nav.findPathTo(lookAhead, -1));
carriage.train.manualTick = false;
navDistanceTotal = nav.distanceToDestination;
return true;

View file

@ -304,9 +304,12 @@ public class CarriageSyncData {
TrackNode initialNode1 = forward ? current.node1 : current.node2;
TrackNode initialNode2 = forward ? current.node2 : current.node1;
TrackEdge initialEdge = graph.getConnectionsFrom(initialNode1)
.get(initialNode2);
Map<TrackNode, TrackEdge> connectionsFromInitial = graph.getConnectionsFrom(initialNode1);
if (connectionsFromInitial == null)
return -1;
TrackEdge initialEdge = connectionsFromInitial.get(initialNode2);
if (initialEdge == null)
return -1; // graph changed

View file

@ -21,6 +21,7 @@ import org.apache.commons.lang3.mutable.MutableObject;
import com.simibubi.create.Create;
import com.simibubi.create.content.trains.entity.TravellingPoint.ITrackSelector;
import com.simibubi.create.content.trains.graph.DimensionPalette;
import com.simibubi.create.content.trains.graph.DiscoveredPath;
import com.simibubi.create.content.trains.graph.EdgeData;
import com.simibubi.create.content.trains.graph.EdgePointType;
import com.simibubi.create.content.trains.graph.TrackEdge;
@ -380,15 +381,11 @@ public class Navigation {
train.reservedSignalBlocks.clear();
}
public double startNavigation(GlobalStation destination, double maxCost, boolean simulate) {
DiscoveredPath pathTo = findPathTo(destination, maxCost);
public double startNavigation(DiscoveredPath pathTo) {
boolean noneFound = pathTo == null;
double distance = noneFound ? -1 : Math.abs(pathTo.distance);
double cost = noneFound ? -1 : pathTo.cost;
if (simulate)
return cost;
distanceToDestination = distance;
if (noneFound) {
@ -407,10 +404,10 @@ public class Navigation {
train.reservedSignalBlocks.clear();
train.navigation.waitingForSignal = null;
if (this.destination == null && !simulate)
if (this.destination == null)
distanceStartedAt = distance;
if (this.destination == destination)
if (this.destination == pathTo.destination)
return 0;
if (!train.runtime.paused) {
@ -435,12 +432,19 @@ public class Navigation {
train.status.foundConductor();
}
this.destination = destination;
this.destination = pathTo.destination;
return cost;
}
@Nullable
private DiscoveredPath findPathTo(GlobalStation destination, double maxCost) {
public DiscoveredPath findPathTo(GlobalStation destination, double maxCost) {
ArrayList<GlobalStation> destinations = new ArrayList<>();
destinations.add(destination);
return findPathTo(destinations, maxCost);
}
@Nullable
public DiscoveredPath findPathTo(ArrayList<GlobalStation> destinations, double maxCost) {
TrackGraph graph = train.graph;
if (graph == null)
return null;
@ -460,34 +464,36 @@ public class Navigation {
: graph.getConnectionsFrom(initialPoint.node2)
.get(initialPoint.node1);
search(Double.MAX_VALUE, maxCost, forward, (distance, cost, reachedVia, currentEntry, globalStation) -> {
if (globalStation != destination)
return false;
search(Double.MAX_VALUE, maxCost, forward, destinations, (distance, cost, reachedVia, currentEntry, globalStation) -> {
for (GlobalStation destination : destinations){
if (globalStation == destination) {
TrackEdge edge = currentEntry.getSecond();
TrackNode node1 = currentEntry.getFirst()
.getFirst();
TrackNode node2 = currentEntry.getFirst()
.getSecond();
TrackEdge edge = currentEntry.getSecond();
TrackNode node1 = currentEntry.getFirst()
.getFirst();
TrackNode node2 = currentEntry.getFirst()
.getSecond();
List<Couple<TrackNode>> currentPath = new ArrayList<>();
Pair<Boolean, Couple<TrackNode>> backTrack = reachedVia.get(edge);
Couple<TrackNode> toReach = Couple.create(node1, node2);
TrackEdge edgeReached = edge;
while (backTrack != null) {
if (edgeReached == initialEdge)
break;
if (backTrack.getFirst())
currentPath.add(0, toReach);
toReach = backTrack.getSecond();
edgeReached = graph.getConnection(toReach);
backTrack = reachedVia.get(edgeReached);
}
List<Couple<TrackNode>> currentPath = new ArrayList<>();
Pair<Boolean, Couple<TrackNode>> backTrack = reachedVia.get(edge);
Couple<TrackNode> toReach = Couple.create(node1, node2);
TrackEdge edgeReached = edge;
while (backTrack != null) {
if (edgeReached == initialEdge)
break;
if (backTrack.getFirst())
currentPath.add(0, toReach);
toReach = backTrack.getSecond();
edgeReached = graph.getConnection(toReach);
backTrack = reachedVia.get(edgeReached);
double position = edge.getLength() - destination.getLocationOn(edge);
double distanceToDestination = distance - position;
results.set(forward, new DiscoveredPath((forward ? 1 : -1) * distanceToDestination, cost, currentPath, destination));
return true;
}
}
double position = edge.getLength() - destination.getLocationOn(edge);
double distanceToDestination = distance - position;
results.set(forward, new DiscoveredPath((forward ? 1 : -1) * distanceToDestination, cost, currentPath));
return true;
return false;
});
}
@ -508,18 +514,6 @@ public class Navigation {
return frontBetter ? front : back;
}
public class DiscoveredPath {
List<Couple<TrackNode>> path;
double distance;
double cost;
public DiscoveredPath(double distance, double cost, List<Couple<TrackNode>> path) {
this.distance = distance;
this.cost = cost;
this.path = path;
}
}
public GlobalStation findNearestApproachable(boolean forward) {
TrackGraph graph = train.graph;
if (graph == null)
@ -530,7 +524,7 @@ public class Navigation {
double minDistance = .75f * (train.speed * train.speed) / (2 * acceleration);
double maxDistance = Math.max(32, 1.5f * (train.speed * train.speed) / (2 * acceleration));
search(maxDistance, forward, (distance, cost, reachedVia, currentEntry, globalStation) -> {
search(maxDistance, forward, null, (distance, cost, reachedVia, currentEntry, globalStation) -> {
if (distance < minDistance)
return false;
@ -548,11 +542,11 @@ public class Navigation {
return result.getValue();
}
public void search(double maxDistance, boolean forward, StationTest stationTest) {
search(maxDistance, -1, forward, stationTest);
public void search(double maxDistance, boolean forward, ArrayList<GlobalStation> destinations, StationTest stationTest) {
search(maxDistance, -1, forward, destinations, stationTest);
}
public void search(double maxDistance, double maxCost, boolean forward, StationTest stationTest) {
public void search(double maxDistance, double maxCost, boolean forward, ArrayList<GlobalStation> destinations, StationTest stationTest) {
TrackGraph graph = train.graph;
if (graph == null)
return;
@ -614,10 +608,58 @@ public class Navigation {
double distanceToNode2 = forward ? initialEdge.getLength() - startingPoint.position : startingPoint.position;
frontier.add(new FrontierEntry(distanceToNode2, 0, initialNode1, initialNode2, initialEdge));
int signalWeight = Mth.clamp(ticksWaitingForSignal * 2, Train.Penalties.RED_SIGNAL, 200);
Search: while (!frontier.isEmpty()) {
// Apply penalties to initial edge
int initialPenalty = 0;
if (costRelevant)
initialPenalty += penalties.getOrDefault(initialEdge, 0);
EdgeData initialSignalData = initialEdge.getEdgeData();
if (initialSignalData.hasPoints()) {
for (TrackEdgePoint point : initialSignalData.getPoints()) {
if (point.getLocationOn(initialEdge) < initialEdge.getLength() - distanceToNode2)
continue;
if (costRelevant && distanceToNode2 + initialPenalty > maxCost)
return;
if (!point.canNavigateVia(initialNode2))
return;
if (point instanceof SignalBoundary signal) {
if (signal.isForcedRed(initialNode2)) {
initialPenalty += Train.Penalties.REDSTONE_RED_SIGNAL;
continue;
}
UUID group = signal.getGroup(initialNode2);
if (group == null)
continue;
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(group);
if (signalEdgeGroup == null)
continue;
if (signalEdgeGroup.isOccupiedUnless(signal)) {
initialPenalty += signalWeight;
signalWeight /= 2;
}
}
if (point instanceof GlobalStation station) {
Train presentTrain = station.getPresentTrain();
boolean isOwnStation = presentTrain == train;
if (presentTrain != null && !isOwnStation)
initialPenalty += Train.Penalties.STATION_WITH_TRAIN;
if (station.canApproachFrom(initialNode2) && stationTest.test(distanceToNode2, distanceToNode2 + initialPenalty, reachedVia,
Pair.of(Couple.create(initialNode1, initialNode2), initialEdge), station))
return;
if (!isOwnStation)
initialPenalty += Train.Penalties.STATION;
}
}
}
if (costRelevant && distanceToNode2 + initialPenalty > maxCost)
return;
frontier.add(new FrontierEntry(distanceToNode2, initialPenalty, initialNode1, initialNode2, initialEdge));
while (!frontier.isEmpty()) {
FrontierEntry entry = frontier.poll();
if (!visited.add(entry.edge))
continue;
@ -632,51 +674,19 @@ public class Navigation {
TrackNode node1 = entry.node1;
TrackNode node2 = entry.node2;
if (costRelevant)
penalty += penalties.getOrDefault(edge, 0);
EdgeData signalData = edge.getEdgeData();
if (signalData.hasPoints()) {
for (TrackEdgePoint point : signalData.getPoints()) {
if (node1 == initialNode1 && point.getLocationOn(edge) < edge.getLength() - distanceToNode2)
continue;
if (costRelevant && distance + penalty > maxCost)
continue Search;
if (!point.canNavigateVia(node2))
continue Search;
if (point instanceof SignalBoundary signal) {
if (signal.isForcedRed(node2)) {
penalty += Train.Penalties.REDSTONE_RED_SIGNAL;
continue;
if (entry.hasDestination) {
EdgeData signalData = edge.getEdgeData();
if (signalData.hasPoints()) {
for (TrackEdgePoint point : signalData.getPoints()) {
if (point instanceof GlobalStation station) {
if (station.canApproachFrom(node2) && stationTest.test(distance, penalty, reachedVia,
Pair.of(Couple.create(node1, node2), edge), station))
return;
}
UUID group = signal.getGroup(node2);
if (group == null)
continue;
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(group);
if (signalEdgeGroup == null)
continue;
if (signalEdgeGroup.isOccupiedUnless(signal)) {
penalty += signalWeight;
signalWeight /= 2;
}
}
if (point instanceof GlobalStation station) {
Train presentTrain = station.getPresentTrain();
boolean isOwnStation = presentTrain == train;
if (presentTrain != null && !isOwnStation)
penalty += Train.Penalties.STATION_WITH_TRAIN;
if (station.canApproachFrom(node2) && stationTest.test(distance, distance + penalty, reachedVia,
Pair.of(Couple.create(node1, node2), edge), station))
return;
if (!isOwnStation)
penalty += Train.Penalties.STATION;
}
}
}
if (costRelevant && distance + penalty > maxCost)
continue;
List<Entry<TrackNode, TrackEdge>> validTargets = new ArrayList<>();
Map<TrackNode, TrackEdge> connectionsFrom = graph.getConnectionsFrom(node2);
for (Entry<TrackNode, TrackEdge> connection : connectionsFrom.entrySet()) {
@ -690,15 +700,101 @@ public class Navigation {
if (validTargets.isEmpty())
continue;
for (Entry<TrackNode, TrackEdge> target : validTargets) {
Search: for (Entry<TrackNode, TrackEdge> target : validTargets) {
if (!validTypes.contains(target.getValue().getTrackMaterial().trackType))
continue;
TrackNode newNode = target.getKey();
TrackEdge newEdge = target.getValue();
double newDistance = newEdge.getLength() + distance;
int newPenalty = penalty;
double edgeLength = newEdge.getLength();
double newDistance = distance + edgeLength;
if (costRelevant)
newPenalty += penalties.getOrDefault(newEdge, 0);
// Apply penalty to next connected edge
boolean hasDestination = false;
EdgeData signalData = newEdge.getEdgeData();
if (signalData.hasPoints()) {
for (TrackEdgePoint point : signalData.getPoints()) {
if (node2 == initialNode1 && point.getLocationOn(newEdge) < edgeLength - distanceToNode2)
continue;
if (costRelevant && newDistance + newPenalty > maxCost)
continue Search;
if (!point.canNavigateVia(newNode))
continue Search;
if (point instanceof SignalBoundary signal) {
if (signal.isForcedRed(newNode)) {
newPenalty += Train.Penalties.REDSTONE_RED_SIGNAL;
continue;
}
UUID group = signal.getGroup(newNode);
if (group == null)
continue;
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(group);
if (signalEdgeGroup == null)
continue;
if (signalEdgeGroup.isOccupiedUnless(signal)) {
newPenalty += signalWeight;
signalWeight /= 2;
}
}
if (point instanceof GlobalStation station) {
Train presentTrain = station.getPresentTrain();
boolean isOwnStation = presentTrain == train;
if (presentTrain != null && !isOwnStation)
newPenalty += Train.Penalties.STATION_WITH_TRAIN;
if (station.canApproachFrom(newNode) && stationTest.test(newDistance, newDistance + newPenalty, reachedVia,
Pair.of(Couple.create(node2, newNode), newEdge), station)) {
hasDestination = true;
continue;
}
if (!isOwnStation)
newPenalty += Train.Penalties.STATION;
}
}
}
if (costRelevant && newDistance + newPenalty > maxCost)
continue;
double remainingDist = 0;
// Calculate remaining distance estimator for next connected edge
if (destinations != null && !destinations.isEmpty()) {
remainingDist = Double.MAX_VALUE;
Vec3 newNodePosition = newNode.getLocation().getLocation();
for (GlobalStation destination : destinations) {
TrackNodeLocation destinationNode = destination.edgeLocation.getFirst();
double dMin = Math.abs(newNodePosition.x - destinationNode.getLocation().x);
double dMid = Math.abs(newNodePosition.y - destinationNode.getLocation().y);
double dMax = Math.abs(newNodePosition.z - destinationNode.getLocation().z);
// Sort distance vector in ascending order
double temp;
if (dMin > dMid) {
temp = dMid;
dMid = dMin;
dMin = temp;
}
if (dMin > dMax) {
temp = dMax;
dMax = dMin;
dMin = temp;
}
if (dMid > dMax) {
temp = dMax;
dMax = dMid;
dMid = temp;
}
// Octile distance from newNode to station node
double currentRemaining = 0.317837245195782 * dMin + 0.414213562373095 * dMid + dMax + destination.position;
if (node2.getLocation().equals(destinationNode))
currentRemaining -= newEdge.getLength() * 2; // Correct the distance estimator for station edge
remainingDist = Math.min(remainingDist, currentRemaining);
}
}
reachedVia.putIfAbsent(newEdge, Pair.of(validTargets.size() > 1, Couple.create(node1, node2)));
frontier.add(new FrontierEntry(newDistance, newPenalty, node2, newNode, newEdge));
frontier.add(new FrontierEntry(newDistance, newPenalty, remainingDist, hasDestination, node2, newNode, newEdge));
}
}
}
@ -707,6 +803,8 @@ public class Navigation {
double distance;
int penalty;
double remaining;
boolean hasDestination;
TrackNode node1;
TrackNode node2;
TrackEdge edge;
@ -714,6 +812,17 @@ public class Navigation {
public FrontierEntry(double distance, int penalty, TrackNode node1, TrackNode node2, TrackEdge edge) {
this.distance = distance;
this.penalty = penalty;
this.remaining = 0;
this.hasDestination = false;
this.node1 = node1;
this.node2 = node2;
this.edge = edge;
}
public FrontierEntry(double distance, int penalty, double remaining, boolean hasDestination, TrackNode node1, TrackNode node2, TrackEdge edge) {
this.distance = distance;
this.penalty = penalty;
this.remaining = remaining;
this.hasDestination = hasDestination;
this.node1 = node1;
this.node2 = node2;
this.edge = edge;
@ -721,7 +830,7 @@ public class Navigation {
@Override
public int compareTo(FrontierEntry o) {
return Double.compare(distance + penalty, o.distance + o.penalty);
return Double.compare(distance + penalty + remaining, o.distance + o.penalty + o.remaining);
}
}

View file

@ -24,12 +24,13 @@ import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.AllPackets;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour;
import com.simibubi.create.content.logistics.filter.FilterItem;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.trains.bogey.AbstractBogeyBlockEntity;
import com.simibubi.create.content.trains.entity.Carriage.DimensionalCarriageEntity;
import com.simibubi.create.content.trains.entity.TravellingPoint.IEdgePointListener;
import com.simibubi.create.content.trains.entity.TravellingPoint.SteerDirection;
import com.simibubi.create.content.trains.graph.DimensionPalette;
import com.simibubi.create.content.trains.graph.DiscoveredPath;
import com.simibubi.create.content.trains.graph.EdgeData;
import com.simibubi.create.content.trains.graph.EdgePointType;
import com.simibubi.create.content.trains.graph.TrackEdge;
@ -195,7 +196,7 @@ public class Train {
if (observer == null)
continue;
ItemStack filter = observer.getFilter();
FilterItemStack filter = observer.getFilter();
if (filter.isEmpty()) {
observer.keepAlive(this);
continue;
@ -223,7 +224,7 @@ public class Train {
ItemStack extractItem = inv.extractItem(slot, 1, true);
if (extractItem.isEmpty())
continue;
shouldActivate |= FilterItem.test(level, extractItem, filter);
shouldActivate |= filter.test(level, extractItem);
}
}
@ -235,7 +236,7 @@ public class Train {
FluidStack drain = tank.drain(1, FluidAction.SIMULATE);
if (drain.isEmpty())
continue;
shouldActivate |= FilterItem.test(level, drain, filter);
shouldActivate |= filter.test(level, drain);
}
}
}
@ -539,14 +540,12 @@ public class Train {
if (!reservedSignalBlocks.isEmpty())
return;
GlobalStation destination = navigation.destination;
if (!navigatingManually && fullRefresh) {
GlobalStation preferredDestination = runtime.startCurrentInstruction();
if (preferredDestination != null)
destination = preferredDestination;
DiscoveredPath preferredPath = runtime.startCurrentInstruction();
if (preferredPath != null){
navigation.startNavigation(preferredPath);
}
}
navigation.startNavigation(destination, navigatingManually ? -1 : Double.MAX_VALUE, false);
}
private void tickDerailedSlowdown() {
@ -601,7 +600,7 @@ public class Train {
Vec3 start = (speed < 0 ? trailingPoint : leadingPoint).getPosition(graph);
Vec3 end = (speed < 0 ? leadingPoint : trailingPoint).getPosition(graph);
Pair<Train, Vec3> collision = findCollidingTrain(level, start, end, this, dimension);
Pair<Train, Vec3> collision = findCollidingTrain(level, start, end, dimension);
if (collision == null)
return;
@ -617,13 +616,16 @@ public class Train {
train.crash();
}
public static Pair<Train, Vec3> findCollidingTrain(Level level, Vec3 start, Vec3 end, Train ignore,
ResourceKey<Level> dimension) {
for (Train train : Create.RAILWAYS.sided(level).trains.values()) {
if (train == ignore)
public Pair<Train, Vec3> findCollidingTrain(Level level, Vec3 start, Vec3 end, ResourceKey<Level> dimension) {
Vec3 diff = end.subtract(start);
double maxDistanceSqr = Math.pow(AllConfigs.server().trains.maxAssemblyLength.get(), 2.0);
Trains: for (Train train : Create.RAILWAYS.sided(level).trains.values()) {
if (train == this)
continue;
if (train.graph != null && train.graph != graph)
continue;
Vec3 diff = end.subtract(start);
Vec3 lastPoint = null;
for (Carriage otherCarriage : train.carriages) {
@ -643,6 +645,10 @@ public class Train {
Vec3 start2 = otherLeading.getPosition(train.graph);
Vec3 end2 = otherTrailing.getPosition(train.graph);
if (Math.min(start2.distanceToSqr(start), end2.distanceToSqr(start)) > maxDistanceSqr)
continue Trains;
if (betweenBits) {
end2 = start2;
start2 = lastPoint;
@ -1040,7 +1046,7 @@ public class Train {
}
public static class Penalties {
static final int STATION = 200, STATION_WITH_TRAIN = 300;
static final int STATION = 50, STATION_WITH_TRAIN = 300;
static final int MANUAL_TRAIN = 200, IDLE_TRAIN = 700, ARRIVING_TRAIN = 50, WAITING_TRAIN = 50, ANY_TRAIN = 25,
RED_SIGNAL = 25, REDSTONE_RED_SIGNAL = 400;
}

Some files were not shown because too many files have changed in this diff Show more