Merge branch 'mc1.18/dev' into mc1.18/0.5.1

This commit is contained in:
simibubi 2023-02-24 22:10:33 +01:00
commit a75e3af0b0
52 changed files with 438 additions and 55419 deletions

View file

@ -49,6 +49,7 @@ body:
label: Mod Version label: Mod Version
description: The version of the mod you were using when the bug occured description: The version of the mod you were using when the bug occured
options: options:
- "0.5.0i"
- "0.5.0h" - "0.5.0h"
- "0.5.0g" - "0.5.0g"
- "0.5.0f" - "0.5.0f"

View file

@ -5,7 +5,7 @@
<a href="https://github.com/Creators-of-Create/Create/blob/master/LICENSE"><img src="https://img.shields.io/github/license/Creators-of-Create/Create?style=flat&color=900c3f" alt="License"></a> <a href="https://github.com/Creators-of-Create/Create/blob/master/LICENSE"><img src="https://img.shields.io/github/license/Creators-of-Create/Create?style=flat&color=900c3f" alt="License"></a>
<a href="https://discord.gg/hmaD7Se"><img src="https://img.shields.io/discord/620934202875183104?color=5865f2&label=Discord&style=flat" alt="Discord"></a> <a href="https://discord.gg/hmaD7Se"><img src="https://img.shields.io/discord/620934202875183104?color=5865f2&label=Discord&style=flat" alt="Discord"></a>
<a href="https://www.curseforge.com/minecraft/mc-mods/create"><img src="http://cf.way2muchnoise.eu/328085.svg" alt="CF"></a> <a href="https://www.curseforge.com/minecraft/mc-mods/create"><img src="http://cf.way2muchnoise.eu/328085.svg" alt="CF"></a>
<a href="https://modrinth.com/mod/create"><img src="https://img.shields.io/badge/dynamic/json?logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+Cjxzdmcgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDUxMiA1MTQiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgeG1sbnM6c2VyaWY9Imh0dHA6Ly93d3cuc2VyaWYuY29tLyIgc3R5bGU9ImZpbGwtcnVsZTpldmVub2RkO2NsaXAtcnVsZTpldmVub2RkO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoyOyI+CiAgICA8Zz4KICAgICAgICA8ZyBpZD0ibW9kcmludGgiPgogICAgICAgICAgICA8cGF0aCBkPSJNNTAzLjE2LDMyMy41NkM1MTQuNTUsMjgxLjQ3IDUxNS4zMiwyMzUuOTEgNTAzLjIsMTkwLjc2QzQ2Ni41Nyw1NC4yMyAzMjYuMDQsLTI2LjggMTg5LjMzLDkuNzhDODMuODEsMzguMDIgMTEuMzksMTI4LjA3IDAuNjksMjMwLjQ3TDQzLjk5LDIzMC40N0M1NC4yOSwxNDcuMzMgMTEzLjc0LDc0LjczIDE5OS43NSw1MS43MUMzMDYuMDUsMjMuMjYgNDE1LjEzLDgwLjY3IDQ1My4xNywxODEuMzhMNDExLjAzLDE5Mi42NUMzOTEuNjQsMTQ1LjggMzUyLjU3LDExMS40NSAzMDYuMyw5Ni44MkwyOTguNTYsMTQwLjY2QzMzNS4wOSwxNTQuMTMgMzY0LjcyLDE4NC41IDM3NS41NiwyMjQuOTFDMzkxLjM2LDI4My44IDM2MS45NCwzNDQuMTQgMzA4LjU2LDM2OS4xN0wzMjAuMDksNDEyLjE2QzM5MC4yNSwzODMuMjEgNDMyLjQsMzEwLjMgNDIyLjQzLDIzNS4xNEw0NjQuNDEsMjIzLjkxQzQ2OC45MSwyNTIuNjIgNDY3LjM1LDI4MS4xNiA0NjAuNTUsMzA4LjA3TDUwMy4xNiwzMjMuNTZaIiBzdHlsZT0iZmlsbDpyZ2IoMjMsMjMsMjUpOyIvPgogICAgICAgICAgICA8cGF0aCBkPSJNMzIxLjk5LDUwNC4yMkMxODUuMjcsNTQwLjggNDQuNzUsNDU5Ljc3IDguMTEsMzIzLjI0QzMuODQsMzA3LjMxIDEuMTcsMjkxLjMzIDAsMjc1LjQ2TDQzLjI3LDI3NS40NkM0NC4zNiwyODcuMzcgNDYuNDcsMjk5LjM1IDQ5LjY4LDMxMS4yOUM1My4wNCwzMjMuOCA1Ny40NSwzMzUuNzUgNjIuNzksMzQ3LjA3TDEwMS4zOCwzMjMuOTJDOTguMTMsMzE2LjQyIDk1LjM5LDMwOC42IDkzLjIxLDMwMC40N0M2OS4xNywyMTAuODcgMTIyLjQxLDExOC43NyAyMTIuMTMsOTQuNzZDMjI5LjEzLDkwLjIxIDI0Ni4yMyw4OC40NCAyNjIuOTMsODkuMTVMMjU1LjE5LDEzM0MyNDQuNzMsMTMzLjA1IDIzNC4xMSwxMzQuNDIgMjIzLjUzLDEzNy4yNUMxNTcuMzEsMTU0Ljk4IDExOC4wMSwyMjIuOTUgMTM1Ljc1LDI4OS4wOUMxMzYuODUsMjkzLjE2IDEzOC4xMywyOTcuMTMgMTM5LjU5LDMwMC45OUwxODguOTQsMjcxLjM4TDE3NC4wNywyMzEuOTVMMjIwLjY3LDE4NC4wOEwyNzkuNTcsMTcxLjM5TDI5Ni42MiwxOTIuMzhMMjY5LjQ3LDIxOS44OEwyNDUuNzksMjI3LjMzTDIyOC44NywyNDQuNzJMMjM3LjE2LDI2Ny43OUMyMzcuMTYsMjY3Ljc5IDI1My45NSwyODUuNjMgMjUzLjk4LDI4NS42NEwyNzcuNywyNzkuMzNMMjk0LjU4LDI2MC43OUwzMzEuNDQsMjQ5LjEyTDM0Mi40MiwyNzMuODJMMzA0LjM5LDMyMC40NUwyNDAuNjYsMzQwLjYzTDIxMi4wOCwzMDguODFMMTYyLjI2LDMzOC43QzE4Ny44LDM2Ny43OCAyMjYuMiwzODMuOTMgMjY2LjAxLDM4MC41NkwyNzcuNTQsNDIzLjU1QzIxOC4xMyw0MzEuNDEgMTYwLjEsNDA2LjgyIDEyNC4wNSwzNjEuNjRMODUuNjQsMzg0LjY4QzEzNi4yNSw0NTEuMTcgMjIzLjg0LDQ4NC4xMSAzMDkuNjEsNDYxLjE2QzM3MS4zNSw0NDQuNjQgNDE5LjQsNDAyLjU2IDQ0NS40MiwzNDkuMzhMNDg4LjA2LDM2NC44OEM0NTcuMTcsNDMxLjE2IDM5OC4yMiw0ODMuODIgMzIxLjk5LDUwNC4yMloiIHN0eWxlPSJmaWxsOnJnYigyMywyMywyNSk7ZmlsbC1ydWxlOm5vbnplcm87Ii8+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4K&label=&suffix=%20&query=downloads&url=https://api.modrinth.com/api/v1/mod/LNytGWDc&style=flat&color=242629&labelColor=5ca424" alt="Modrinth"></a> <a href="https://modrinth.com/mod/create"><img src="https://img.shields.io/modrinth/dt/create?logo=modrinth&label=&suffix=%20&style=flat&color=242629&labelColor=5ca424&logoColor=1c1c1c" alt="Modrinth"></a>
<br><br> <br><br>
</h1> </h1>

View file

@ -8,7 +8,7 @@ mod_version = 0.5.1
artifact_minecraft_version = 1.18.2 artifact_minecraft_version = 1.18.2
minecraft_version = 1.18.2 minecraft_version = 1.18.2
forge_version = 40.1.60 forge_version = 40.2.1
# build dependency versions # build dependency versions
forgegradle_version = 5.1.53 forgegradle_version = 5.1.53

View file

@ -566,30 +566,7 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
3054a5519fbf91481b0c9c8160a20679fa9530da assets/create/lang/en_ud.json 3054a5519fbf91481b0c9c8160a20679fa9530da assets/create/lang/en_ud.json
10368a860ae28910f8b376da5a71ed5329e878d6 assets/create/lang/en_us.json 8db7da2dab7745aa409e536d7a36cbe9fcce21a4 assets/create/lang/en_us.json
0aca1235610eae2a297eda6f96780115f8cd0a8e assets/create/lang/unfinished/cs_cz.json
91513e2231501328a1a2e99c8bd90a51c8513c1b assets/create/lang/unfinished/da_dk.json
e2e4f2644ca0cfbe26436abadc6553333fe2ce89 assets/create/lang/unfinished/de_de.json
ef633c12441059ac2d6795e39bb70578696da6e0 assets/create/lang/unfinished/es_cl.json
2d4d14e4c1fb9d9c8590a33570981cca83e0f44f assets/create/lang/unfinished/es_es.json
2fb12650950d8867501f5b00ff6edbedd8e231e4 assets/create/lang/unfinished/es_mx.json
645f1b7cc8d99de345fa3e5f2d1967e49b17d32b assets/create/lang/unfinished/fr_fr.json
0e6f608edc0d95337a6cce21d26cc8c5c7284bfc assets/create/lang/unfinished/hu_hu.json
0afaccef5e6b4bc2149bef652e5dd51c426c816a assets/create/lang/unfinished/it_it.json
ee8bd262d30c4b176d012902d0371648f5f5d5d4 assets/create/lang/unfinished/ja_jp.json
499063468b398b7b31182c109b68e751361b04fa assets/create/lang/unfinished/ko_kr.json
5beecf8025e06933a488a4e8224927e001f759cb assets/create/lang/unfinished/nl_nl.json
7e6a23b7f7c24ebbd08c135a8565787f65c6e0f0 assets/create/lang/unfinished/no_no.json
da8649af75b2b52a99ae4c30a106768f917192b4 assets/create/lang/unfinished/pl_pl.json
3fba7b5d3649aac2cb759bed41d8690b5cf4dbd1 assets/create/lang/unfinished/pt_br.json
3e83cdf96cde7c50f3f106a7e1f4c029cf26bfe2 assets/create/lang/unfinished/pt_pt.json
4a9f031baa04241b34779c74a75ca9f73ee589b7 assets/create/lang/unfinished/ro_ro.json
fa470b919e1f304ed0eb43cf3b47f2e9c9f1a470 assets/create/lang/unfinished/ru_ru.json
ec236461ebc2bddf2a1281b4d8713ba0bbb40012 assets/create/lang/unfinished/sv_se.json
906d8450cd95b65824ff23c1db38096cdc3802ec assets/create/lang/unfinished/th_th.json
a7122f134d4cdad8802f097822c38158b3042fa5 assets/create/lang/unfinished/uk_ua.json
0e0501505897acbc7bb2fe5cb20faa71727285ab assets/create/lang/unfinished/zh_cn.json
7829c9e8b9e5fa92b7327b839d914162a2ab5f06 assets/create/lang/unfinished/zh_tw.json
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json 487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json 3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json

View file

@ -1133,6 +1133,7 @@
"create.schematicAndQuill.saved": "Saved as %1$s", "create.schematicAndQuill.saved": "Saved as %1$s",
"create.schematic.invalid": "[!] Invalid Item - Use the Schematic Table instead", "create.schematic.invalid": "[!] Invalid Item - Use the Schematic Table instead",
"create.schematic.error": "Schematic failed to Load - Check Game Logs",
"create.schematic.position": "Position", "create.schematic.position": "Position",
"create.schematic.rotation": "Rotation", "create.schematic.rotation": "Rotation",
"create.schematic.rotation.none": "None", "create.schematic.rotation.none": "None",
@ -1226,6 +1227,8 @@
"create.schematicannon.status.schematicInvalid": "Schematic Invalid", "create.schematicannon.status.schematicInvalid": "Schematic Invalid",
"create.schematicannon.status.schematicNotPlaced": "Schematic not Positioned", "create.schematicannon.status.schematicNotPlaced": "Schematic not Positioned",
"create.schematicannon.status.schematicExpired": "Schematic File Expired", "create.schematicannon.status.schematicExpired": "Schematic File Expired",
"create.schematicannon.status.schematicErrored": "Incompatible Blocks",
"create.schematicannon.status.schematicErroredCheckLogs": "Check Server Logs",
"create.materialChecklist": "Material Checklist", "create.materialChecklist": "Material Checklist",
"create.materialChecklist.blocksNotLoaded": "* Disclaimer *\n\nMaterial List may be inaccurate due to relevant chunks not being loaded.", "create.materialChecklist.blocksNotLoaded": "* Disclaimer *\n\nMaterial List may be inaccurate due to relevant chunks not being loaded.",
@ -1772,6 +1775,9 @@
"create.contraption.minecart_contraption_too_big": "This Cart Contraption seems too big to pick up", "create.contraption.minecart_contraption_too_big": "This Cart Contraption seems too big to pick up",
"create.contraption.minecart_contraption_illegal_pickup": "A mystical force is binding this Cart Contraption to the world", "create.contraption.minecart_contraption_illegal_pickup": "A mystical force is binding this Cart Contraption to the world",
"enchantment.create.capacity.desc": "Increases Backtank air capacity.",
"enchantment.create.potato_recovery.desc": "Potato Cannon projectiles have a chance to be reused.",
"_": "->------------------------] Subtitles [------------------------<-", "_": "->------------------------] Subtitles [------------------------<-",

View file

@ -121,6 +121,7 @@ import com.simibubi.create.content.contraptions.relays.belt.BeltModel;
import com.simibubi.create.content.contraptions.relays.elementary.BracketedKineticBlockModel; import com.simibubi.create.content.contraptions.relays.elementary.BracketedKineticBlockModel;
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
import com.simibubi.create.content.contraptions.relays.elementary.CogwheelBlockItem; import com.simibubi.create.content.contraptions.relays.elementary.CogwheelBlockItem;
import com.simibubi.create.content.contraptions.relays.elementary.EncasingRegistry;
import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock;
import com.simibubi.create.content.contraptions.relays.encased.AdjustablePulleyBlock; import com.simibubi.create.content.contraptions.relays.encased.AdjustablePulleyBlock;
import com.simibubi.create.content.contraptions.relays.encased.ClutchBlock; import com.simibubi.create.content.contraptions.relays.encased.ClutchBlock;
@ -360,23 +361,26 @@ public class AllBlocks {
.register(); .register();
public static final BlockEntry<EncasedShaftBlock> ANDESITE_ENCASED_SHAFT = public static final BlockEntry<EncasedShaftBlock> ANDESITE_ENCASED_SHAFT =
REGISTRATE.block("andesite_encased_shaft", EncasedShaftBlock::andesite) REGISTRATE.block("andesite_encased_shaft", p -> new EncasedShaftBlock(p, AllBlocks.ANDESITE_CASING::get))
.properties(p -> p.color(MaterialColor.PODZOL)) .properties(p -> p.color(MaterialColor.PODZOL))
.transform(BuilderTransformers.encasedShaft("andesite", () -> AllSpriteShifts.ANDESITE_CASING)) .transform(BuilderTransformers.encasedShaft("andesite", () -> AllSpriteShifts.ANDESITE_CASING))
.transform(EncasingRegistry.addVariantTo(AllBlocks.SHAFT))
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.register(); .register();
public static final BlockEntry<EncasedShaftBlock> BRASS_ENCASED_SHAFT = public static final BlockEntry<EncasedShaftBlock> BRASS_ENCASED_SHAFT =
REGISTRATE.block("brass_encased_shaft", EncasedShaftBlock::brass) REGISTRATE.block("brass_encased_shaft", p -> new EncasedShaftBlock(p, AllBlocks.BRASS_CASING::get))
.properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN)) .properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN))
.transform(BuilderTransformers.encasedShaft("brass", () -> AllSpriteShifts.BRASS_CASING)) .transform(BuilderTransformers.encasedShaft("brass", () -> AllSpriteShifts.BRASS_CASING))
.transform(EncasingRegistry.addVariantTo(AllBlocks.SHAFT))
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.register(); .register();
public static final BlockEntry<EncasedCogwheelBlock> ANDESITE_ENCASED_COGWHEEL = REGISTRATE public static final BlockEntry<EncasedCogwheelBlock> ANDESITE_ENCASED_COGWHEEL = REGISTRATE
.block("andesite_encased_cogwheel", p -> EncasedCogwheelBlock.andesite(false, p)) .block("andesite_encased_cogwheel", p -> new EncasedCogwheelBlock(p, false, AllBlocks.ANDESITE_CASING::get))
.properties(p -> p.color(MaterialColor.PODZOL)) .properties(p -> p.color(MaterialColor.PODZOL))
.transform(BuilderTransformers.encasedCogwheel("andesite", () -> AllSpriteShifts.ANDESITE_CASING)) .transform(BuilderTransformers.encasedCogwheel("andesite", () -> AllSpriteShifts.ANDESITE_CASING))
.transform(EncasingRegistry.addVariantTo(AllBlocks.COGWHEEL))
.onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCogCTBehaviour(AllSpriteShifts.ANDESITE_CASING, .onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCogCTBehaviour(AllSpriteShifts.ANDESITE_CASING,
Couple.create(AllSpriteShifts.ANDESITE_ENCASED_COGWHEEL_SIDE, Couple.create(AllSpriteShifts.ANDESITE_ENCASED_COGWHEEL_SIDE,
AllSpriteShifts.ANDESITE_ENCASED_COGWHEEL_OTHERSIDE)))) AllSpriteShifts.ANDESITE_ENCASED_COGWHEEL_OTHERSIDE))))
@ -384,9 +388,10 @@ public class AllBlocks {
.register(); .register();
public static final BlockEntry<EncasedCogwheelBlock> BRASS_ENCASED_COGWHEEL = public static final BlockEntry<EncasedCogwheelBlock> BRASS_ENCASED_COGWHEEL =
REGISTRATE.block("brass_encased_cogwheel", p -> EncasedCogwheelBlock.brass(false, p)) REGISTRATE.block("brass_encased_cogwheel", p -> new EncasedCogwheelBlock(p, false, AllBlocks.BRASS_CASING::get))
.properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN)) .properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN))
.transform(BuilderTransformers.encasedCogwheel("brass", () -> AllSpriteShifts.BRASS_CASING)) .transform(BuilderTransformers.encasedCogwheel("brass", () -> AllSpriteShifts.BRASS_CASING))
.transform(EncasingRegistry.addVariantTo(AllBlocks.COGWHEEL))
.onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCogCTBehaviour(AllSpriteShifts.BRASS_CASING, .onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCogCTBehaviour(AllSpriteShifts.BRASS_CASING,
Couple.create(AllSpriteShifts.BRASS_ENCASED_COGWHEEL_SIDE, Couple.create(AllSpriteShifts.BRASS_ENCASED_COGWHEEL_SIDE,
AllSpriteShifts.BRASS_ENCASED_COGWHEEL_OTHERSIDE)))) AllSpriteShifts.BRASS_ENCASED_COGWHEEL_OTHERSIDE))))
@ -394,16 +399,18 @@ public class AllBlocks {
.register(); .register();
public static final BlockEntry<EncasedCogwheelBlock> ANDESITE_ENCASED_LARGE_COGWHEEL = public static final BlockEntry<EncasedCogwheelBlock> ANDESITE_ENCASED_LARGE_COGWHEEL =
REGISTRATE.block("andesite_encased_large_cogwheel", p -> EncasedCogwheelBlock.andesite(true, p)) REGISTRATE.block("andesite_encased_large_cogwheel", p -> new EncasedCogwheelBlock(p, true, AllBlocks.ANDESITE_CASING::get))
.properties(p -> p.color(MaterialColor.PODZOL)) .properties(p -> p.color(MaterialColor.PODZOL))
.transform(BuilderTransformers.encasedLargeCogwheel("andesite", () -> AllSpriteShifts.ANDESITE_CASING)) .transform(BuilderTransformers.encasedLargeCogwheel("andesite", () -> AllSpriteShifts.ANDESITE_CASING))
.transform(EncasingRegistry.addVariantTo(AllBlocks.LARGE_COGWHEEL))
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.register(); .register();
public static final BlockEntry<EncasedCogwheelBlock> BRASS_ENCASED_LARGE_COGWHEEL = public static final BlockEntry<EncasedCogwheelBlock> BRASS_ENCASED_LARGE_COGWHEEL =
REGISTRATE.block("brass_encased_large_cogwheel", p -> EncasedCogwheelBlock.brass(true, p)) REGISTRATE.block("brass_encased_large_cogwheel", p -> new EncasedCogwheelBlock(p, true, AllBlocks.BRASS_CASING::get))
.properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN)) .properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN))
.transform(BuilderTransformers.encasedLargeCogwheel("brass", () -> AllSpriteShifts.BRASS_CASING)) .transform(BuilderTransformers.encasedLargeCogwheel("brass", () -> AllSpriteShifts.BRASS_CASING))
.transform(EncasingRegistry.addVariantTo(AllBlocks.LARGE_COGWHEEL))
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.register(); .register();
@ -821,7 +828,7 @@ public class AllBlocks {
.register(); .register();
public static final BlockEntry<EncasedPipeBlock> ENCASED_FLUID_PIPE = public static final BlockEntry<EncasedPipeBlock> ENCASED_FLUID_PIPE =
REGISTRATE.block("encased_fluid_pipe", EncasedPipeBlock::new) REGISTRATE.block("encased_fluid_pipe", p -> new EncasedPipeBlock(p, AllBlocks.COPPER_CASING::get))
.initialProperties(SharedProperties::copperMetal) .initialProperties(SharedProperties::copperMetal)
.properties(p -> p.color(MaterialColor.TERRACOTTA_LIGHT_GRAY)) .properties(p -> p.color(MaterialColor.TERRACOTTA_LIGHT_GRAY))
.properties(BlockBehaviour.Properties::noOcclusion) .properties(BlockBehaviour.Properties::noOcclusion)
@ -832,6 +839,7 @@ public class AllBlocks {
(s, f) -> !s.getValue(EncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(f))))) (s, f) -> !s.getValue(EncasedPipeBlock.FACING_TO_PROPERTY_MAP.get(f)))))
.onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new))
.loot((p, b) -> p.dropOther(b, FLUID_PIPE.get())) .loot((p, b) -> p.dropOther(b, FLUID_PIPE.get()))
.transform(EncasingRegistry.addVariantTo(AllBlocks.FLUID_PIPE))
.register(); .register();
public static final BlockEntry<GlassFluidPipeBlock> GLASS_FLUID_PIPE = public static final BlockEntry<GlassFluidPipeBlock> GLASS_FLUID_PIPE =

View file

@ -9,11 +9,13 @@ import static net.minecraft.world.level.block.state.properties.BlockStatePropert
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.function.Supplier;
import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlockEntityTypes;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.fluids.FluidPropagator; import com.simibubi.create.content.contraptions.fluids.FluidPropagator;
import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour;
import com.simibubi.create.content.contraptions.relays.elementary.EncasedBlock;
import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement;
import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement;
@ -25,6 +27,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.network.protocol.game.DebugPackets; import net.minecraft.network.protocol.game.DebugPackets;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
@ -39,15 +42,18 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition.Builder; import net.minecraft.world.level.block.state.StateDefinition.Builder;
import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.world.ticks.TickPriority; import net.minecraft.world.ticks.TickPriority;
public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBlockItemRequirement, IBE<FluidPipeBlockEntity> { public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBlockItemRequirement, IBE<FluidPipeBlockEntity>, EncasedBlock {
public static final Map<Direction, BooleanProperty> FACING_TO_PROPERTY_MAP = PipeBlock.PROPERTY_BY_DIRECTION; public static final Map<Direction, BooleanProperty> FACING_TO_PROPERTY_MAP = PipeBlock.PROPERTY_BY_DIRECTION;
public EncasedPipeBlock(Properties p_i48339_1_) { private final Supplier<Block> casing;
super(p_i48339_1_);
public EncasedPipeBlock(Properties properties, Supplier<Block> casing) {
super(properties);
this.casing = casing;
registerDefaultState(defaultBlockState().setValue(NORTH, false) registerDefaultState(defaultBlockState().setValue(NORTH, false)
.setValue(SOUTH, false) .setValue(SOUTH, false)
.setValue(DOWN, false) .setValue(DOWN, false)
@ -61,7 +67,7 @@ public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBloc
builder.add(NORTH, EAST, SOUTH, WEST, UP, DOWN); builder.add(NORTH, EAST, SOUTH, WEST, UP, DOWN);
super.createBlockStateDefinition(builder); super.createBlockStateDefinition(builder);
} }
@Override @Override
public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) {
super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack);
@ -154,4 +160,17 @@ public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBloc
return AllBlockEntityTypes.ENCASED_FLUID_PIPE.get(); return AllBlockEntityTypes.ENCASED_FLUID_PIPE.get();
} }
@Override
public Block getCasing() {
return casing.get();
}
@Override
public void handleEncasing(BlockState state, Level level, BlockPos pos, ItemStack heldItem, Player player, InteractionHand hand,
BlockHitResult ray) {
FluidTransportBehaviour.cacheFlows(level, pos);
level.setBlockAndUpdate(pos,
EncasedPipeBlock.transferSixWayProperties(state, defaultBlockState()));
FluidTransportBehaviour.loadFlows(level, pos);
}
} }

View file

@ -11,6 +11,7 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.fluids.FluidPropagator; import com.simibubi.create.content.contraptions.fluids.FluidPropagator;
import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour;
import com.simibubi.create.content.contraptions.relays.elementary.BracketedBlockEntityBehaviour; import com.simibubi.create.content.contraptions.relays.elementary.BracketedBlockEntityBehaviour;
import com.simibubi.create.content.contraptions.relays.elementary.EncasableBlock;
import com.simibubi.create.content.contraptions.wrench.IWrenchableWithBracket; import com.simibubi.create.content.contraptions.wrench.IWrenchableWithBracket;
import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.advancement.AdvancementBehaviour;
import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.AllAdvancements;
@ -50,7 +51,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.ticks.TickPriority; import net.minecraft.world.ticks.TickPriority;
public class FluidPipeBlock extends PipeBlock public class FluidPipeBlock extends PipeBlock
implements SimpleWaterloggedBlock, IWrenchableWithBracket, IBE<FluidPipeBlockEntity> { implements SimpleWaterloggedBlock, IWrenchableWithBracket, IBE<FluidPipeBlockEntity>, EncasableBlock {
private static final VoxelShape OCCLUSION_BOX = Block.box(4, 4, 4, 12, 12, 12); private static final VoxelShape OCCLUSION_BOX = Block.box(4, 4, 4, 12, 12, 12);
@ -95,7 +96,7 @@ public class FluidPipeBlock extends PipeBlock
.filter(pc -> pc != null && pc.hasFlow()) .filter(pc -> pc != null && pc.hasFlow())
.findAny() .findAny()
.ifPresent($ -> AllAdvancements.GLASS_PIPE.awardTo(context.getPlayer()))); .ifPresent($ -> AllAdvancements.GLASS_PIPE.awardTo(context.getPlayer())));
FluidTransportBehaviour.cacheFlows(world, pos); FluidTransportBehaviour.cacheFlows(world, pos);
world.setBlockAndUpdate(pos, AllBlocks.GLASS_FLUID_PIPE.getDefaultState() world.setBlockAndUpdate(pos, AllBlocks.GLASS_FLUID_PIPE.getDefaultState()
.setValue(GlassFluidPipeBlock.AXIS, axis) .setValue(GlassFluidPipeBlock.AXIS, axis)
@ -113,18 +114,13 @@ public class FluidPipeBlock extends PipeBlock
@Override @Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand,
BlockHitResult hit) { BlockHitResult ray) {
if (!AllBlocks.COPPER_CASING.isIn(player.getItemInHand(hand))) ItemStack heldItem = player.getItemInHand(hand);
return InteractionResult.PASS; InteractionResult result = tryEncase(state, world, pos, heldItem, player, hand, ray);
if (world.isClientSide) if (result.consumesAction())
return InteractionResult.SUCCESS; return result;
FluidTransportBehaviour.cacheFlows(world, pos);
world.setBlockAndUpdate(pos,
EncasedPipeBlock.transferSixWayProperties(state, AllBlocks.ENCASED_FLUID_PIPE.getDefaultState()));
FluidTransportBehaviour.loadFlows(world, pos);
return InteractionResult.SUCCESS;
return InteractionResult.PASS;
} }
public BlockState getAxisState(Axis axis) { public BlockState getAxisState(Axis axis) {
@ -341,5 +337,4 @@ public class FluidPipeBlock extends PipeBlock
public VoxelShape getOcclusionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos) { public VoxelShape getOcclusionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos) {
return OCCLUSION_BOX; return OCCLUSION_BOX;
} }
} }

View file

@ -168,6 +168,8 @@ public class BeltBlockEntity extends KineticBlockEntity {
protected void initializeItemHandler() { protected void initializeItemHandler() {
if (level.isClientSide || itemHandler.isPresent()) if (level.isClientSide || itemHandler.isPresent())
return; return;
if (beltLength == 0 || controller == null)
return;
if (!level.isLoaded(controller)) if (!level.isLoaded(controller))
return; return;
BlockEntity be = level.getBlockEntity(controller); BlockEntity be = level.getBlockEntity(controller);

View file

@ -52,6 +52,8 @@ public class ItemHandlerBeltSegment implements IItemHandler {
amount = Math.min(amount, transported.stack.getCount()); amount = Math.min(amount, transported.stack.getCount());
ItemStack extracted = simulate ? transported.stack.copy().split(amount) : transported.stack.split(amount); ItemStack extracted = simulate ? transported.stack.copy().split(amount) : transported.stack.split(amount);
if (!simulate) { if (!simulate) {
if (transported.stack.isEmpty())
this.beltInventory.toRemove.add(transported);
this.beltInventory.belt.setChanged(); this.beltInventory.belt.setChanged();
this.beltInventory.belt.sendData(); this.beltInventory.belt.sendData();
} }

View file

@ -5,9 +5,7 @@ import javax.annotation.ParametersAreNonnullByDefault;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlock; import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlock;
import com.simibubi.create.content.contraptions.relays.encased.EncasedCogwheelBlock;
import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
@ -35,7 +33,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault
public class CogWheelBlock extends AbstractSimpleShaftBlock implements ICogWheel { public class CogWheelBlock extends AbstractSimpleShaftBlock implements ICogWheel, EncasableBlock {
boolean isLarge; boolean isLarge;
@ -122,38 +120,9 @@ public class CogWheelBlock extends AbstractSimpleShaftBlock implements ICogWheel
return InteractionResult.PASS; return InteractionResult.PASS;
ItemStack heldItem = player.getItemInHand(hand); ItemStack heldItem = player.getItemInHand(hand);
EncasedCogwheelBlock[] encasedBlocks = isLarge InteractionResult result = tryEncase(state, world, pos, heldItem, player, hand, ray);
? new EncasedCogwheelBlock[] { AllBlocks.ANDESITE_ENCASED_LARGE_COGWHEEL.get(), if (result.consumesAction())
AllBlocks.BRASS_ENCASED_LARGE_COGWHEEL.get() } return result;
: new EncasedCogwheelBlock[] { AllBlocks.ANDESITE_ENCASED_COGWHEEL.get(),
AllBlocks.BRASS_ENCASED_COGWHEEL.get() };
for (EncasedCogwheelBlock encasedCog : encasedBlocks) {
if (!encasedCog.getCasing()
.isIn(heldItem))
continue;
if (world.isClientSide)
return InteractionResult.SUCCESS;
BlockState encasedState = encasedCog.defaultBlockState()
.setValue(AXIS, state.getValue(AXIS));
for (Direction d : Iterate.directionsInAxis(state.getValue(AXIS))) {
BlockState adjacentState = world.getBlockState(pos.relative(d));
if (!(adjacentState.getBlock() instanceof IRotate))
continue;
IRotate def = (IRotate) adjacentState.getBlock();
if (!def.hasShaftTowards(world, pos.relative(d), adjacentState, d.getOpposite()))
continue;
encasedState =
encasedState.cycle(d.getAxisDirection() == AxisDirection.POSITIVE ? EncasedCogwheelBlock.TOP_SHAFT
: EncasedCogwheelBlock.BOTTOM_SHAFT);
}
KineticBlockEntity.switchToBlockState(world, pos, encasedState);
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS; return InteractionResult.PASS;
} }

View file

@ -0,0 +1,39 @@
package com.simibubi.create.content.contraptions.relays.elementary;
import java.util.List;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
/**
* Implement this interface to indicate that this block is encasable.
*/
public interface EncasableBlock {
/**
* This method should be called in the {@link Block#use(BlockState, Level, BlockPos, Player, InteractionHand, BlockHitResult)} method.
*/
default InteractionResult tryEncase(BlockState state, Level level, BlockPos pos, ItemStack heldItem, Player player, InteractionHand hand,
BlockHitResult ray) {
List<Block> encasedVariants = EncasingRegistry.getVariants(state.getBlock());
for (Block block : encasedVariants) {
if (block instanceof EncasedBlock encased) {
if (encased.getCasing().asItem() != heldItem.getItem())
continue;
if (level.isClientSide)
return InteractionResult.SUCCESS;
encased.handleEncasing(state, level, pos, heldItem, player, hand, ray);
return InteractionResult.SUCCESS;
}
}
return InteractionResult.PASS;
}
}

View file

@ -0,0 +1,23 @@
package com.simibubi.create.content.contraptions.relays.elementary;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
/**
* Implement this interface to indicate that this block is encased.
*/
public interface EncasedBlock {
Block getCasing();
/**
* Handles how encasing should be done if {@link EncasableBlock#tryEncase(BlockState, Level, BlockPos, ItemStack, Player, InteractionHand, BlockHitResult)} is successful.
*/
default void handleEncasing(BlockState state, Level level, BlockPos pos, ItemStack heldItem, Player player, InteractionHand hand, BlockHitResult ray) {
}
}

View file

@ -0,0 +1,36 @@
package com.simibubi.create.content.contraptions.relays.elementary;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import com.tterrag.registrate.builders.BlockBuilder;
import com.tterrag.registrate.util.nullness.NonNullUnaryOperator;
import net.minecraft.core.Registry;
import net.minecraft.world.level.block.Block;
public class EncasingRegistry {
private static final Map<Block, List<Block>> ENCASED_VARIANTS = new HashMap<>();
/**
* <strong>This method must not be called before block registration is finished.</strong>
*/
public static <B extends Block & EncasableBlock, E extends Block & EncasedBlock, P> void addVariant(B encasable, E encased) {
ENCASED_VARIANTS.computeIfAbsent(encasable, b -> new ArrayList<>()).add(encased);
}
public static List<Block> getVariants(Block block) {
return ENCASED_VARIANTS.getOrDefault(block, Collections.emptyList());
}
public static <B extends Block & EncasedBlock, P, E extends Block & EncasableBlock> NonNullUnaryOperator<BlockBuilder<B, P>> addVariantTo(Supplier<E> encasable) {
return builder -> {
builder.onRegisterAfter(Registry.BLOCK_REGISTRY, b -> addVariant(encasable.get(), b));
return builder;
};
}
}

View file

@ -7,7 +7,6 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.base.KineticBlockEntity; import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
import com.simibubi.create.content.contraptions.components.steam.PoweredShaftBlock; import com.simibubi.create.content.contraptions.components.steam.PoweredShaftBlock;
import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftBlock;
import com.simibubi.create.content.curiosities.girder.GirderEncasedShaftBlock; import com.simibubi.create.content.curiosities.girder.GirderEncasedShaftBlock;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
@ -31,7 +30,7 @@ import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
public class ShaftBlock extends AbstractSimpleShaftBlock { public class ShaftBlock extends AbstractSimpleShaftBlock implements EncasableBlock {
public static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); public static final int placementHelperId = PlacementHelpers.register(new PlacementHelper());
@ -77,20 +76,9 @@ public class ShaftBlock extends AbstractSimpleShaftBlock {
return InteractionResult.PASS; return InteractionResult.PASS;
ItemStack heldItem = player.getItemInHand(hand); ItemStack heldItem = player.getItemInHand(hand);
for (EncasedShaftBlock encasedShaft : new EncasedShaftBlock[] { AllBlocks.ANDESITE_ENCASED_SHAFT.get(), InteractionResult result = tryEncase(state, world, pos, heldItem, player, hand, ray);
AllBlocks.BRASS_ENCASED_SHAFT.get() }) { if (result.consumesAction())
return result;
if (!encasedShaft.getCasing()
.isIn(heldItem))
continue;
if (world.isClientSide)
return InteractionResult.SUCCESS;
KineticBlockEntity.switchToBlockState(world, pos, encasedShaft.defaultBlockState()
.setValue(AXIS, state.getValue(AXIS)));
return InteractionResult.SUCCESS;
}
if (AllBlocks.METAL_GIRDER.isIn(heldItem) && state.getValue(AXIS) != Axis.Y) { if (AllBlocks.METAL_GIRDER.isIn(heldItem) && state.getValue(AXIS) != Axis.Y) {
KineticBlockEntity.switchToBlockState(world, pos, AllBlocks.METAL_GIRDER_ENCASED_SHAFT.getDefaultState() KineticBlockEntity.switchToBlockState(world, pos, AllBlocks.METAL_GIRDER_ENCASED_SHAFT.getDefaultState()

View file

@ -1,27 +1,30 @@
package com.simibubi.create.content.contraptions.relays.encased; package com.simibubi.create.content.contraptions.relays.encased;
import java.util.function.Supplier;
import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlockEntityTypes;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.CasingBlock;
import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticBlockEntity; import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock; import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
import com.simibubi.create.content.contraptions.relays.elementary.EncasedBlock;
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
import com.simibubi.create.content.contraptions.relays.elementary.SimpleKineticBlockEntity; import com.simibubi.create.content.contraptions.relays.elementary.SimpleKineticBlockEntity;
import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement;
import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.IBE;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.VoxelShaper; import com.simibubi.create.foundation.utility.VoxelShaper;
import com.tterrag.registrate.util.entry.BlockEntry;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.Axis;
import net.minecraft.core.Direction.AxisDirection; import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.core.NonNullList; import net.minecraft.core.NonNullList;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTab;
@ -43,23 +46,15 @@ import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
public class EncasedCogwheelBlock extends RotatedPillarKineticBlock public class EncasedCogwheelBlock extends RotatedPillarKineticBlock
implements ICogWheel, IBE<SimpleKineticBlockEntity>, ISpecialBlockItemRequirement, ITransformableBlock { implements ICogWheel, IBE<SimpleKineticBlockEntity>, ISpecialBlockItemRequirement, ITransformableBlock, EncasedBlock {
public static final BooleanProperty TOP_SHAFT = BooleanProperty.create("top_shaft"); public static final BooleanProperty TOP_SHAFT = BooleanProperty.create("top_shaft");
public static final BooleanProperty BOTTOM_SHAFT = BooleanProperty.create("bottom_shaft"); public static final BooleanProperty BOTTOM_SHAFT = BooleanProperty.create("bottom_shaft");
boolean isLarge; protected final boolean isLarge;
private BlockEntry<CasingBlock> casing; private final Supplier<Block> casing;
public static EncasedCogwheelBlock andesite(boolean large, Properties properties) { public EncasedCogwheelBlock(Properties properties, boolean large, Supplier<Block> casing) {
return new EncasedCogwheelBlock(large, properties, AllBlocks.ANDESITE_CASING);
}
public static EncasedCogwheelBlock brass(boolean large, Properties properties) {
return new EncasedCogwheelBlock(large, properties, AllBlocks.BRASS_CASING);
}
public EncasedCogwheelBlock(boolean large, Properties properties, BlockEntry<CasingBlock> casing) {
super(properties); super(properties);
isLarge = large; isLarge = large;
this.casing = casing; this.casing = casing;
@ -81,7 +76,7 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock
return ((BlockHitResult) target).getDirection() return ((BlockHitResult) target).getDirection()
.getAxis() != getRotationAxis(state) .getAxis() != getRotationAxis(state)
? isLarge ? AllBlocks.LARGE_COGWHEEL.asStack() : AllBlocks.COGWHEEL.asStack() ? isLarge ? AllBlocks.LARGE_COGWHEEL.asStack() : AllBlocks.COGWHEEL.asStack()
: getCasing().asStack(); : getCasing().asItem().getDefaultInstance();
return super.getCloneItemStack(state, target, world, pos, player); return super.getCloneItemStack(state, target, world, pos, player);
} }
@ -98,10 +93,6 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock
return stateForPlacement; return stateForPlacement;
} }
public BlockEntry<CasingBlock> getCasing() {
return casing;
}
@Override @Override
public boolean skipRendering(BlockState pState, BlockState pAdjacentBlockState, Direction pDirection) { public boolean skipRendering(BlockState pState, BlockState pAdjacentBlockState, Direction pDirection) {
return pState.getBlock() == pAdjacentBlockState.getBlock() return pState.getBlock() == pAdjacentBlockState.getBlock()
@ -276,4 +267,29 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock
return isLarge ? AllBlockEntityTypes.ENCASED_LARGE_COGWHEEL.get() : AllBlockEntityTypes.ENCASED_COGWHEEL.get(); return isLarge ? AllBlockEntityTypes.ENCASED_LARGE_COGWHEEL.get() : AllBlockEntityTypes.ENCASED_COGWHEEL.get();
} }
@Override
public Block getCasing() {
return casing.get();
}
@Override
public void handleEncasing(BlockState state, Level level, BlockPos pos, ItemStack heldItem, Player player, InteractionHand hand,
BlockHitResult ray) {
BlockState encasedState = defaultBlockState()
.setValue(AXIS, state.getValue(AXIS));
for (Direction d : Iterate.directionsInAxis(state.getValue(AXIS))) {
BlockState adjacentState = level.getBlockState(pos.relative(d));
if (!(adjacentState.getBlock() instanceof IRotate))
continue;
IRotate def = (IRotate) adjacentState.getBlock();
if (!def.hasShaftTowards(level, pos.relative(d), adjacentState, d.getOpposite()))
continue;
encasedState =
encasedState.cycle(d.getAxisDirection() == AxisDirection.POSITIVE ? EncasedCogwheelBlock.TOP_SHAFT
: EncasedCogwheelBlock.BOTTOM_SHAFT);
}
KineticBlockEntity.switchToBlockState(level, pos, encasedState);
}
} }

View file

@ -1,22 +1,26 @@
package com.simibubi.create.content.contraptions.relays.encased; package com.simibubi.create.content.contraptions.relays.encased;
import java.util.function.Supplier;
import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlockEntityTypes;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.CasingBlock;
import com.simibubi.create.content.contraptions.base.KineticBlockEntity; import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
import com.simibubi.create.content.contraptions.relays.elementary.EncasedBlock;
import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement;
import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.IBE;
import com.tterrag.registrate.util.entry.BlockEntry;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList; import net.minecraft.core.NonNullList;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
@ -25,27 +29,15 @@ import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
public class EncasedShaftBlock extends AbstractEncasedShaftBlock public class EncasedShaftBlock extends AbstractEncasedShaftBlock
implements IBE<KineticBlockEntity>, ISpecialBlockItemRequirement { implements IBE<KineticBlockEntity>, ISpecialBlockItemRequirement, EncasedBlock {
private BlockEntry<CasingBlock> casing; private final Supplier<Block> casing;
public static EncasedShaftBlock andesite(Properties properties) { public EncasedShaftBlock(Properties properties, Supplier<Block> casing) {
return new EncasedShaftBlock(properties, AllBlocks.ANDESITE_CASING);
}
public static EncasedShaftBlock brass(Properties properties) {
return new EncasedShaftBlock(properties, AllBlocks.BRASS_CASING);
}
protected EncasedShaftBlock(Properties properties, BlockEntry<CasingBlock> casing) {
super(properties); super(properties);
this.casing = casing; this.casing = casing;
} }
public BlockEntry<CasingBlock> getCasing() {
return casing;
}
@Override @Override
public void fillItemCategory(CreativeModeTab pTab, NonNullList<ItemStack> pItems) {} public void fillItemCategory(CreativeModeTab pTab, NonNullList<ItemStack> pItems) {}
@ -65,7 +57,7 @@ public class EncasedShaftBlock extends AbstractEncasedShaftBlock
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) { public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) {
if (target instanceof BlockHitResult) if (target instanceof BlockHitResult)
return ((BlockHitResult) target).getDirection() return ((BlockHitResult) target).getDirection()
.getAxis() == getRotationAxis(state) ? AllBlocks.SHAFT.asStack() : getCasing().asStack(); .getAxis() == getRotationAxis(state) ? AllBlocks.SHAFT.asStack() : getCasing().asItem().getDefaultInstance();
return super.getCloneItemStack(state, target, world, pos, player); return super.getCloneItemStack(state, target, world, pos, player);
} }
@ -84,4 +76,15 @@ public class EncasedShaftBlock extends AbstractEncasedShaftBlock
return AllBlockEntityTypes.ENCASED_SHAFT.get(); return AllBlockEntityTypes.ENCASED_SHAFT.get();
} }
@Override
public Block getCasing() {
return casing.get();
}
@Override
public void handleEncasing(BlockState state, Level level, BlockPos pos, ItemStack heldItem, Player player, InteractionHand hand,
BlockHitResult ray) {
KineticBlockEntity.switchToBlockState(level, pos, defaultBlockState()
.setValue(RotatedPillarKineticBlock.AXIS, state.getValue(RotatedPillarKineticBlock.AXIS)));
}
} }

View file

@ -0,0 +1,56 @@
package com.simibubi.create.content.contraptions.wrench;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllTags.AllItemTags;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class WrenchEventHandler {
@SubscribeEvent(priority = EventPriority.HIGH)
public static void useOwnWrenchLogicForCreateBlocks(PlayerInteractEvent.RightClickBlock event) {
Player player = event.getPlayer();
ItemStack itemStack = event.getItemStack();
if (event.isCanceled())
return;
if (event.getWorld() == null)
return;
if (player == null || !player.mayBuild())
return;
if (itemStack.isEmpty())
return;
if (AllItems.WRENCH.isIn(itemStack))
return;
if (!AllItemTags.WRENCH.matches(itemStack.getItem()))
return;
BlockState state = event.getWorld()
.getBlockState(event.getPos());
Block block = state.getBlock();
if (!(block instanceof IWrenchable))
return;
BlockHitResult hitVec = event.getHitVec();
UseOnContext context = new UseOnContext(player, event.getHand(), hitVec);
IWrenchable actor = (IWrenchable) block;
InteractionResult result =
player.isShiftKeyDown() ? actor.onSneakWrenched(state, context) : actor.onWrenched(state, context);
event.setCanceled(true);
event.setCancellationResult(result);
}
}

View file

@ -209,7 +209,7 @@ public class EjectorBlockEntity extends KineticBlockEntity {
; ;
else if (remainder.isEmpty()) else if (remainder.isEmpty())
depotBehaviour.removeHeldItem(); depotBehaviour.removeHeldItem();
else if (!remainder.sameItem(heldItemStack)) else if (remainder.getCount() != heldItemStack.getCount())
depotBehaviour.heldItem.stack = remainder; depotBehaviour.heldItem.stack = remainder;
} }

View file

@ -54,22 +54,26 @@ public class TrackGraphSync {
public void nodeAdded(TrackGraph graph, TrackNode node) { public void nodeAdded(TrackGraph graph, TrackNode node) {
flushGraphPacket(graph); flushGraphPacket(graph);
currentGraphSyncPacket.addedNodes.put(node.getNetId(), Pair.of(node.getLocation(), node.getNormal())); currentGraphSyncPacket.addedNodes.put(node.getNetId(), Pair.of(node.getLocation(), node.getNormal()));
currentPayload++;
} }
public void edgeAdded(TrackGraph graph, TrackNode node1, TrackNode node2, TrackEdge edge) { public void edgeAdded(TrackGraph graph, TrackNode node1, TrackNode node2, TrackEdge edge) {
flushGraphPacket(graph); flushGraphPacket(graph);
currentGraphSyncPacket.addedEdges currentGraphSyncPacket.addedEdges
.add(Pair.of(Couple.create(node1.getNetId(), node2.getNetId()), edge.getTurn())); .add(Pair.of(Couple.create(node1.getNetId(), node2.getNetId()), edge.getTurn()));
currentPayload++;
} }
public void pointAdded(TrackGraph graph, TrackEdgePoint point) { public void pointAdded(TrackGraph graph, TrackEdgePoint point) {
flushGraphPacket(graph); flushGraphPacket(graph);
currentGraphSyncPacket.addedEdgePoints.add(point); currentGraphSyncPacket.addedEdgePoints.add(point);
currentPayload++;
} }
public void pointRemoved(TrackGraph graph, TrackEdgePoint point) { public void pointRemoved(TrackGraph graph, TrackEdgePoint point) {
flushGraphPacket(graph); flushGraphPacket(graph);
currentGraphSyncPacket.removedEdgePoints.add(point.getId()); currentGraphSyncPacket.removedEdgePoints.add(point.getId());
currentPayload++;
} }
public void nodeRemoved(TrackGraph graph, TrackNode node) { public void nodeRemoved(TrackGraph graph, TrackNode node) {
@ -120,12 +124,14 @@ public class TrackGraphSync {
public void edgeDataChanged(TrackGraph graph, TrackNode node1, TrackNode node2, TrackEdge edge) { public void edgeDataChanged(TrackGraph graph, TrackNode node1, TrackNode node2, TrackEdge edge) {
flushGraphPacket(graph); flushGraphPacket(graph);
currentGraphSyncPacket.syncEdgeData(node1, node2, edge); currentGraphSyncPacket.syncEdgeData(node1, node2, edge);
currentPayload++;
} }
public void edgeDataChanged(TrackGraph graph, TrackNode node1, TrackNode node2, TrackEdge edge, TrackEdge edge2) { public void edgeDataChanged(TrackGraph graph, TrackNode node1, TrackNode node2, TrackEdge edge, TrackEdge edge2) {
flushGraphPacket(graph); flushGraphPacket(graph);
currentGraphSyncPacket.syncEdgeData(node1, node2, edge); currentGraphSyncPacket.syncEdgeData(node1, node2, edge);
currentGraphSyncPacket.syncEdgeData(node2, node1, edge2); currentGraphSyncPacket.syncEdgeData(node2, node1, edge2);
currentPayload++;
} }
public void sendFullGraphTo(TrackGraph graph, ServerPlayer player) { public void sendFullGraphTo(TrackGraph graph, ServerPlayer player) {
@ -190,6 +196,7 @@ public class TrackGraphSync {
// //
private TrackGraphSyncPacket currentGraphSyncPacket; private TrackGraphSyncPacket currentGraphSyncPacket;
private int currentPayload;
private void flushGraphPacket() { private void flushGraphPacket() {
flushGraphPacket(null, 0); flushGraphPacket(null, 0);
@ -201,14 +208,17 @@ public class TrackGraphSync {
private void flushGraphPacket(@Nullable UUID graphId, int netId) { private void flushGraphPacket(@Nullable UUID graphId, int netId) {
if (currentGraphSyncPacket != null) { if (currentGraphSyncPacket != null) {
if (currentGraphSyncPacket.graphId.equals(graphId)) if (currentGraphSyncPacket.graphId.equals(graphId) && currentPayload < 1000)
return; return;
queuedPackets.add(currentGraphSyncPacket); queuedPackets.add(currentGraphSyncPacket);
currentGraphSyncPacket = null; currentGraphSyncPacket = null;
currentPayload = 0;
} }
if (graphId != null) if (graphId != null) {
currentGraphSyncPacket = new TrackGraphSyncPacket(graphId, netId); currentGraphSyncPacket = new TrackGraphSyncPacket(graphId, netId);
currentPayload = 0;
}
} }
} }

View file

@ -16,6 +16,8 @@ import java.util.function.Function;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import net.minecraft.server.MinecraftServer;
import org.apache.commons.lang3.mutable.MutableDouble; import org.apache.commons.lang3.mutable.MutableDouble;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
@ -129,7 +131,7 @@ public class Carriage {
boolean onTwoBogeys = isOnTwoBogeys(); boolean onTwoBogeys = isOnTwoBogeys();
double stress = train.derailed ? 0 : onTwoBogeys ? bogeySpacing - getAnchorDiff() : 0; double stress = train.derailed ? 0 : onTwoBogeys ? bogeySpacing - getAnchorDiff() : 0;
blocked = false; blocked = false;
MutableDouble distanceMoved = new MutableDouble(distance); MutableDouble distanceMoved = new MutableDouble(distance);
boolean iterateFromBack = distance < 0; boolean iterateFromBack = distance < 0;
@ -141,7 +143,7 @@ public class Carriage {
CarriageBogey bogey = bogeys.get(actuallyFirstBogey); CarriageBogey bogey = bogeys.get(actuallyFirstBogey);
double bogeyCorrection = stress * (actuallyFirstBogey ? 0.5d : -0.5d); double bogeyCorrection = stress * (actuallyFirstBogey ? 0.5d : -0.5d);
double bogeyStress = bogey.getStress(); double bogeyStress = bogey.getStress();
for (boolean firstWheel : Iterate.trueAndFalse) { for (boolean firstWheel : Iterate.trueAndFalse) {
boolean actuallyFirstWheel = firstWheel ^ iterateFromBack; boolean actuallyFirstWheel = firstWheel ^ iterateFromBack;
TravellingPoint point = bogey.points.get(actuallyFirstWheel); TravellingPoint point = bogey.points.get(actuallyFirstWheel);
@ -249,8 +251,11 @@ public class Carriage {
boolean discard = boolean discard =
!currentlyTraversedDimensions.isEmpty() && !currentlyTraversedDimensions.contains(entry.getKey()); !currentlyTraversedDimensions.isEmpty() && !currentlyTraversedDimensions.contains(entry.getKey());
ServerLevel currentLevel = level.getServer()
.getLevel(entry.getKey()); MinecraftServer server = level.getServer();
if (server == null)
continue;
ServerLevel currentLevel = server.getLevel(entry.getKey());
if (currentLevel == null) if (currentLevel == null)
continue; continue;
@ -848,7 +853,7 @@ public class Carriage {
train.carriageWaitingForChunks = id; train.carriageWaitingForChunks = id;
return; return;
} }
if (entity.getPassengers() if (entity.getPassengers()
.stream() .stream()
.anyMatch(p -> p instanceof Player) .anyMatch(p -> p instanceof Player)

View file

@ -117,9 +117,7 @@ public class CarriageSyncData {
TrackGraph graph = carriage.train.graph; TrackGraph graph = carriage.train.graph;
if (graph == null) { if (graph == null) {
fallbackLocations = Pair.of(dce.positionAnchor, dce.rotationAnchors); updateFallbackLocations(dce);
dce.pointsInitialised = true;
setDirty(true);
return; return;
} }
@ -129,13 +127,19 @@ public class CarriageSyncData {
for (boolean first : Iterate.trueAndFalse) { for (boolean first : Iterate.trueAndFalse) {
if (!first && !carriage.isOnTwoBogeys()) if (!first && !carriage.isOnTwoBogeys())
break; break;
CarriageBogey bogey = carriage.bogeys.get(first); CarriageBogey bogey = carriage.bogeys.get(first);
for (boolean firstPoint : Iterate.trueAndFalse) { for (boolean firstPoint : Iterate.trueAndFalse) {
TravellingPoint point = bogey.points.get(firstPoint); TravellingPoint point = bogey.points.get(firstPoint);
int index = (first ? 0 : 2) + (firstPoint ? 0 : 1); int index = (first ? 0 : 2) + (firstPoint ? 0 : 1);
Pair<Couple<Integer>, Float> pair = Couple<TrackNode> nodes = Couple.create(point.node1, point.node2);
Pair.of(Couple.create(point.node1.getNetId(), point.node2.getNetId()), (float) point.position);
wheelLocations.set(index, pair); if (nodes.either(Objects::isNull)) {
updateFallbackLocations(dce);
return;
}
wheelLocations.set(index, Pair.of(nodes.map(TrackNode::getNetId), (float) point.position));
} }
} }
@ -143,6 +147,12 @@ public class CarriageSyncData {
setDirty(true); setDirty(true);
} }
private void updateFallbackLocations(DimensionalCarriageEntity dce) {
fallbackLocations = Pair.of(dce.positionAnchor, dce.rotationAnchors);
dce.pointsInitialised = true;
setDirty(true);
}
public void apply(CarriageContraptionEntity entity, Carriage carriage) { public void apply(CarriageContraptionEntity entity, Carriage carriage) {
DimensionalCarriageEntity dce = carriage.getDimensional(entity.level); DimensionalCarriageEntity dce = carriage.getDimensional(entity.level);

View file

@ -138,7 +138,11 @@ public class FlapDisplayBlockEntity extends KineticBlockEntity {
} }
public void applyTextManually(int lineIndex, String rawComponentText) { public void applyTextManually(int lineIndex, String rawComponentText) {
FlapDisplayLayout layout = getLines().get(lineIndex); List<FlapDisplayLayout> lines = getLines();
if (lineIndex >= lines.size())
return;
FlapDisplayLayout layout = lines.get(lineIndex);
if (!layout.isLayout("Default")) if (!layout.isLayout("Default"))
layout.loadDefault(getMaxCharCount()); layout.loadDefault(getMaxCharCount());
List<FlapDisplaySection> sections = layout.getSections(); List<FlapDisplaySection> sections = layout.getSections();

View file

@ -5,6 +5,7 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks; import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks;
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
import com.simibubi.create.content.schematics.item.SchematicItem; import com.simibubi.create.content.schematics.item.SchematicItem;
@ -37,6 +38,7 @@ public class SchematicPrinter {
} }
private boolean schematicLoaded; private boolean schematicLoaded;
private boolean isErrored;
private SchematicWorld blockReader; private SchematicWorld blockReader;
private BlockPos schematicAnchor; private BlockPos schematicAnchor;
@ -93,7 +95,16 @@ public class SchematicPrinter {
schematicAnchor = NbtUtils.readBlockPos(blueprint.getTag() schematicAnchor = NbtUtils.readBlockPos(blueprint.getTag()
.getCompound("Anchor")); .getCompound("Anchor"));
blockReader = new SchematicWorld(schematicAnchor, originalWorld); blockReader = new SchematicWorld(schematicAnchor, originalWorld);
activeTemplate.placeInWorld(blockReader, schematicAnchor, schematicAnchor, settings, blockReader.getRandom(), Block.UPDATE_CLIENTS);
try {
activeTemplate.placeInWorld(blockReader, schematicAnchor, schematicAnchor, settings,
blockReader.getRandom(), Block.UPDATE_CLIENTS);
} catch (Exception e) {
Create.LOGGER.error("Failed to load Schematic for Printing", e);
schematicLoaded = true;
isErrored = true;
return;
}
BlockPos extraBounds = StructureTemplate.calculateRelativePosition(settings, new BlockPos(activeTemplate.getSize()) BlockPos extraBounds = StructureTemplate.calculateRelativePosition(settings, new BlockPos(activeTemplate.getSize())
.offset(-1, -1, -1)); .offset(-1, -1, -1));
@ -115,6 +126,7 @@ public class SchematicPrinter {
public void resetSchematic() { public void resetSchematic() {
schematicLoaded = false; schematicLoaded = false;
schematicAnchor = null; schematicAnchor = null;
isErrored = false;
currentPos = null; currentPos = null;
blockReader = null; blockReader = null;
printingEntityIndex = -1; printingEntityIndex = -1;
@ -125,9 +137,13 @@ public class SchematicPrinter {
public boolean isLoaded() { public boolean isLoaded() {
return schematicLoaded; return schematicLoaded;
} }
public boolean isErrored() {
return isErrored;
}
public BlockPos getCurrentTarget() { public BlockPos getCurrentTarget() {
if (!isLoaded()) if (!isLoaded() || isErrored())
return null; return null;
return schematicAnchor.offset(currentPos); return schematicAnchor.offset(currentPos);
} }

View file

@ -303,8 +303,9 @@ public class SchematicannonBlockEntity extends SmartBlockEntity implements MenuP
protected void tickPrinter() { protected void tickPrinter() {
ItemStack blueprint = inventory.getStackInSlot(0); ItemStack blueprint = inventory.getStackInSlot(0);
blockSkipped = false; blockSkipped = false;
if (blueprint.isEmpty() && !statusMsg.equals("idle")) { if (blueprint.isEmpty() && !statusMsg.equals("idle") && inventory.getStackInSlot(1)
.isEmpty()) {
state = State.STOPPED; state = State.STOPPED;
statusMsg = "idle"; statusMsg = "idle";
sendUpdate = true; sendUpdate = true;
@ -448,12 +449,23 @@ public class SchematicannonBlockEntity extends SmartBlockEntity implements MenuP
// Load blocks into reader // Load blocks into reader
printer.loadSchematic(blueprint, level, true); printer.loadSchematic(blueprint, level, true);
if (printer.isErrored()) {
state = State.STOPPED;
statusMsg = "schematicErrored";
inventory.setStackInSlot(0, ItemStack.EMPTY);
inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get()));
printer.resetSchematic();
sendUpdate = true;
return;
}
if (printer.isWorldEmpty()) { if (printer.isWorldEmpty()) {
state = State.STOPPED; state = State.STOPPED;
statusMsg = "schematicExpired"; statusMsg = "schematicExpired";
inventory.setStackInSlot(0, ItemStack.EMPTY); inventory.setStackInSlot(0, ItemStack.EMPTY);
inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get())); inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get()));
printer.resetSchematic(); printer.resetSchematic();
sendUpdate = true;
return; return;
} }
@ -462,6 +474,7 @@ public class SchematicannonBlockEntity extends SmartBlockEntity implements MenuP
state = State.STOPPED; state = State.STOPPED;
statusMsg = "targetOutsideRange"; statusMsg = "targetOutsideRange";
printer.resetSchematic(); printer.resetSchematic();
sendUpdate = true;
return; return;
} }
@ -663,6 +676,9 @@ public class SchematicannonBlockEntity extends SmartBlockEntity implements MenuP
boolean outputFull = inventory.getStackInSlot(BookOutput) boolean outputFull = inventory.getStackInSlot(BookOutput)
.getCount() == inventory.getSlotLimit(BookOutput); .getCount() == inventory.getSlotLimit(BookOutput);
if (printer.isErrored())
return;
if (!printer.isLoaded()) { if (!printer.isLoaded()) {
if (!blueprint.isEmpty()) if (!blueprint.isEmpty())
initializePrinter(blueprint); initializePrinter(blueprint);
@ -796,11 +812,12 @@ public class SchematicannonBlockEntity extends SmartBlockEntity implements MenuP
checklist.damageRequired.clear(); checklist.damageRequired.clear();
checklist.blocksNotLoaded = false; checklist.blocksNotLoaded = false;
if (printer.isLoaded()) { if (printer.isLoaded() && !printer.isErrored()) {
blocksToPlace = blocksPlaced; blocksToPlace = blocksPlaced;
blocksToPlace += printer.markAllBlockRequirements(checklist, level, this::shouldPlace); blocksToPlace += printer.markAllBlockRequirements(checklist, level, this::shouldPlace);
printer.markAllEntityRequirements(checklist); printer.markAllEntityRequirements(checklist);
} }
checklist.gathered.clear(); checklist.gathered.clear();
findInventories(); findInventories();
for (LazyOptional<IItemHandler> cap : attachedInventories) { for (LazyOptional<IItemHandler> cap : attachedInventories) {

View file

@ -310,6 +310,10 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
} }
font.drawShadow(ms, msg, x + 103 - stringWidth / 2, y + 53, 0xCCDDFF); font.drawShadow(ms, msg, x + 103 - stringWidth / 2, y + 53, 0xCCDDFF);
if ("schematicErrored".equals(te.statusMsg))
font.drawShadow(ms, Lang.translateDirect("schematicannon.status.schematicErroredCheckLogs"),
x + 103 - stringWidth / 2, y + 65, 0xCCDDFF);
} }
protected void renderBlueprintHighlight(PoseStack matrixStack, int x, int y) { protected void renderBlueprintHighlight(PoseStack matrixStack, int x, int y) {

View file

@ -8,6 +8,7 @@ import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.AllKeys; import com.simibubi.create.AllKeys;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
import com.simibubi.create.content.schematics.SchematicWorld; import com.simibubi.create.content.schematics.SchematicWorld;
import com.simibubi.create.content.schematics.client.tools.Tools; import com.simibubi.create.content.schematics.client.tools.Tools;
@ -18,6 +19,7 @@ import com.simibubi.create.content.schematics.packet.SchematicSyncPacket;
import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.outliner.AABBOutline; import com.simibubi.create.foundation.utility.outliner.AABBOutline;
@ -157,7 +159,15 @@ public class SchematicHandler {
BlockPos pos; BlockPos pos;
pos = BlockPos.ZERO; pos = BlockPos.ZERO;
schematic.placeInWorld(w, pos, pos, placementSettings, w.getRandom(), Block.UPDATE_CLIENTS);
try {
schematic.placeInWorld(w, pos, pos, placementSettings, w.getRandom(), Block.UPDATE_CLIENTS);
} catch (Exception e) {
Minecraft.getInstance().player.displayClientMessage(Lang.translate("schematic.error")
.component(), false);
Create.LOGGER.error("Failed to load Schematic for Previewing", e);
return;
}
placementSettings.setMirror(Mirror.FRONT_BACK); placementSettings.setMirror(Mirror.FRONT_BACK);
pos = BlockPos.ZERO.east(size.getX() - 1); pos = BlockPos.ZERO.east(size.getX() - 1);

View file

@ -39,7 +39,7 @@ public class SchematicPlacePacket extends SimplePacketBase {
Level world = player.getLevel(); Level world = player.getLevel();
SchematicPrinter printer = new SchematicPrinter(); SchematicPrinter printer = new SchematicPrinter();
printer.loadSchematic(stack, world, !player.canUseGameMasterBlocks()); printer.loadSchematic(stack, world, !player.canUseGameMasterBlocks());
if (!printer.isLoaded()) if (!printer.isLoaded() || printer.isErrored())
return; return;
boolean includeAir = AllConfigs.server().schematics.creativePrintIncludesAir.get(); boolean includeAir = AllConfigs.server().schematics.creativePrintIncludesAir.get();

View file

@ -60,6 +60,7 @@ import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.forgespi.language.IModFileInfo; import net.minecraftforge.forgespi.language.IModFileInfo;
@ -120,9 +121,11 @@ public class CommonEvents {
} }
@SubscribeEvent @SubscribeEvent
public static void onWorldTick(WorldTickEvent event) { public static void onServerWorldTick(WorldTickEvent event) {
if (event.phase == Phase.START) if (event.phase == Phase.START)
return; return;
if (event.side == LogicalSide.CLIENT)
return;
Level world = event.world; Level world = event.world;
ContraptionHandler.tick(world); ContraptionHandler.tick(world);
CapabilityMinecartController.tick(world); CapabilityMinecartController.tick(world);

View file

@ -3,28 +3,19 @@ package com.simibubi.create.foundation.data;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects; import java.util.Objects;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.mutable.MutableObject; import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.commons.lang3.tuple.Pair;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderScene;
import com.simibubi.create.foundation.utility.FilesHelper;
import net.minecraft.data.DataGenerator; import net.minecraft.data.DataGenerator;
import net.minecraft.data.DataProvider; import net.minecraft.data.DataProvider;
@ -44,10 +35,6 @@ public class LangMerger implements DataProvider {
private final LangPartial[] langPartials; private final LangPartial[] langPartials;
private List<Object> mergedLangData; private List<Object> mergedLangData;
private Map<String, List<Object>> populatedLangData;
private Map<String, Map<String, String>> allLocalizedEntries;
private Map<String, MutableInt> missingTranslationTally;
private List<String> langIgnore; private List<String> langIgnore;
public <T extends LangPartial> LangMerger(DataGenerator gen, String modid, String displayName, T[] langPartials) { public <T extends LangPartial> LangMerger(DataGenerator gen, String modid, String displayName, T[] langPartials) {
@ -57,9 +44,6 @@ public class LangMerger implements DataProvider {
this.langPartials = langPartials; this.langPartials = langPartials;
this.mergedLangData = new ArrayList<>(); this.mergedLangData = new ArrayList<>();
this.langIgnore = new ArrayList<>(); this.langIgnore = new ArrayList<>();
this.allLocalizedEntries = new HashMap<>();
this.populatedLangData = new HashMap<>();
this.missingTranslationTally = new HashMap<>();
populateLangIgnore(); populateLangIgnore();
} }
@ -86,42 +70,11 @@ public class LangMerger implements DataProvider {
Path path = this.gen.getOutputFolder() Path path = this.gen.getOutputFolder()
.resolve("assets/" + modid + "/lang/" + "en_us.json"); .resolve("assets/" + modid + "/lang/" + "en_us.json");
for (Pair<String, JsonElement> pair : getAllLocalizationFiles()) {
if (!pair.getRight()
.isJsonObject())
continue;
Map<String, String> localizedEntries = new HashMap<>();
JsonObject jsonobject = pair.getRight()
.getAsJsonObject();
jsonobject.entrySet()
.stream()
.forEachOrdered(entry -> {
String key = entry.getKey();
if (key.startsWith("_"))
return;
String value = entry.getValue()
.getAsString();
localizedEntries.put(key, value);
});
String key = pair.getKey();
allLocalizedEntries.put(key, localizedEntries);
populatedLangData.put(key, new ArrayList<>());
missingTranslationTally.put(key, new MutableInt(0));
}
collectExistingEntries(path); collectExistingEntries(path);
collectEntries(); collectEntries();
if (mergedLangData.isEmpty()) if (mergedLangData.isEmpty())
return; return;
save(cache, mergedLangData, path, "Merging en_us.json with hand-written lang entries...");
save(cache, mergedLangData, -1, path, "Merging en_us.json with hand-written lang entries...");
for (Entry<String, List<Object>> localization : populatedLangData.entrySet()) {
String key = localization.getKey();
Path populatedLangPath = this.gen.getOutputFolder()
.resolve("assets/" + modid + "/lang/unfinished/" + key);
save(cache, localization.getValue(), missingTranslationTally.get(key)
.intValue(), populatedLangPath, "Populating " + key + " with missing entries...");
}
} }
private void collectExistingEntries(Path path) throws IOException { private void collectExistingEntries(Path path) throws IOException {
@ -167,19 +120,10 @@ public class LangMerger implements DataProvider {
private void writeData(String data) { private void writeData(String data) {
mergedLangData.add(data); mergedLangData.add(data);
populatedLangData.values()
.forEach(l -> l.add(data));
} }
private void writeEntry(String key, String value) { private void writeEntry(String key, String value) {
mergedLangData.add(new LangEntry(key, value)); mergedLangData.add(new LangEntry(key, value));
populatedLangData.forEach((k, l) -> {
ForeignLangEntry entry = new ForeignLangEntry(key, value, allLocalizedEntries.get(k));
if (entry.isMissing())
missingTranslationTally.get(k)
.increment();
l.add(entry);
});
} }
protected boolean shouldAddLineBreak(String key, String previousKey) { protected boolean shouldAddLineBreak(String key, String previousKey) {
@ -201,40 +145,15 @@ public class LangMerger implements DataProvider {
return !split[0].equals(split2[0]); return !split[0].equals(split2[0]);
} }
private List<Pair<String, JsonElement>> getAllLocalizationFiles() {
ArrayList<Pair<String, JsonElement>> list = new ArrayList<>();
String filepath = "assets/" + modid + "/lang/";
try (InputStream resourceStream = ClassLoader.getSystemResourceAsStream(filepath)) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resourceStream));
while (true) {
String readLine = bufferedReader.readLine();
if (readLine == null)
break;
if (!readLine.endsWith(".json"))
continue;
if (readLine.startsWith("en_us") || readLine.startsWith("en_ud"))
continue;
list.add(Pair.of(readLine, FilesHelper.loadJsonResource(filepath + readLine)));
}
} catch (IOException | NullPointerException e) {
e.printStackTrace();
}
return list;
}
private void collectEntries() { private void collectEntries() {
for (LangPartial partial : langPartials) for (LangPartial partial : langPartials)
addAll(partial.getDisplayName(), partial.provide() addAll(partial.getDisplayName(), partial.provide()
.getAsJsonObject()); .getAsJsonObject());
} }
private void save(HashCache cache, List<Object> dataIn, int missingKeys, Path target, String message) private void save(HashCache cache, List<Object> dataIn, Path target, String message)
throws IOException { throws IOException {
String data = createString(dataIn, missingKeys); String data = createString(dataIn);
// data = JavaUnicodeEscaper.outsideOf(0, 0x7f)
// .translate(data);
String hash = DataProvider.SHA1.hashUnencodedChars(data) String hash = DataProvider.SHA1.hashUnencodedChars(data)
.toString(); .toString();
if (!Objects.equals(cache.getHash(target), hash) || !Files.exists(target)) { if (!Objects.equals(cache.getHash(target), hash) || !Files.exists(target)) {
@ -249,11 +168,9 @@ public class LangMerger implements DataProvider {
cache.putNew(target, hash); cache.putNew(target, hash);
} }
protected String createString(List<Object> data, int missingKeys) { protected String createString(List<Object> data) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("{\n"); builder.append("{\n");
if (missingKeys != -1)
builder.append("\t\"_\": \"Missing Localizations: " + missingKeys + "\",\n");
data.forEach(builder::append); data.forEach(builder::append);
builder.append("\t\"_\": \"Thank you for translating ").append(displayName).append("!\"\n\n"); builder.append("\t\"_\": \"Thank you for translating ").append(displayName).append("!\"\n\n");
builder.append("}"); builder.append("}");
@ -278,19 +195,4 @@ public class LangMerger implements DataProvider {
} }
private class ForeignLangEntry extends LangEntry {
private boolean missing;
ForeignLangEntry(String key, String value, Map<String, String> localizationMap) {
super(key, localizationMap.getOrDefault(key, "UNLOCALIZED: " + value));
missing = !localizationMap.containsKey(key);
}
public boolean isMissing() {
return missing;
}
}
} }

View file

@ -274,6 +274,7 @@
"create.schematicAndQuill.saved": "Saved as %1$s", "create.schematicAndQuill.saved": "Saved as %1$s",
"create.schematic.invalid": "[!] Invalid Item - Use the Schematic Table instead", "create.schematic.invalid": "[!] Invalid Item - Use the Schematic Table instead",
"create.schematic.error": "Schematic failed to Load - Check Game Logs",
"create.schematic.position": "Position", "create.schematic.position": "Position",
"create.schematic.rotation": "Rotation", "create.schematic.rotation": "Rotation",
"create.schematic.rotation.none": "None", "create.schematic.rotation.none": "None",
@ -372,6 +373,8 @@
"create.schematicannon.status.schematicInvalid": "Schematic Invalid", "create.schematicannon.status.schematicInvalid": "Schematic Invalid",
"create.schematicannon.status.schematicNotPlaced": "Schematic not Positioned", "create.schematicannon.status.schematicNotPlaced": "Schematic not Positioned",
"create.schematicannon.status.schematicExpired": "Schematic File Expired", "create.schematicannon.status.schematicExpired": "Schematic File Expired",
"create.schematicannon.status.schematicErrored": "Incompatible Blocks",
"create.schematicannon.status.schematicErroredCheckLogs": "Check Server Logs",
"create.materialChecklist": "Material Checklist", "create.materialChecklist": "Material Checklist",
"create.materialChecklist.blocksNotLoaded": "* Disclaimer *\n\nMaterial List may be inaccurate due to relevant chunks not being loaded.", "create.materialChecklist.blocksNotLoaded": "* Disclaimer *\n\nMaterial List may be inaccurate due to relevant chunks not being loaded.",
@ -930,6 +933,9 @@
"create.command.killTPSCommand.argument.tickTime": "tickTime", "create.command.killTPSCommand.argument.tickTime": "tickTime",
"create.contraption.minecart_contraption_too_big": "This Cart Contraption seems too big to pick up", "create.contraption.minecart_contraption_too_big": "This Cart Contraption seems too big to pick up",
"create.contraption.minecart_contraption_illegal_pickup": "A mystical force is binding this Cart Contraption to the world" "create.contraption.minecart_contraption_illegal_pickup": "A mystical force is binding this Cart Contraption to the world",
"enchantment.create.capacity.desc": "Increases Backtank air capacity.",
"enchantment.create.potato_recovery.desc": "Potato Cannon projectiles have a chance to be reused."
} }

View file

@ -1,31 +0,0 @@
{
"conditions": [
{
"type": "forge:mod_loaded",
"modid": "appliedenergistics2"
}
],
"type": "create:crushing",
"ingredients": [
{
"item": "appliedenergistics2:charged_quartz_ore"
}
],
"results": [
{
"item": "appliedenergistics2:charged_certus_quartz_crystal",
"count": 2
},
{
"item": "appliedenergistics2:certus_quartz_dust",
"count": 1,
"chance": 0.25
},
{
"item": "minecraft:cobblestone",
"count": 1,
"chance": 0.125
}
],
"processingTime": 300
}

View file

@ -0,0 +1,35 @@
{
"conditions": [
{
"type": "forge:mod_loaded",
"modid": "ae2"
}
],
"type": "create:crushing",
"ingredients": [
{
"item": "ae2:deepslate_quartz_ore"
}
],
"results": [
{
"item": "ae2:certus_quartz_crystal",
"count": 1
},
{
"item": "ae2:certus_quartz_dust",
"count": 4
},
{
"item": "ae2:certus_quartz_dust",
"count": 1,
"chance": 0.5
},
{
"item": "minecraft:cobbled_deepslate",
"count": 1,
"chance": 0.125
}
],
"processingTime": 300
}

View file

@ -2,24 +2,28 @@
"conditions": [ "conditions": [
{ {
"type": "forge:mod_loaded", "type": "forge:mod_loaded",
"modid": "appliedenergistics2" "modid": "ae2"
} }
], ],
"type": "create:crushing", "type": "create:crushing",
"ingredients": [ "ingredients": [
{ {
"item": "appliedenergistics2:quartz_ore" "item": "ae2:quartz_ore"
} }
], ],
"results": [ "results": [
{ {
"item": "appliedenergistics2:certus_quartz_crystal", "item": "ae2:certus_quartz_crystal",
"count": 2 "count": 1
}, },
{ {
"item": "appliedenergistics2:certus_quartz_dust", "item": "ae2:certus_quartz_dust",
"count": 4
},
{
"item": "ae2:certus_quartz_dust",
"count": 1, "count": 1,
"chance": 0.25 "chance": 0.5
}, },
{ {
"item": "minecraft:cobblestone", "item": "minecraft:cobblestone",