mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-02-27 20:34:43 +01:00
Merge remote-tracking branch 'origin/mc1.18/0.5.1' into mc1.19/0.5.1
This commit is contained in:
commit
500019465a
219 changed files with 6797 additions and 1078 deletions
23
.github/workflows/gametest.yml
vendored
Normal file
23
.github/workflows/gametest.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
name: gametest
|
||||||
|
on: [ pull_request, push, workflow_dispatch ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: setup Java
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 17
|
||||||
|
cache: gradle
|
||||||
|
|
||||||
|
- name: make gradle wrapper executable
|
||||||
|
run: chmod +x ./gradlew
|
||||||
|
|
||||||
|
- name: run gametests
|
||||||
|
run: ./gradlew prepareRunGameTestServer runGameTestServer --no-daemon
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -43,3 +43,4 @@ local.properties
|
||||||
.buildpath
|
.buildpath
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
/libs/
|
||||||
|
|
35
build.gradle
35
build.gradle
|
@ -90,6 +90,18 @@ minecraft {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gameTestServer {
|
||||||
|
workingDirectory project.file('run/gametest')
|
||||||
|
arg '-mixin.config=create.mixins.json'
|
||||||
|
property 'forge.logging.console.level', 'info'
|
||||||
|
mods {
|
||||||
|
create {
|
||||||
|
source sourceSets.main
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setForceExit false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +147,17 @@ repositories {
|
||||||
includeGroup "maven.modrinth"
|
includeGroup "maven.modrinth"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
flatDir {
|
||||||
|
dirs 'libs'
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
// Location of maven for CC: Tweaked
|
||||||
|
name = "squiddev"
|
||||||
|
url = "https://squiddev.cc/maven/"
|
||||||
|
content {
|
||||||
|
includeGroup "org.squiddev"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -162,6 +185,11 @@ dependencies {
|
||||||
compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}:api")
|
compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}:api")
|
||||||
runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}")
|
runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}")
|
||||||
|
|
||||||
|
if (cc_tweaked_enable.toBoolean()) {
|
||||||
|
compileOnly fg.deobf("org.squiddev:cc-tweaked-${cc_tweaked_minecraft_version}:${cc_tweaked_version}:api")
|
||||||
|
runtimeOnly fg.deobf("org.squiddev:cc-tweaked-${cc_tweaked_minecraft_version}:${cc_tweaked_version}")
|
||||||
|
}
|
||||||
|
|
||||||
// implementation fg.deobf("curse.maven:druidcraft-340991:3101903")
|
// implementation fg.deobf("curse.maven:druidcraft-340991:3101903")
|
||||||
// implementation fg.deobf("com.ferreusveritas.dynamictrees:DynamicTrees-1.16.5:0.10.0-Beta25")
|
// implementation fg.deobf("com.ferreusveritas.dynamictrees:DynamicTrees-1.16.5:0.10.0-Beta25")
|
||||||
// runtimeOnly fg.deobf("vazkii.arl:AutoRegLib:1.4-35.69")
|
// runtimeOnly fg.deobf("vazkii.arl:AutoRegLib:1.4-35.69")
|
||||||
|
@ -169,6 +197,7 @@ dependencies {
|
||||||
// runtimeOnly fg.deobf("slimeknights.mantle:Mantle:1.16.5-1.6.115")
|
// runtimeOnly fg.deobf("slimeknights.mantle:Mantle:1.16.5-1.6.115")
|
||||||
// runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.1.1.252")
|
// runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.1.1.252")
|
||||||
// runtimeOnly fg.deobf("maven.modrinth:rubidium:0.5.3")
|
// 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 }
|
||||||
|
|
||||||
// https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497
|
// https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497
|
||||||
// Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings
|
// Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings
|
||||||
|
@ -178,6 +207,12 @@ dependencies {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sourceSets.main.java {
|
||||||
|
if (!cc_tweaked_enable.toBoolean()) {
|
||||||
|
exclude 'com/simibubi/create/compat/computercraft/implementation/**'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sourceSets.main.resources {
|
sourceSets.main.resources {
|
||||||
srcDir 'src/generated/resources'
|
srcDir 'src/generated/resources'
|
||||||
exclude '.cache/'
|
exclude '.cache/'
|
||||||
|
|
|
@ -27,6 +27,10 @@ jei_version = 11.2.0.254
|
||||||
curios_minecraft_version = 1.19.2
|
curios_minecraft_version = 1.19.2
|
||||||
curios_version = 5.1.1.0
|
curios_version = 5.1.1.0
|
||||||
|
|
||||||
|
cc_tweaked_enable = true
|
||||||
|
cc_tweaked_minecraft_version = 1.18.2
|
||||||
|
cc_tweaked_version = 1.100.10
|
||||||
|
|
||||||
# curseforge information
|
# curseforge information
|
||||||
projectId = 328085
|
projectId = 328085
|
||||||
curse_type = beta
|
curse_type = beta
|
||||||
|
|
|
@ -1192,6 +1192,8 @@
|
||||||
"create.schematicAndQuill.convert": "Save and Upload Immediately",
|
"create.schematicAndQuill.convert": "Save and Upload Immediately",
|
||||||
"create.schematicAndQuill.fallbackName": "My Schematic",
|
"create.schematicAndQuill.fallbackName": "My Schematic",
|
||||||
"create.schematicAndQuill.saved": "Saved as %1$s",
|
"create.schematicAndQuill.saved": "Saved as %1$s",
|
||||||
|
"create.schematicAndQuill.failed": "Failed to save schematic, check logs for details",
|
||||||
|
"create.schematicAndQuill.instant_failed": "Schematic instant-upload failed, check logs for details",
|
||||||
|
|
||||||
"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.error": "Schematic failed to Load - Check Game Logs",
|
||||||
|
@ -1811,6 +1813,7 @@
|
||||||
"create.display_source.redstone_power.progress_bar": "Progress Bar",
|
"create.display_source.redstone_power.progress_bar": "Progress Bar",
|
||||||
"create.display_source.boiler.not_enough_space": "Not enough space ",
|
"create.display_source.boiler.not_enough_space": "Not enough space ",
|
||||||
"create.display_source.boiler.for_boiler_status": "for Boiler Status",
|
"create.display_source.boiler.for_boiler_status": "for Boiler Status",
|
||||||
|
"create.display_source.computer_display_source": "From Computer",
|
||||||
|
|
||||||
"create.display_target.line": "Line %1$s",
|
"create.display_target.line": "Line %1$s",
|
||||||
"create.display_target.page": "Page %1$s",
|
"create.display_target.page": "Page %1$s",
|
||||||
|
@ -1833,6 +1836,8 @@
|
||||||
"create.super_glue.not_enough": "Not enough glue in inventory",
|
"create.super_glue.not_enough": "Not enough glue in inventory",
|
||||||
"create.super_glue.success": "Applying Glue...",
|
"create.super_glue.success": "Applying Glue...",
|
||||||
|
|
||||||
|
"create.gui.attached_computer.controlled": "This device is being controlled by a computer",
|
||||||
|
"create.gui.attached_computer.hint": "To use device manually, disconnect all computers and modems",
|
||||||
"create.gui.config.overlay1": "Hi :)",
|
"create.gui.config.overlay1": "Hi :)",
|
||||||
"create.gui.config.overlay2": "This is a sample overlay",
|
"create.gui.config.overlay2": "This is a sample overlay",
|
||||||
"create.gui.config.overlay3": "Click or drag with your mouse",
|
"create.gui.config.overlay3": "Click or drag with your mouse",
|
||||||
|
@ -1856,6 +1861,12 @@
|
||||||
"enchantment.create.capacity.desc": "Increases Backtank air capacity.",
|
"enchantment.create.capacity.desc": "Increases Backtank air capacity.",
|
||||||
"enchantment.create.potato_recovery.desc": "Potato Cannon projectiles have a chance to be reused.",
|
"enchantment.create.potato_recovery.desc": "Potato Cannon projectiles have a chance to be reused.",
|
||||||
|
|
||||||
|
"create.bogey.style.updated_style": "Updated style",
|
||||||
|
"create.bogey.style.updated_style_and_size": "Updated style and size",
|
||||||
|
"create.bogey.style.no_other_sizes": "No other sizes",
|
||||||
|
"create.bogey.style.invalid": "Unnamed style",
|
||||||
|
"create.bogey.style.standard": "Standard",
|
||||||
|
|
||||||
|
|
||||||
"_": "->------------------------] Subtitles [------------------------<-",
|
"_": "->------------------------] Subtitles [------------------------<-",
|
||||||
|
|
||||||
|
@ -2814,7 +2825,7 @@
|
||||||
"create.ponder.mechanical_roller_fill.text_5": "As opposed to 'clear & pave', neither of these modes will cause the rollers to break existing blocks",
|
"create.ponder.mechanical_roller_fill.text_5": "As opposed to 'clear & pave', neither of these modes will cause the rollers to break existing blocks",
|
||||||
|
|
||||||
"create.ponder.mechanical_roller_pave.header": "Clearing and Paving with the Roller",
|
"create.ponder.mechanical_roller_pave.header": "Clearing and Paving with the Roller",
|
||||||
"create.ponder.mechanical_roller_pave.text_1": "Mechanical rollers help to clean up long tracks or paths conveniently",
|
"create.ponder.mechanical_roller_pave.text_1": "Mechanical rollers help to clean up terrain around tracks or paths",
|
||||||
"create.ponder.mechanical_roller_pave.text_2": "In its default mode, without a material set, it will simply clear blocks like a Drill",
|
"create.ponder.mechanical_roller_pave.text_2": "In its default mode, without a material set, it will simply clear blocks like a Drill",
|
||||||
"create.ponder.mechanical_roller_pave.text_3": "While disassembled, a suitable paving material can be specified",
|
"create.ponder.mechanical_roller_pave.text_3": "While disassembled, a suitable paving material can be specified",
|
||||||
"create.ponder.mechanical_roller_pave.text_4": "Materials can be supplied via chests or barrels attached to the structure",
|
"create.ponder.mechanical_roller_pave.text_4": "Materials can be supplied via chests or barrels attached to the structure",
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"create:track"
|
||||||
|
]
|
||||||
|
}
|
|
@ -18,10 +18,8 @@
|
||||||
"create:andesite_belt_funnel",
|
"create:andesite_belt_funnel",
|
||||||
"create:brass_funnel",
|
"create:brass_funnel",
|
||||||
"create:brass_belt_funnel",
|
"create:brass_belt_funnel",
|
||||||
"create:creative_crate",
|
|
||||||
"create:redstone_link",
|
"create:redstone_link",
|
||||||
"create:analog_lever",
|
"create:analog_lever",
|
||||||
"create:placard",
|
|
||||||
"create:pulse_repeater",
|
"create:pulse_repeater",
|
||||||
"create:pulse_extender",
|
"create:pulse_extender",
|
||||||
"create:clipboard",
|
"create:clipboard",
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"create:track"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"create:copper_diving_boots",
|
||||||
|
"create:netherite_diving_boots"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"create:copper_backtank",
|
||||||
|
"create:netherite_backtank"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"create:copper_diving_helmet",
|
||||||
|
"create:netherite_diving_helmet"
|
||||||
|
]
|
||||||
|
}
|
|
@ -195,6 +195,7 @@ import com.simibubi.create.content.logistics.block.vault.ItemVaultBlockEntity;
|
||||||
import com.simibubi.create.content.logistics.item.LecternControllerBlockEntity;
|
import com.simibubi.create.content.logistics.item.LecternControllerBlockEntity;
|
||||||
import com.simibubi.create.content.logistics.item.LecternControllerRenderer;
|
import com.simibubi.create.content.logistics.item.LecternControllerRenderer;
|
||||||
import com.simibubi.create.content.logistics.trains.BogeyBlockEntityRenderer;
|
import com.simibubi.create.content.logistics.trains.BogeyBlockEntityRenderer;
|
||||||
|
import com.simibubi.create.content.logistics.trains.TrackMaterial;
|
||||||
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayBlockEntity;
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayBlockEntity;
|
||||||
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayRenderer;
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayRenderer;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.observer.TrackObserverBlockEntity;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.observer.TrackObserverBlockEntity;
|
||||||
|
@ -831,8 +832,8 @@ public class AllBlockEntityTypes {
|
||||||
public static final BlockEntityEntry<TrackBlockEntity> TRACK = REGISTRATE
|
public static final BlockEntityEntry<TrackBlockEntity> TRACK = REGISTRATE
|
||||||
.blockEntity("track", TrackBlockEntity::new)
|
.blockEntity("track", TrackBlockEntity::new)
|
||||||
.instance(() -> TrackInstance::new)
|
.instance(() -> TrackInstance::new)
|
||||||
|
.validBlocksDeferred(TrackMaterial::allBlocks)
|
||||||
.renderer(() -> TrackRenderer::new)
|
.renderer(() -> TrackRenderer::new)
|
||||||
.validBlocks(AllBlocks.TRACK)
|
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntityEntry<FakeTrackBlockEntity> FAKE_TRACK = REGISTRATE
|
public static final BlockEntityEntry<FakeTrackBlockEntity> FAKE_TRACK = REGISTRATE
|
||||||
|
@ -859,8 +860,8 @@ public class AllBlockEntityTypes {
|
||||||
AllBlocks.BRASS_DOOR, AllBlocks.COPPER_DOOR)
|
AllBlocks.BRASS_DOOR, AllBlocks.COPPER_DOOR)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntityEntry<CopycatBlockEntity> COPYCAT = REGISTRATE
|
public static final BlockEntityEntry<CopycatBlockEntity> COPYCAT =
|
||||||
.blockEntity("copycat", CopycatBlockEntity::new)
|
REGISTRATE.blockEntity("copycat", CopycatBlockEntity::new)
|
||||||
.validBlocks(AllBlocks.COPYCAT_PANEL, AllBlocks.COPYCAT_STEP)
|
.validBlocks(AllBlocks.COPYCAT_PANEL, AllBlocks.COPYCAT_STEP)
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
|
|
@ -230,6 +230,8 @@ import com.simibubi.create.content.logistics.block.vault.ItemVaultBlock;
|
||||||
import com.simibubi.create.content.logistics.block.vault.ItemVaultCTBehaviour;
|
import com.simibubi.create.content.logistics.block.vault.ItemVaultCTBehaviour;
|
||||||
import com.simibubi.create.content.logistics.block.vault.ItemVaultItem;
|
import com.simibubi.create.content.logistics.block.vault.ItemVaultItem;
|
||||||
import com.simibubi.create.content.logistics.item.LecternControllerBlock;
|
import com.simibubi.create.content.logistics.item.LecternControllerBlock;
|
||||||
|
import com.simibubi.create.content.logistics.trains.BogeySizes;
|
||||||
|
import com.simibubi.create.content.logistics.trains.TrackMaterial;
|
||||||
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayBlock;
|
import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem;
|
||||||
|
@ -718,7 +720,7 @@ public class AllBlocks {
|
||||||
.onRegister(movementBehaviour(new BlazeBurnerMovementBehaviour()))
|
.onRegister(movementBehaviour(new BlazeBurnerMovementBehaviour()))
|
||||||
.onRegister(interactionBehaviour(new BlazeBurnerInteractionBehaviour()))
|
.onRegister(interactionBehaviour(new BlazeBurnerInteractionBehaviour()))
|
||||||
.item(BlazeBurnerBlockItem::withBlaze)
|
.item(BlazeBurnerBlockItem::withBlaze)
|
||||||
.model(AssetLookup.<BlazeBurnerBlockItem>customBlockItemModel("blaze_burner", "block_with_blaze"))
|
.model(AssetLookup.customBlockItemModel("blaze_burner", "block_with_blaze"))
|
||||||
.build()
|
.build()
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
@ -938,7 +940,7 @@ public class AllBlocks {
|
||||||
.onRegister(assignDataBehaviour(new BoilerDisplaySource(), "boiler_status"))
|
.onRegister(assignDataBehaviour(new BoilerDisplaySource(), "boiler_status"))
|
||||||
.addLayer(() -> RenderType::cutoutMipped)
|
.addLayer(() -> RenderType::cutoutMipped)
|
||||||
.item(FluidTankItem::new)
|
.item(FluidTankItem::new)
|
||||||
.model(AssetLookup.<FluidTankItem>customBlockItemModel("_", "block_single_window"))
|
.model(AssetLookup.customBlockItemModel("_", "block_single_window"))
|
||||||
.build()
|
.build()
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
@ -1541,7 +1543,7 @@ public class AllBlocks {
|
||||||
.transform(customItemModel())
|
.transform(customItemModel())
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntry<TrackBlock> TRACK = REGISTRATE.block("track", TrackBlock::new)
|
public static final BlockEntry<TrackBlock> TRACK = REGISTRATE.block("track", TrackMaterial.ANDESITE::createBlock)
|
||||||
.initialProperties(Material.STONE)
|
.initialProperties(Material.STONE)
|
||||||
.properties(p -> p.color(MaterialColor.METAL)
|
.properties(p -> p.color(MaterialColor.METAL)
|
||||||
.strength(0.8F)
|
.strength(0.8F)
|
||||||
|
@ -1552,6 +1554,8 @@ public class AllBlocks {
|
||||||
.onRegister(CreateRegistrate.blockModel(() -> TrackModel::new))
|
.onRegister(CreateRegistrate.blockModel(() -> TrackModel::new))
|
||||||
.blockstate(new TrackBlockStateGenerator()::generate)
|
.blockstate(new TrackBlockStateGenerator()::generate)
|
||||||
.tag(AllBlockTags.RELOCATION_NOT_SUPPORTED.tag)
|
.tag(AllBlockTags.RELOCATION_NOT_SUPPORTED.tag)
|
||||||
|
.tag(AllBlockTags.TRACKS.tag)
|
||||||
|
.tag(AllBlockTags.GIRDABLE_TRACKS.tag)
|
||||||
.lang("Train Track")
|
.lang("Train Track")
|
||||||
.item(TrackBlockItem::new)
|
.item(TrackBlockItem::new)
|
||||||
.model((c, p) -> p.generated(c, Create.asResource("item/" + c.getName())))
|
.model((c, p) -> p.generated(c, Create.asResource("item/" + c.getName())))
|
||||||
|
@ -1620,13 +1624,13 @@ public class AllBlocks {
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntry<StandardBogeyBlock> SMALL_BOGEY =
|
public static final BlockEntry<StandardBogeyBlock> SMALL_BOGEY =
|
||||||
REGISTRATE.block("small_bogey", p -> new StandardBogeyBlock(p, false))
|
REGISTRATE.block("small_bogey", p -> new StandardBogeyBlock(p, BogeySizes.SMALL))
|
||||||
.properties(p -> p.color(MaterialColor.PODZOL))
|
.properties(p -> p.color(MaterialColor.PODZOL))
|
||||||
.transform(BuilderTransformers.bogey())
|
.transform(BuilderTransformers.bogey())
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntry<StandardBogeyBlock> LARGE_BOGEY =
|
public static final BlockEntry<StandardBogeyBlock> LARGE_BOGEY =
|
||||||
REGISTRATE.block("large_bogey", p -> new StandardBogeyBlock(p, true))
|
REGISTRATE.block("large_bogey", p -> new StandardBogeyBlock(p, BogeySizes.LARGE))
|
||||||
.properties(p -> p.color(MaterialColor.PODZOL))
|
.properties(p -> p.color(MaterialColor.PODZOL))
|
||||||
.transform(BuilderTransformers.bogey())
|
.transform(BuilderTransformers.bogey())
|
||||||
.register();
|
.register();
|
||||||
|
@ -1765,7 +1769,6 @@ public class AllBlocks {
|
||||||
REGISTRATE.block("creative_crate", CreativeCrateBlock::new)
|
REGISTRATE.block("creative_crate", CreativeCrateBlock::new)
|
||||||
.transform(BuilderTransformers.crate("creative"))
|
.transform(BuilderTransformers.crate("creative"))
|
||||||
.properties(p -> p.color(MaterialColor.COLOR_PURPLE))
|
.properties(p -> p.color(MaterialColor.COLOR_PURPLE))
|
||||||
.tag(AllBlockTags.SAFE_NBT.tag)
|
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final BlockEntry<DisplayLinkBlock> DISPLAY_LINK =
|
public static final BlockEntry<DisplayLinkBlock> DISPLAY_LINK =
|
||||||
|
@ -1861,7 +1864,6 @@ public class AllBlocks {
|
||||||
public static final BlockEntry<PlacardBlock> PLACARD = REGISTRATE.block("placard", PlacardBlock::new)
|
public static final BlockEntry<PlacardBlock> PLACARD = REGISTRATE.block("placard", PlacardBlock::new)
|
||||||
.initialProperties(SharedProperties::copperMetal)
|
.initialProperties(SharedProperties::copperMetal)
|
||||||
.transform(pickaxeOnly())
|
.transform(pickaxeOnly())
|
||||||
.tag(AllBlockTags.SAFE_NBT.tag)
|
|
||||||
.blockstate((c, p) -> p.horizontalFaceBlock(c.get(), AssetLookup.standardModel(c, p)))
|
.blockstate((c, p) -> p.horizontalFaceBlock(c.get(), AssetLookup.standardModel(c, p)))
|
||||||
.simpleItem()
|
.simpleItem()
|
||||||
.register();
|
.register();
|
||||||
|
|
122
src/main/java/com/simibubi/create/AllBogeyStyles.java
Normal file
122
src/main/java/com/simibubi/create/AllBogeyStyles.java
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
package com.simibubi.create;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock;
|
||||||
|
import com.simibubi.create.content.logistics.trains.BogeyRenderer;
|
||||||
|
import com.simibubi.create.content.logistics.trains.BogeyRenderer.CommonRenderer;
|
||||||
|
import com.simibubi.create.content.logistics.trains.BogeySizes;
|
||||||
|
import com.simibubi.create.content.logistics.trains.StandardBogeyRenderer.CommonStandardBogeyRenderer;
|
||||||
|
import com.simibubi.create.content.logistics.trains.StandardBogeyRenderer.LargeStandardBogeyRenderer;
|
||||||
|
import com.simibubi.create.content.logistics.trains.StandardBogeyRenderer.SmallStandardBogeyRenderer;
|
||||||
|
import com.simibubi.create.content.logistics.trains.entity.BogeyStyle;
|
||||||
|
import com.simibubi.create.foundation.utility.Components;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
import com.tterrag.registrate.util.entry.BlockEntry;
|
||||||
|
|
||||||
|
import net.minecraft.core.particles.ParticleOptions;
|
||||||
|
import net.minecraft.core.particles.ParticleTypes;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
public class AllBogeyStyles {
|
||||||
|
public static final Map<ResourceLocation, BogeyStyle> BOGEY_STYLES = new HashMap<>();
|
||||||
|
public static final Map<ResourceLocation, Map<ResourceLocation, BogeyStyle>> CYCLE_GROUPS = new HashMap<>();
|
||||||
|
private static final Map<ResourceLocation, BogeyStyle> EMPTY_GROUP = ImmutableMap.of();
|
||||||
|
|
||||||
|
public static Map<ResourceLocation, BogeyStyle> getCycleGroup(ResourceLocation cycleGroup) {
|
||||||
|
return CYCLE_GROUPS.getOrDefault(cycleGroup, EMPTY_GROUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String STANDARD_CYCLE_GROUP = "standard";
|
||||||
|
|
||||||
|
public static final BogeyStyle STANDARD =
|
||||||
|
create("standard", STANDARD_CYCLE_GROUP).commonRenderer(CommonStandardBogeyRenderer::new)
|
||||||
|
.displayName(Components.translatable("create.bogey.style.standard"))
|
||||||
|
.size(BogeySizes.SMALL, SmallStandardBogeyRenderer::new, AllBlocks.SMALL_BOGEY)
|
||||||
|
.size(BogeySizes.LARGE, LargeStandardBogeyRenderer::new, AllBlocks.LARGE_BOGEY)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private static BogeyStyleBuilder create(String name, String cycleGroup) {
|
||||||
|
return create(Create.asResource(name), Create.asResource(cycleGroup));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BogeyStyleBuilder create(ResourceLocation name, ResourceLocation cycleGroup) {
|
||||||
|
return new BogeyStyleBuilder(name, cycleGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register() {}
|
||||||
|
|
||||||
|
public static class BogeyStyleBuilder {
|
||||||
|
protected final Map<BogeySizes.BogeySize, BogeyStyle.SizeData> sizes = new HashMap<>();
|
||||||
|
protected final ResourceLocation name;
|
||||||
|
protected final ResourceLocation cycleGroup;
|
||||||
|
|
||||||
|
protected Component displayName = Lang.translateDirect("bogey.style.invalid");
|
||||||
|
protected ResourceLocation soundType = AllSoundEvents.TRAIN2.getId();
|
||||||
|
protected CompoundTag defaultData = new CompoundTag();
|
||||||
|
protected ParticleOptions contactParticle = ParticleTypes.CRIT;
|
||||||
|
protected ParticleOptions smokeParticle = ParticleTypes.POOF;
|
||||||
|
protected Optional<Supplier<? extends CommonRenderer>> commonRenderer = Optional.empty();
|
||||||
|
|
||||||
|
public BogeyStyleBuilder(ResourceLocation name, ResourceLocation cycleGroup) {
|
||||||
|
this.name = name;
|
||||||
|
this.cycleGroup = cycleGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyStyleBuilder displayName(Component displayName) {
|
||||||
|
this.displayName = displayName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyStyleBuilder soundType(ResourceLocation soundType) {
|
||||||
|
this.soundType = soundType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyStyleBuilder defaultData(CompoundTag defaultData) {
|
||||||
|
this.defaultData = defaultData;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyStyleBuilder size(BogeySizes.BogeySize size, Supplier<? extends BogeyRenderer> renderer,
|
||||||
|
BlockEntry<? extends AbstractBogeyBlock<?>> blockEntry) {
|
||||||
|
this.size(size, renderer, blockEntry.getId());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyStyleBuilder size(BogeySizes.BogeySize size, Supplier<? extends BogeyRenderer> renderer,
|
||||||
|
ResourceLocation location) {
|
||||||
|
this.sizes.put(size, new BogeyStyle.SizeData(location, renderer, renderer.get()));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyStyleBuilder contactParticle(ParticleOptions contactParticle) {
|
||||||
|
this.contactParticle = contactParticle;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyStyleBuilder smokeParticle(ParticleOptions smokeParticle) {
|
||||||
|
this.smokeParticle = smokeParticle;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyStyleBuilder commonRenderer(Supplier<? extends CommonRenderer> commonRenderer) {
|
||||||
|
this.commonRenderer = Optional.of(commonRenderer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyStyle build() {
|
||||||
|
BogeyStyle entry =
|
||||||
|
new BogeyStyle(name, cycleGroup, displayName, soundType, contactParticle, smokeParticle, defaultData, sizes, commonRenderer);
|
||||||
|
BOGEY_STYLES.put(name, entry);
|
||||||
|
CYCLE_GROUPS.computeIfAbsent(cycleGroup, l -> new HashMap<>()).put(name, entry);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -228,14 +228,16 @@ public class AllItems {
|
||||||
// wrapped by COPPER_BACKTANK for block placement uses.
|
// wrapped by COPPER_BACKTANK for block placement uses.
|
||||||
// must be registered as of 1.18.2
|
// must be registered as of 1.18.2
|
||||||
public static final ItemEntry<BacktankBlockItem> COPPER_BACKTANK_PLACEABLE = REGISTRATE
|
public static final ItemEntry<BacktankBlockItem> COPPER_BACKTANK_PLACEABLE = REGISTRATE
|
||||||
.item("copper_backtank_placeable", p -> new BacktankBlockItem(AllBlocks.COPPER_BACKTANK.get(), AllItems.COPPER_BACKTANK::get, p))
|
.item("copper_backtank_placeable",
|
||||||
|
p -> new BacktankBlockItem(AllBlocks.COPPER_BACKTANK.get(), AllItems.COPPER_BACKTANK::get, p))
|
||||||
.model((c, p) -> p.withExistingParent(c.getName(), p.mcLoc("item/barrier")))
|
.model((c, p) -> p.withExistingParent(c.getName(), p.mcLoc("item/barrier")))
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
// wrapped by NETHERITE_BACKTANK for block placement uses.
|
// wrapped by NETHERITE_BACKTANK for block placement uses.
|
||||||
// must be registered as of 1.18.2
|
// must be registered as of 1.18.2
|
||||||
public static final ItemEntry<BacktankBlockItem> NETHERITE_BACKTANK_PLACEABLE = REGISTRATE
|
public static final ItemEntry<BacktankBlockItem> NETHERITE_BACKTANK_PLACEABLE = REGISTRATE
|
||||||
.item("netherite_backtank_placeable", p -> new BacktankBlockItem(AllBlocks.NETHERITE_BACKTANK.get(), AllItems.NETHERITE_BACKTANK::get, p))
|
.item("netherite_backtank_placeable",
|
||||||
|
p -> new BacktankBlockItem(AllBlocks.NETHERITE_BACKTANK.get(), AllItems.NETHERITE_BACKTANK::get, p))
|
||||||
.model((c, p) -> p.withExistingParent(c.getName(), p.mcLoc("item/barrier")))
|
.model((c, p) -> p.withExistingParent(c.getName(), p.mcLoc("item/barrier")))
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
|
@ -248,6 +250,7 @@ public class AllItems {
|
||||||
COPPER_BACKTANK_PLACEABLE))
|
COPPER_BACKTANK_PLACEABLE))
|
||||||
.model(AssetLookup.customGenericItemModel("_", "item"))
|
.model(AssetLookup.customGenericItemModel("_", "item"))
|
||||||
.tag(AllItemTags.PRESSURIZED_AIR_SOURCES.tag)
|
.tag(AllItemTags.PRESSURIZED_AIR_SOURCES.tag)
|
||||||
|
.tag(forgeItemTag("armors/chestplates"))
|
||||||
.register(),
|
.register(),
|
||||||
|
|
||||||
NETHERITE_BACKTANK = REGISTRATE
|
NETHERITE_BACKTANK = REGISTRATE
|
||||||
|
@ -257,6 +260,7 @@ public class AllItems {
|
||||||
.model(AssetLookup.customGenericItemModel("_", "item"))
|
.model(AssetLookup.customGenericItemModel("_", "item"))
|
||||||
.properties(p -> p.fireResistant())
|
.properties(p -> p.fireResistant())
|
||||||
.tag(AllItemTags.PRESSURIZED_AIR_SOURCES.tag)
|
.tag(AllItemTags.PRESSURIZED_AIR_SOURCES.tag)
|
||||||
|
.tag(forgeItemTag("armors/chestplates"))
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final ItemEntry<? extends DivingHelmetItem>
|
public static final ItemEntry<? extends DivingHelmetItem>
|
||||||
|
@ -265,12 +269,14 @@ public class AllItems {
|
||||||
REGISTRATE
|
REGISTRATE
|
||||||
.item("copper_diving_helmet",
|
.item("copper_diving_helmet",
|
||||||
p -> new DivingHelmetItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving")))
|
p -> new DivingHelmetItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving")))
|
||||||
|
.tag(forgeItemTag("armors/helmets"))
|
||||||
.register(),
|
.register(),
|
||||||
|
|
||||||
NETHERITE_DIVING_HELMET = REGISTRATE
|
NETHERITE_DIVING_HELMET = REGISTRATE
|
||||||
.item("netherite_diving_helmet",
|
.item("netherite_diving_helmet",
|
||||||
p -> new DivingHelmetItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving")))
|
p -> new DivingHelmetItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving")))
|
||||||
.properties(p -> p.fireResistant())
|
.properties(p -> p.fireResistant())
|
||||||
|
.tag(forgeItemTag("armors/helmets"))
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final ItemEntry<? extends DivingBootsItem>
|
public static final ItemEntry<? extends DivingBootsItem>
|
||||||
|
@ -279,12 +285,14 @@ public class AllItems {
|
||||||
REGISTRATE
|
REGISTRATE
|
||||||
.item("copper_diving_boots",
|
.item("copper_diving_boots",
|
||||||
p -> new DivingBootsItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving")))
|
p -> new DivingBootsItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving")))
|
||||||
|
.tag(forgeItemTag("armors/boots"))
|
||||||
.register(),
|
.register(),
|
||||||
|
|
||||||
NETHERITE_DIVING_BOOTS = REGISTRATE
|
NETHERITE_DIVING_BOOTS = REGISTRATE
|
||||||
.item("netherite_diving_boots",
|
.item("netherite_diving_boots",
|
||||||
p -> new DivingBootsItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving")))
|
p -> new DivingBootsItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving")))
|
||||||
.properties(p -> p.fireResistant())
|
.properties(p -> p.fireResistant())
|
||||||
|
.tag(forgeItemTag("armors/boots"))
|
||||||
.register();
|
.register();
|
||||||
|
|
||||||
public static final ItemEntry<SandPaperItem> SAND_PAPER = REGISTRATE.item("sand_paper", SandPaperItem::new)
|
public static final ItemEntry<SandPaperItem> SAND_PAPER = REGISTRATE.item("sand_paper", SandPaperItem::new)
|
||||||
|
|
|
@ -14,6 +14,7 @@ import net.minecraft.tags.BlockTags;
|
||||||
import net.minecraft.tags.FluidTags;
|
import net.minecraft.tags.FluidTags;
|
||||||
import net.minecraft.tags.ItemTags;
|
import net.minecraft.tags.ItemTags;
|
||||||
import net.minecraft.tags.TagKey;
|
import net.minecraft.tags.TagKey;
|
||||||
|
import net.minecraft.world.item.BlockItem;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
|
@ -80,6 +81,8 @@ public class AllTags {
|
||||||
SAFE_NBT,
|
SAFE_NBT,
|
||||||
SEATS,
|
SEATS,
|
||||||
TOOLBOXES,
|
TOOLBOXES,
|
||||||
|
TRACKS,
|
||||||
|
GIRDABLE_TRACKS,
|
||||||
TREE_ATTACHMENTS,
|
TREE_ATTACHMENTS,
|
||||||
VALVE_HANDLES,
|
VALVE_HANDLES,
|
||||||
WINDMILL_SAILS,
|
WINDMILL_SAILS,
|
||||||
|
@ -131,6 +134,10 @@ public class AllTags {
|
||||||
.is(tag);
|
.is(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean matches(ItemStack stack) {
|
||||||
|
return stack != null && stack.getItem() instanceof BlockItem blockItem && matches(blockItem.getBlock());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean matches(BlockState state) {
|
public boolean matches(BlockState state) {
|
||||||
return state.is(tag);
|
return state.is(tag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ package com.simibubi.create;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.trains.BogeySizes;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
@ -9,6 +11,7 @@ import com.google.gson.GsonBuilder;
|
||||||
import com.mojang.logging.LogUtils;
|
import com.mojang.logging.LogUtils;
|
||||||
import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour;
|
import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour;
|
||||||
import com.simibubi.create.compat.Mods;
|
import com.simibubi.create.compat.Mods;
|
||||||
|
import com.simibubi.create.compat.computercraft.ComputerCraftProxy;
|
||||||
import com.simibubi.create.compat.curios.Curios;
|
import com.simibubi.create.compat.curios.Curios;
|
||||||
import com.simibubi.create.content.contraptions.TorquePropagator;
|
import com.simibubi.create.content.contraptions.TorquePropagator;
|
||||||
import com.simibubi.create.content.contraptions.fluids.tank.BoilerHeaters;
|
import com.simibubi.create.content.contraptions.fluids.tank.BoilerHeaters;
|
||||||
|
@ -125,6 +128,8 @@ public class Create {
|
||||||
AllFeatures.register(modEventBus);
|
AllFeatures.register(modEventBus);
|
||||||
AllPlacementModifiers.register(modEventBus);
|
AllPlacementModifiers.register(modEventBus);
|
||||||
BuiltinRegistration.register(modEventBus);
|
BuiltinRegistration.register(modEventBus);
|
||||||
|
BogeySizes.init();
|
||||||
|
AllBogeyStyles.register();
|
||||||
|
|
||||||
AllConfigs.register(modLoadingContext);
|
AllConfigs.register(modLoadingContext);
|
||||||
|
|
||||||
|
@ -134,6 +139,7 @@ public class Create {
|
||||||
ContraptionMovementSetting.registerDefaults();
|
ContraptionMovementSetting.registerDefaults();
|
||||||
AllArmInteractionPointTypes.register();
|
AllArmInteractionPointTypes.register();
|
||||||
BlockSpoutingBehaviour.registerDefaults();
|
BlockSpoutingBehaviour.registerDefaults();
|
||||||
|
ComputerCraftProxy.register();
|
||||||
|
|
||||||
ForgeMod.enableMilkFluid();
|
ForgeMod.enableMilkFluid();
|
||||||
CopperRegistries.inject();
|
CopperRegistries.inject();
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.simibubi.create.api.event;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
|
|
||||||
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
|
|
||||||
|
public class TrackGraphMergeEvent extends Event{
|
||||||
|
private TrackGraph mergedInto, mergedFrom;
|
||||||
|
|
||||||
|
public TrackGraphMergeEvent(TrackGraph from, TrackGraph into) {
|
||||||
|
mergedInto = into;
|
||||||
|
mergedFrom = from;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackGraph getGraphMergedInto() {
|
||||||
|
return mergedInto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackGraph getGraphMergedFrom() {
|
||||||
|
return mergedFrom;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,10 @@ import java.util.function.Supplier;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraftforge.fml.ModList;
|
import net.minecraftforge.fml.ModList;
|
||||||
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For compatibility with and without another mod present, we have to define load conditions of the specific code
|
* For compatibility with and without another mod present, we have to define load conditions of the specific code
|
||||||
|
@ -14,6 +17,8 @@ public enum Mods {
|
||||||
DYNAMICTREES,
|
DYNAMICTREES,
|
||||||
TCONSTRUCT,
|
TCONSTRUCT,
|
||||||
CURIOS,
|
CURIOS,
|
||||||
|
|
||||||
|
COMPUTERCRAFT,
|
||||||
STORAGEDRAWERS,
|
STORAGEDRAWERS,
|
||||||
XLPACKETS;
|
XLPACKETS;
|
||||||
|
|
||||||
|
@ -51,4 +56,8 @@ public enum Mods {
|
||||||
toExecute.get().run();
|
toExecute.get().run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Block getBlock(String id) {
|
||||||
|
return ForgeRegistries.BLOCKS.getValue(new ResourceLocation(asId(), id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.simibubi.create.compat.computercraft;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||||
|
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||||
|
import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
|
||||||
|
public class AbstractComputerBehaviour extends BlockEntityBehaviour {
|
||||||
|
|
||||||
|
public static final BehaviourType<AbstractComputerBehaviour> TYPE = new BehaviourType<>();
|
||||||
|
|
||||||
|
boolean hasAttachedComputer;
|
||||||
|
|
||||||
|
public AbstractComputerBehaviour(SmartBlockEntity te) {
|
||||||
|
super(te);
|
||||||
|
this.hasAttachedComputer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(CompoundTag nbt, boolean clientPacket) {
|
||||||
|
hasAttachedComputer = nbt.getBoolean("HasAttachedComputer");
|
||||||
|
super.read(nbt, clientPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(CompoundTag nbt, boolean clientPacket) {
|
||||||
|
nbt.putBoolean("HasAttachedComputer", hasAttachedComputer);
|
||||||
|
super.write(nbt, clientPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> boolean isPeripheralCap(Capability<T> cap) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> LazyOptional<T> getPeripheralCapability() {
|
||||||
|
return LazyOptional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePeripheral() {}
|
||||||
|
|
||||||
|
public void setHasAttachedComputer(boolean hasAttachedComputer) {
|
||||||
|
this.hasAttachedComputer = hasAttachedComputer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasAttachedComputer() {
|
||||||
|
return hasAttachedComputer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BehaviourType<?> getType() {
|
||||||
|
return TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.simibubi.create.compat.computercraft;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||||
|
import com.simibubi.create.foundation.blockEntity.SyncedBlockEntity;
|
||||||
|
import com.simibubi.create.foundation.networking.BlockEntityDataPacket;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
|
public class AttachedComputerPacket extends BlockEntityDataPacket<SyncedBlockEntity> {
|
||||||
|
|
||||||
|
private final boolean hasAttachedComputer;
|
||||||
|
|
||||||
|
public AttachedComputerPacket(BlockPos tilePos, boolean hasAttachedComputer) {
|
||||||
|
super(tilePos);
|
||||||
|
this.hasAttachedComputer = hasAttachedComputer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttachedComputerPacket(FriendlyByteBuf buffer) {
|
||||||
|
super(buffer);
|
||||||
|
this.hasAttachedComputer = buffer.readBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeData(FriendlyByteBuf buffer) {
|
||||||
|
buffer.writeBoolean(hasAttachedComputer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handlePacket(SyncedBlockEntity tile) {
|
||||||
|
if (tile instanceof SmartBlockEntity smartTile) {
|
||||||
|
smartTile.getBehaviour(AbstractComputerBehaviour.TYPE)
|
||||||
|
.setHasAttachedComputer(hasAttachedComputer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.simibubi.create.compat.computercraft;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import com.simibubi.create.compat.Mods;
|
||||||
|
import com.simibubi.create.compat.computercraft.implementation.ComputerBehaviour;
|
||||||
|
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||||
|
|
||||||
|
public class ComputerCraftProxy {
|
||||||
|
|
||||||
|
public static void register() {
|
||||||
|
fallbackFactory = FallbackComputerBehaviour::new;
|
||||||
|
Mods.COMPUTERCRAFT.executeIfInstalled(() -> ComputerCraftProxy::registerWithDependency);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void registerWithDependency() {
|
||||||
|
/* Comment if computercraft.implementation is not in the source set */
|
||||||
|
computerFactory = ComputerBehaviour::new;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Function<SmartBlockEntity, ? extends AbstractComputerBehaviour> fallbackFactory;
|
||||||
|
private static Function<SmartBlockEntity, ? extends AbstractComputerBehaviour> computerFactory;
|
||||||
|
|
||||||
|
public static AbstractComputerBehaviour behaviour(SmartBlockEntity sbe) {
|
||||||
|
if (computerFactory == null)
|
||||||
|
return fallbackFactory.apply(sbe);
|
||||||
|
return computerFactory.apply(sbe);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
package com.simibubi.create.compat.computercraft;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.simibubi.create.compat.Mods;
|
||||||
|
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
|
||||||
|
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||||
|
import com.simibubi.create.foundation.gui.AllIcons;
|
||||||
|
import com.simibubi.create.foundation.gui.element.GuiGameElement;
|
||||||
|
import com.simibubi.create.foundation.gui.widget.AbstractSimiWidget;
|
||||||
|
import com.simibubi.create.foundation.gui.widget.ElementWidget;
|
||||||
|
import com.simibubi.create.foundation.gui.widget.IconButton;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
public class ComputerScreen extends AbstractSimiScreen {
|
||||||
|
|
||||||
|
private final AllGuiTextures background = AllGuiTextures.COMPUTER;
|
||||||
|
|
||||||
|
private final Supplier<Component> displayTitle;
|
||||||
|
private final RenderWindowFunction additional;
|
||||||
|
private final Screen previousScreen;
|
||||||
|
private final Supplier<Boolean> hasAttachedComputer;
|
||||||
|
|
||||||
|
private AbstractSimiWidget computerWidget;
|
||||||
|
private IconButton confirmButton;
|
||||||
|
|
||||||
|
public ComputerScreen(Component title, @Nullable RenderWindowFunction additional, Screen previousScreen, Supplier<Boolean> hasAttachedComputer) {
|
||||||
|
this(title, () -> title, additional, previousScreen, hasAttachedComputer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComputerScreen(Component title, Supplier<Component> displayTitle, @Nullable RenderWindowFunction additional, Screen previousScreen, Supplier<Boolean> hasAttachedComputer) {
|
||||||
|
super(title);
|
||||||
|
this.displayTitle = displayTitle;
|
||||||
|
this.additional = additional;
|
||||||
|
this.previousScreen = previousScreen;
|
||||||
|
this.hasAttachedComputer = hasAttachedComputer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
if (!hasAttachedComputer.get())
|
||||||
|
minecraft.setScreen(previousScreen);
|
||||||
|
|
||||||
|
super.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
setWindowSize(background.width, background.height);
|
||||||
|
super.init();
|
||||||
|
|
||||||
|
int x = guiLeft;
|
||||||
|
int y = guiTop;
|
||||||
|
|
||||||
|
Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> {
|
||||||
|
computerWidget = new ElementWidget(x + 33, y + 38)
|
||||||
|
.showingElement(GuiGameElement.of(Mods.COMPUTERCRAFT.getBlock("computer_advanced")));
|
||||||
|
computerWidget.getToolTip().add(Lang.translate("gui.attached_computer.hint").component());
|
||||||
|
addRenderableWidget(computerWidget);
|
||||||
|
});
|
||||||
|
|
||||||
|
confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM);
|
||||||
|
confirmButton.withCallback(this::onClose);
|
||||||
|
addRenderableWidget(confirmButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
|
int x = guiLeft;
|
||||||
|
int y = guiTop;
|
||||||
|
|
||||||
|
background.render(ms, x, y, this);
|
||||||
|
|
||||||
|
font.draw(ms, displayTitle.get(), x + background.width / 2.0F - font.width(displayTitle.get()) / 2.0F, y + 4, 0x442000);
|
||||||
|
font.drawWordWrap(Lang.translate("gui.attached_computer.controlled").component(), x + 55, y + 32, 111, 0x7A7A7A);
|
||||||
|
|
||||||
|
if (additional != null)
|
||||||
|
additional.render(ms, mouseX, mouseY, partialTicks, x, y, background);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface RenderWindowFunction {
|
||||||
|
|
||||||
|
void render(PoseStack ms, int mouseX, int mouseY, float partialTicks, int guiLeft, int guiTop, AllGuiTextures background);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.simibubi.create.compat.computercraft;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||||
|
|
||||||
|
public class FallbackComputerBehaviour extends AbstractComputerBehaviour {
|
||||||
|
|
||||||
|
public FallbackComputerBehaviour(SmartBlockEntity te) {
|
||||||
|
super(te);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasAttachedComputer() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.simibubi.create.compat.computercraft.implementation;
|
||||||
|
|
||||||
|
import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour;
|
||||||
|
import com.simibubi.create.compat.computercraft.implementation.peripherals.DisplayLinkPeripheral;
|
||||||
|
import com.simibubi.create.compat.computercraft.implementation.peripherals.SequencedGearshiftPeripheral;
|
||||||
|
import com.simibubi.create.compat.computercraft.implementation.peripherals.SpeedControllerPeripheral;
|
||||||
|
import com.simibubi.create.compat.computercraft.implementation.peripherals.SpeedGaugePeripheral;
|
||||||
|
import com.simibubi.create.compat.computercraft.implementation.peripherals.StationPeripheral;
|
||||||
|
import com.simibubi.create.compat.computercraft.implementation.peripherals.StressGaugePeripheral;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlockEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencedGearshiftBlockEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.gauge.SpeedGaugeBlockEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.gauge.StressGaugeBlockEntity;
|
||||||
|
import com.simibubi.create.content.logistics.block.display.DisplayLinkBlockEntity;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlockEntity;
|
||||||
|
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||||
|
import net.minecraftforge.common.capabilities.CapabilityToken;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
import net.minecraftforge.common.util.NonNullSupplier;
|
||||||
|
|
||||||
|
public class ComputerBehaviour extends AbstractComputerBehaviour {
|
||||||
|
|
||||||
|
protected static final Capability<IPeripheral> PERIPHERAL_CAPABILITY =
|
||||||
|
CapabilityManager.get(new CapabilityToken<>() {
|
||||||
|
});
|
||||||
|
LazyOptional<IPeripheral> peripheral;
|
||||||
|
NonNullSupplier<IPeripheral> peripheralSupplier;
|
||||||
|
|
||||||
|
public ComputerBehaviour(SmartBlockEntity te) {
|
||||||
|
super(te);
|
||||||
|
this.peripheralSupplier = getPeripheralFor(te);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NonNullSupplier<IPeripheral> getPeripheralFor(SmartBlockEntity te) {
|
||||||
|
if (te instanceof SpeedControllerBlockEntity scte)
|
||||||
|
return () -> new SpeedControllerPeripheral(scte, scte.targetSpeed);
|
||||||
|
if (te instanceof DisplayLinkBlockEntity dlte)
|
||||||
|
return () -> new DisplayLinkPeripheral(dlte);
|
||||||
|
if (te instanceof SequencedGearshiftBlockEntity sgte)
|
||||||
|
return () -> new SequencedGearshiftPeripheral(sgte);
|
||||||
|
if (te instanceof SpeedGaugeBlockEntity sgte)
|
||||||
|
return () -> new SpeedGaugePeripheral(sgte);
|
||||||
|
if (te instanceof StressGaugeBlockEntity sgte)
|
||||||
|
return () -> new StressGaugePeripheral(sgte);
|
||||||
|
if (te instanceof StationBlockEntity ste)
|
||||||
|
return () -> new StationPeripheral(ste);
|
||||||
|
|
||||||
|
throw new IllegalArgumentException("No peripheral available for " + te.getType()
|
||||||
|
.getRegistryName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> boolean isPeripheralCap(Capability<T> cap) {
|
||||||
|
return cap == PERIPHERAL_CAPABILITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> LazyOptional<T> getPeripheralCapability() {
|
||||||
|
if (peripheral == null || !peripheral.isPresent())
|
||||||
|
peripheral = LazyOptional.of(peripheralSupplier);
|
||||||
|
return peripheral.cast();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removePeripheral() {
|
||||||
|
if (peripheral != null)
|
||||||
|
peripheral.invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,172 @@
|
||||||
|
package com.simibubi.create.compat.computercraft.implementation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
|
import dan200.computercraft.api.lua.LuaTable;
|
||||||
|
import dan200.computercraft.api.lua.LuaValues;
|
||||||
|
|
||||||
|
public class CreateLuaTable implements LuaTable<Object, Object> {
|
||||||
|
|
||||||
|
private final Map<Object, Object> map;
|
||||||
|
|
||||||
|
public CreateLuaTable() {
|
||||||
|
this.map = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateLuaTable(Map<?, ?> map) {
|
||||||
|
this.map = new HashMap<>(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getBoolean(String key) throws LuaException {
|
||||||
|
Object value = get(key);
|
||||||
|
|
||||||
|
if (!(value instanceof Boolean))
|
||||||
|
throw LuaValues.badField(key, "boolean", LuaValues.getType(value));
|
||||||
|
|
||||||
|
return (Boolean) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getString(String key) throws LuaException {
|
||||||
|
Object value = get(key);
|
||||||
|
|
||||||
|
if (!(value instanceof String))
|
||||||
|
throw LuaValues.badField(key, "string", LuaValues.getType(value));
|
||||||
|
|
||||||
|
return (String) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateLuaTable getTable(String key) throws LuaException {
|
||||||
|
Object value = get(key);
|
||||||
|
|
||||||
|
if (!(value instanceof Map<?, ?>))
|
||||||
|
throw LuaValues.badField(key, "table", LuaValues.getType(value));
|
||||||
|
|
||||||
|
return new CreateLuaTable((Map<?, ?>) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Boolean> getOptBoolean(String key) throws LuaException {
|
||||||
|
Object value = get(key);
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return Optional.empty();
|
||||||
|
|
||||||
|
if (!(value instanceof Boolean))
|
||||||
|
throw LuaValues.badField(key, "boolean", LuaValues.getType(value));
|
||||||
|
|
||||||
|
return Optional.of((Boolean) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> stringKeySet() throws LuaException {
|
||||||
|
Set<String> stringSet = new HashSet<>();
|
||||||
|
|
||||||
|
for (Object key : keySet()) {
|
||||||
|
if (!(key instanceof String))
|
||||||
|
throw new LuaException("key " + key + " is not string (got " + LuaValues.getType(key) + ")");
|
||||||
|
|
||||||
|
stringSet.add((String) key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableSet(stringSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<CreateLuaTable> tableValues() throws LuaException {
|
||||||
|
List<CreateLuaTable> tables = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 1; i <= size(); i++) {
|
||||||
|
Object value = get((double) i);
|
||||||
|
|
||||||
|
if (!(value instanceof Map<?, ?>))
|
||||||
|
throw new LuaException("value " + value + " is not table (got " + LuaValues.getType(value) + ")");
|
||||||
|
|
||||||
|
tables.add(new CreateLuaTable((Map<?, ?>) value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableList(tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Object, Object> getMap() {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Object put(Object key, Object value) {
|
||||||
|
return map.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putBoolean(String key, boolean value) {
|
||||||
|
map.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putDouble(String key, double value) {
|
||||||
|
map.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putString(String key, String value) {
|
||||||
|
map.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putTable(String key, CreateLuaTable value) {
|
||||||
|
map.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putTable(int i, CreateLuaTable value) {
|
||||||
|
map.put(i, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return map.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(Object o) {
|
||||||
|
return map.containsKey(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsValue(Object o) {
|
||||||
|
return map.containsValue(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(Object o) {
|
||||||
|
return map.get(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Set<Object> keySet() {
|
||||||
|
return map.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Collection<Object> values() {
|
||||||
|
return map.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Set<Entry<Object, Object>> entrySet() {
|
||||||
|
return map.entrySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
package com.simibubi.create.compat.computercraft.implementation.peripherals;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.display.DisplayLinkBlockEntity;
|
||||||
|
import com.simibubi.create.content.logistics.block.display.DisplayLinkContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.StringTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
|
||||||
|
public class DisplayLinkPeripheral extends SyncedPeripheral<DisplayLinkBlockEntity> {
|
||||||
|
|
||||||
|
public static final String TAG_KEY = "ComputerSourceList";
|
||||||
|
private final AtomicInteger cursorX = new AtomicInteger();
|
||||||
|
private final AtomicInteger cursorY = new AtomicInteger();
|
||||||
|
|
||||||
|
public DisplayLinkPeripheral(DisplayLinkBlockEntity tile) {
|
||||||
|
super(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final void setCursorPos(int x, int y) {
|
||||||
|
cursorX.set(x - 1);
|
||||||
|
cursorY.set(y - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final Object[] getCursorPos() {
|
||||||
|
return new Object[] {cursorX.get() + 1, cursorY.get() + 1};
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public final Object[] getSize() {
|
||||||
|
DisplayTargetStats stats = tile.activeTarget.provideStats(new DisplayLinkContext(tile.getLevel(), tile));
|
||||||
|
return new Object[]{stats.maxRows(), stats.maxColumns()};
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final boolean isColor() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final boolean isColour() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final void write(String text) {
|
||||||
|
ListTag tag = tile.getSourceConfig().getList(TAG_KEY, Tag.TAG_STRING);
|
||||||
|
|
||||||
|
int x = cursorX.get();
|
||||||
|
int y = cursorY.get();
|
||||||
|
|
||||||
|
for (int i = tag.size(); i <= y; i++) {
|
||||||
|
tag.add(StringTag.valueOf(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder(tag.getString(y));
|
||||||
|
|
||||||
|
builder.append(" ".repeat(Math.max(0, x - builder.length())));
|
||||||
|
builder.replace(x, x + text.length(), text);
|
||||||
|
|
||||||
|
tag.set(y, StringTag.valueOf(builder.toString()));
|
||||||
|
|
||||||
|
synchronized (tile) {
|
||||||
|
tile.getSourceConfig().put(TAG_KEY, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
cursorX.set(x + text.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final void clearLine() {
|
||||||
|
ListTag tag = tile.getSourceConfig().getList(TAG_KEY, Tag.TAG_STRING);
|
||||||
|
|
||||||
|
if (tag.size() > cursorY.get())
|
||||||
|
tag.set(cursorY.get(), StringTag.valueOf(""));
|
||||||
|
|
||||||
|
synchronized (tile) {
|
||||||
|
tile.getSourceConfig().put(TAG_KEY, tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final void clear() {
|
||||||
|
synchronized (tile) {
|
||||||
|
tile.getSourceConfig().put(TAG_KEY, new ListTag());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public final void update() {
|
||||||
|
tile.tickSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "Create_DisplayLink";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.simibubi.create.compat.computercraft.implementation.peripherals;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.Instruction;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.InstructionSpeedModifiers;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencedGearshiftBlockEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencerInstructions;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.IArguments;
|
||||||
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
|
|
||||||
|
public class SequencedGearshiftPeripheral extends SyncedPeripheral<SequencedGearshiftBlockEntity> {
|
||||||
|
|
||||||
|
public SequencedGearshiftPeripheral(SequencedGearshiftBlockEntity tile) {
|
||||||
|
super(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public final void rotate(IArguments arguments) throws LuaException {
|
||||||
|
runInstruction(arguments, SequencerInstructions.TURN_ANGLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public final void move(IArguments arguments) throws LuaException {
|
||||||
|
runInstruction(arguments, SequencerInstructions.TURN_DISTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final boolean isRunning() {
|
||||||
|
return !this.tile.isIdle();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runInstruction(IArguments arguments, SequencerInstructions instructionType) throws LuaException {
|
||||||
|
int speedModifier = arguments.count() > 1 ? arguments.getInt(1) : 1;
|
||||||
|
this.tile.getInstructions().clear();
|
||||||
|
|
||||||
|
this.tile.getInstructions().add(new Instruction(
|
||||||
|
instructionType,
|
||||||
|
InstructionSpeedModifiers.getByModifier(speedModifier),
|
||||||
|
Math.abs(arguments.getInt(0))));
|
||||||
|
this.tile.getInstructions().add(new Instruction(SequencerInstructions.END));
|
||||||
|
|
||||||
|
this.tile.run(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "Create_SequencedGearshift";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.simibubi.create.compat.computercraft.implementation.peripherals;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlockEntity;
|
||||||
|
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollValueBehaviour;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
|
|
||||||
|
public class SpeedControllerPeripheral extends SyncedPeripheral<SpeedControllerBlockEntity> {
|
||||||
|
|
||||||
|
private final ScrollValueBehaviour targetSpeed;
|
||||||
|
|
||||||
|
public SpeedControllerPeripheral(SpeedControllerBlockEntity tile, ScrollValueBehaviour targetSpeed) {
|
||||||
|
super(tile);
|
||||||
|
this.targetSpeed = targetSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public final void setTargetSpeed(int speed) {
|
||||||
|
this.targetSpeed.setValue(speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final float getTargetSpeed() {
|
||||||
|
return this.targetSpeed.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "Create_RotationSpeedController";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.simibubi.create.compat.computercraft.implementation.peripherals;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.contraptions.relays.gauge.SpeedGaugeBlockEntity;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
|
|
||||||
|
public class SpeedGaugePeripheral extends SyncedPeripheral<SpeedGaugeBlockEntity> {
|
||||||
|
|
||||||
|
public SpeedGaugePeripheral(SpeedGaugeBlockEntity tile) {
|
||||||
|
super(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final float getSpeed() {
|
||||||
|
return this.tile.getSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "Create_Speedometer";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,269 @@
|
||||||
|
package com.simibubi.create.compat.computercraft.implementation.peripherals;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import com.simibubi.create.compat.computercraft.implementation.CreateLuaTable;
|
||||||
|
import com.simibubi.create.content.logistics.trains.entity.Train;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlockEntity;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.TrainEditPacket;
|
||||||
|
import com.simibubi.create.content.logistics.trains.management.schedule.Schedule;
|
||||||
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
|
import com.simibubi.create.foundation.utility.Components;
|
||||||
|
import com.simibubi.create.foundation.utility.StringHelper;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.IArguments;
|
||||||
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
|
import net.minecraft.nbt.ByteTag;
|
||||||
|
import net.minecraft.nbt.CollectionTag;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.DoubleTag;
|
||||||
|
import net.minecraft.nbt.IntTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.NumericTag;
|
||||||
|
import net.minecraft.nbt.StringTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraftforge.network.PacketDistributor;
|
||||||
|
|
||||||
|
public class StationPeripheral extends SyncedPeripheral<StationBlockEntity> {
|
||||||
|
|
||||||
|
public StationPeripheral(StationBlockEntity tile) {
|
||||||
|
super(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public final void assemble() throws LuaException {
|
||||||
|
if (!tile.isAssembling())
|
||||||
|
throw new LuaException("station must be in assembly mode");
|
||||||
|
|
||||||
|
tile.assemble(null);
|
||||||
|
|
||||||
|
if (tile.getStation() == null || tile.getStation().getPresentTrain() == null)
|
||||||
|
throw new LuaException("failed to assemble train");
|
||||||
|
|
||||||
|
if (!tile.exitAssemblyMode())
|
||||||
|
throw new LuaException("failed to exit assembly mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public final void disassemble() throws LuaException {
|
||||||
|
if (tile.isAssembling())
|
||||||
|
throw new LuaException("station must not be in assembly mode");
|
||||||
|
|
||||||
|
getTrainOrThrow();
|
||||||
|
|
||||||
|
if (!tile.enterAssemblyMode(null))
|
||||||
|
throw new LuaException("could not disassemble train");
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public final void setAssemblyMode(boolean assemblyMode) throws LuaException {
|
||||||
|
if (assemblyMode) {
|
||||||
|
if (!tile.enterAssemblyMode(null))
|
||||||
|
throw new LuaException("failed to enter assembly mode");
|
||||||
|
} else {
|
||||||
|
if (!tile.exitAssemblyMode())
|
||||||
|
throw new LuaException("failed to exit assembly mode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final boolean isInAssemblyMode() {
|
||||||
|
return tile.isAssembling();
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final String getStationName() throws LuaException {
|
||||||
|
GlobalStation station = tile.getStation();
|
||||||
|
if (station == null)
|
||||||
|
throw new LuaException("station is not connected to a track");
|
||||||
|
|
||||||
|
return station.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public final void setStationName(String name) throws LuaException {
|
||||||
|
if (!tile.updateName(name))
|
||||||
|
throw new LuaException("could not set station name");
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final boolean isTrainPresent() throws LuaException {
|
||||||
|
GlobalStation station = tile.getStation();
|
||||||
|
if (station == null)
|
||||||
|
throw new LuaException("station is not connected to a track");
|
||||||
|
|
||||||
|
return station.getPresentTrain() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final boolean isTrainImminent() throws LuaException {
|
||||||
|
GlobalStation station = tile.getStation();
|
||||||
|
if (station == null)
|
||||||
|
throw new LuaException("station is not connected to a track");
|
||||||
|
|
||||||
|
return station.getImminentTrain() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final boolean isTrainEnroute() throws LuaException {
|
||||||
|
GlobalStation station = tile.getStation();
|
||||||
|
if (station == null)
|
||||||
|
throw new LuaException("station is not connected to a track");
|
||||||
|
|
||||||
|
return station.getNearestTrain() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final String getTrainName() throws LuaException {
|
||||||
|
Train train = getTrainOrThrow();
|
||||||
|
return train.name.getString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public final void setTrainName(String name) throws LuaException {
|
||||||
|
Train train = getTrainOrThrow();
|
||||||
|
train.name = Components.literal(name);
|
||||||
|
AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new TrainEditPacket.TrainEditReturnPacket(train.id, name, train.icon.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final boolean hasSchedule() throws LuaException {
|
||||||
|
Train train = getTrainOrThrow();
|
||||||
|
return train.runtime.getSchedule() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final CreateLuaTable getSchedule() throws LuaException {
|
||||||
|
Train train = getTrainOrThrow();
|
||||||
|
|
||||||
|
Schedule schedule = train.runtime.getSchedule();
|
||||||
|
if (schedule == null)
|
||||||
|
throw new LuaException("train doesn't have a schedule");
|
||||||
|
|
||||||
|
return fromCompoundTag(schedule.write());
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public final void setSchedule(IArguments arguments) throws LuaException {
|
||||||
|
Train train = getTrainOrThrow();
|
||||||
|
Schedule schedule = Schedule.fromTag(toCompoundTag(new CreateLuaTable(arguments.getTable(0))));
|
||||||
|
boolean autoSchedule = train.runtime.getSchedule() == null || train.runtime.isAutoSchedule;
|
||||||
|
train.runtime.setSchedule(schedule, autoSchedule);
|
||||||
|
}
|
||||||
|
|
||||||
|
private @NotNull Train getTrainOrThrow() throws LuaException {
|
||||||
|
GlobalStation station = tile.getStation();
|
||||||
|
if (station == null)
|
||||||
|
throw new LuaException("station is not connected to a track");
|
||||||
|
|
||||||
|
Train train = station.getPresentTrain();
|
||||||
|
if (train == null)
|
||||||
|
throw new LuaException("there is no train present");
|
||||||
|
|
||||||
|
return train;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull CreateLuaTable fromCompoundTag(CompoundTag tag) throws LuaException {
|
||||||
|
return (CreateLuaTable) fromNBTTag(null, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull Object fromNBTTag(@Nullable String key, Tag tag) throws LuaException {
|
||||||
|
byte type = tag.getId();
|
||||||
|
|
||||||
|
if (type == Tag.TAG_BYTE && key != null && key.equals("Count"))
|
||||||
|
return ((NumericTag) tag).getAsByte();
|
||||||
|
else if (type == Tag.TAG_BYTE)
|
||||||
|
return ((NumericTag) tag).getAsByte() != 0;
|
||||||
|
else if (type == Tag.TAG_SHORT || type == Tag.TAG_INT || type == Tag.TAG_LONG)
|
||||||
|
return ((NumericTag) tag).getAsLong();
|
||||||
|
else if (type == Tag.TAG_FLOAT || type == Tag.TAG_DOUBLE)
|
||||||
|
return ((NumericTag) tag).getAsDouble();
|
||||||
|
else if (type == Tag.TAG_STRING)
|
||||||
|
return tag.getAsString();
|
||||||
|
else if (type == Tag.TAG_LIST || type == Tag.TAG_BYTE_ARRAY || type == Tag.TAG_INT_ARRAY || type == Tag.TAG_LONG_ARRAY) {
|
||||||
|
CreateLuaTable list = new CreateLuaTable();
|
||||||
|
CollectionTag<?> listTag = (CollectionTag<?>) tag;
|
||||||
|
|
||||||
|
for (int i = 0; i < listTag.size(); i++) {
|
||||||
|
list.put(i + 1, fromNBTTag(null, listTag.get(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
|
||||||
|
} else if (type == Tag.TAG_COMPOUND) {
|
||||||
|
CreateLuaTable table = new CreateLuaTable();
|
||||||
|
CompoundTag compoundTag = (CompoundTag) tag;
|
||||||
|
|
||||||
|
for (String compoundKey : compoundTag.getAllKeys()) {
|
||||||
|
table.put(
|
||||||
|
StringHelper.camelCaseToSnakeCase(compoundKey),
|
||||||
|
fromNBTTag(compoundKey, compoundTag.get(compoundKey))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new LuaException("unknown tag type " + tag.getType().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull CompoundTag toCompoundTag(CreateLuaTable table) throws LuaException {
|
||||||
|
return (CompoundTag) toNBTTag(null, table.getMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull Tag toNBTTag(@Nullable String key, Object value) throws LuaException {
|
||||||
|
if (value instanceof Boolean v)
|
||||||
|
return ByteTag.valueOf(v);
|
||||||
|
else if (value instanceof Byte || (key != null && key.equals("count")))
|
||||||
|
return ByteTag.valueOf(((Number) value).byteValue());
|
||||||
|
else if (value instanceof Number v) {
|
||||||
|
// If number is numerical integer
|
||||||
|
if (v.intValue() == v.doubleValue())
|
||||||
|
return IntTag.valueOf(v.intValue());
|
||||||
|
else
|
||||||
|
return DoubleTag.valueOf(v.doubleValue());
|
||||||
|
|
||||||
|
} else if (value instanceof String v)
|
||||||
|
return StringTag.valueOf(v);
|
||||||
|
else if (value instanceof Map<?, ?> v && v.containsKey(1.0)) { // List
|
||||||
|
ListTag list = new ListTag();
|
||||||
|
for (Object o : v.values()) {
|
||||||
|
list.add(toNBTTag(null, o));
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
|
||||||
|
} else if (value instanceof Map<?, ?> v) { // Table/Map
|
||||||
|
CompoundTag compound = new CompoundTag();
|
||||||
|
for (Object objectKey : v.keySet()) {
|
||||||
|
if (!(objectKey instanceof String compoundKey))
|
||||||
|
throw new LuaException("table key is not of type string");
|
||||||
|
|
||||||
|
compound.put(
|
||||||
|
// Items serialize their resource location as "id" and not as "Id".
|
||||||
|
// This check is needed to see if the 'i' should be left lowercase or not.
|
||||||
|
// Items store "count" in the same compound tag, so we can check for its presence to see if this is a serialized item
|
||||||
|
compoundKey.equals("id") && v.containsKey("count") ? "id" : StringHelper.snakeCaseToCamelCase(compoundKey),
|
||||||
|
toNBTTag(compoundKey, v.get(compoundKey))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return compound;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new LuaException("unknown object type " + value.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "Create_Station";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.simibubi.create.compat.computercraft.implementation.peripherals;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.contraptions.relays.gauge.StressGaugeBlockEntity;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
|
|
||||||
|
public class StressGaugePeripheral extends SyncedPeripheral<StressGaugeBlockEntity> {
|
||||||
|
|
||||||
|
public StressGaugePeripheral(StressGaugeBlockEntity tile) {
|
||||||
|
super(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final float getStress() {
|
||||||
|
return this.tile.getNetworkStress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public final float getStressCapacity() {
|
||||||
|
return this.tile.getNetworkCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "Create_Stressometer";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.simibubi.create.compat.computercraft.implementation.peripherals;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.compat.computercraft.AttachedComputerPacket;
|
||||||
|
import com.simibubi.create.compat.computercraft.implementation.ComputerBehaviour;
|
||||||
|
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||||
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
import net.minecraftforge.network.PacketDistributor;
|
||||||
|
|
||||||
|
public abstract class SyncedPeripheral<T extends SmartBlockEntity> implements IPeripheral {
|
||||||
|
|
||||||
|
protected final T tile;
|
||||||
|
private final AtomicInteger computers = new AtomicInteger();
|
||||||
|
|
||||||
|
public SyncedPeripheral(T tile) {
|
||||||
|
this.tile = tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attach(@NotNull IComputerAccess computer) {
|
||||||
|
computers.incrementAndGet();
|
||||||
|
updateTile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void detach(@NotNull IComputerAccess computer) {
|
||||||
|
computers.decrementAndGet();
|
||||||
|
updateTile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTile() {
|
||||||
|
boolean hasAttachedComputer = computers.get() > 0;
|
||||||
|
|
||||||
|
tile.getBehaviour(ComputerBehaviour.TYPE).setHasAttachedComputer(hasAttachedComputer);
|
||||||
|
AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new AttachedComputerPacket(tile.getBlockPos(), hasAttachedComputer));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable IPeripheral other) {
|
||||||
|
return this == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.MaterialManager;
|
import com.jozufozu.flywheel.api.MaterialManager;
|
||||||
import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld;
|
import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllTags;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
|
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
|
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
|
||||||
|
@ -62,7 +62,7 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour {
|
||||||
@Override
|
@Override
|
||||||
public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) {
|
public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) {
|
||||||
return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos)
|
return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos)
|
||||||
.isEmpty() && !AllBlocks.TRACK.has(state);
|
.isEmpty() && !AllTags.AllBlockTags.TRACKS.matches(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ package com.simibubi.create.content.contraptions.components.press;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
|
||||||
import com.simibubi.create.AllRecipeTypes;
|
import com.simibubi.create.AllRecipeTypes;
|
||||||
|
import com.simibubi.create.AllTags;
|
||||||
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCraftingRecipe;
|
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCraftingRecipe;
|
||||||
import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.Mode;
|
import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.Mode;
|
||||||
import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.PressingBehaviourSpecifics;
|
import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.PressingBehaviourSpecifics;
|
||||||
|
@ -68,7 +68,7 @@ public class MechanicalPressBlockEntity extends BasinOperatingBlockEntity implem
|
||||||
|
|
||||||
public void onItemPressed(ItemStack result) {
|
public void onItemPressed(ItemStack result) {
|
||||||
award(AllAdvancements.PRESS);
|
award(AllAdvancements.PRESS);
|
||||||
if (AllBlocks.TRACK.isIn(result))
|
if (AllTags.AllBlockTags.TRACKS.matches(result))
|
||||||
tracksCreated += result.getCount();
|
tracksCreated += result.getCount();
|
||||||
if (tracksCreated >= 1000) {
|
if (tracksCreated >= 1000) {
|
||||||
award(AllAdvancements.TRACK_CRAFTING);
|
award(AllAdvancements.TRACK_CRAFTING);
|
||||||
|
|
|
@ -29,7 +29,7 @@ import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock;
|
||||||
import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock;
|
import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock;
|
||||||
import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkBlock;
|
import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkBlock;
|
||||||
import com.simibubi.create.content.logistics.block.vault.ItemVaultBlock;
|
import com.simibubi.create.content.logistics.block.vault.ItemVaultBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.ITrackBlock;
|
import com.simibubi.create.content.logistics.trains.ITrackBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlock;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlock;
|
||||||
import com.simibubi.create.foundation.config.ContraptionMovementSetting;
|
import com.simibubi.create.foundation.config.ContraptionMovementSetting;
|
||||||
|
@ -338,7 +338,7 @@ public class BlockMovementChecks {
|
||||||
return direction == state.getValue(StickerBlock.FACING)
|
return direction == state.getValue(StickerBlock.FACING)
|
||||||
&& !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite());
|
&& !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite());
|
||||||
}
|
}
|
||||||
if (block instanceof IBogeyBlock bogey)
|
if (block instanceof AbstractBogeyBlock bogey)
|
||||||
return bogey.getStickySurfaces(world, pos, state)
|
return bogey.getStickySurfaces(world, pos, state)
|
||||||
.contains(direction);
|
.contains(direction);
|
||||||
if (block instanceof WhistleBlock)
|
if (block instanceof WhistleBlock)
|
||||||
|
|
|
@ -64,7 +64,7 @@ import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock;
|
||||||
import com.simibubi.create.content.logistics.block.inventories.CreativeCrateBlockEntity;
|
import com.simibubi.create.content.logistics.block.inventories.CreativeCrateBlockEntity;
|
||||||
import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock;
|
import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock;
|
||||||
import com.simibubi.create.content.logistics.block.vault.ItemVaultBlockEntity;
|
import com.simibubi.create.content.logistics.block.vault.ItemVaultBlockEntity;
|
||||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock;
|
||||||
import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer;
|
import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer;
|
||||||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
|
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
@ -347,7 +347,7 @@ public abstract class Contraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bogeys tend to have sticky sides
|
// Bogeys tend to have sticky sides
|
||||||
if (state.getBlock()instanceof IBogeyBlock bogey)
|
if (state.getBlock()instanceof AbstractBogeyBlock<?> bogey)
|
||||||
for (Direction d : bogey.getStickySurfaces(world, pos, state))
|
for (Direction d : bogey.getStickySurfaces(world, pos, state))
|
||||||
if (!visited.contains(pos.relative(d)))
|
if (!visited.contains(pos.relative(d)))
|
||||||
frontier.add(pos.relative(d));
|
frontier.add(pos.relative(d));
|
||||||
|
|
|
@ -202,6 +202,7 @@ public class GantryContraptionEntity extends AbstractContraptionEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
public void applyLocalTransforms(PoseStack matrixStack, float partialTicks) {}
|
public void applyLocalTransforms(PoseStack matrixStack, float partialTicks) {}
|
||||||
|
|
||||||
public void updateClientMotion() {
|
public void updateClientMotion() {
|
||||||
|
|
|
@ -42,7 +42,6 @@ public class WaterWheelInstance<T extends WaterWheelBlockEntity> extends CutoutR
|
||||||
return getRotatingMaterial().model(key, () -> {
|
return getRotatingMaterial().model(key, () -> {
|
||||||
BakedModel model = WaterWheelRenderer.generateModel(key);
|
BakedModel model = WaterWheelRenderer.generateModel(key);
|
||||||
BlockState state = key.state();
|
BlockState state = key.state();
|
||||||
// TODO waterwheels
|
|
||||||
Direction dir;
|
Direction dir;
|
||||||
if (key.large()) {
|
if (key.large()) {
|
||||||
dir = Direction.fromAxisAndDirection(state.getValue(LargeWaterWheelBlock.AXIS), AxisDirection.POSITIVE);
|
dir = Direction.fromAxisAndDirection(state.getValue(LargeWaterWheelBlock.AXIS), AxisDirection.POSITIVE);
|
||||||
|
|
|
@ -3,9 +3,7 @@ package com.simibubi.create.content.contraptions.components.waterwheel;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.core.PartialModel;
|
|
||||||
import com.jozufozu.flywheel.core.StitchedSprite;
|
import com.jozufozu.flywheel.core.StitchedSprite;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.simibubi.create.AllPartialModels;
|
import com.simibubi.create.AllPartialModels;
|
||||||
|
@ -32,6 +30,7 @@ import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraftforge.client.model.data.ModelData;
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
public class WaterWheelRenderer<T extends WaterWheelBlockEntity> extends KineticBlockEntityRenderer<T> {
|
public class WaterWheelRenderer<T extends WaterWheelBlockEntity> extends KineticBlockEntityRenderer<T> {
|
||||||
|
@ -41,6 +40,8 @@ public class WaterWheelRenderer<T extends WaterWheelBlockEntity> extends Kinetic
|
||||||
public static final StitchedSprite OAK_LOG_TEMPLATE = new StitchedSprite(new ResourceLocation("block/oak_log"));
|
public static final StitchedSprite OAK_LOG_TEMPLATE = new StitchedSprite(new ResourceLocation("block/oak_log"));
|
||||||
public static final StitchedSprite OAK_LOG_TOP_TEMPLATE = new StitchedSprite(new ResourceLocation("block/oak_log_top"));
|
public static final StitchedSprite OAK_LOG_TOP_TEMPLATE = new StitchedSprite(new ResourceLocation("block/oak_log_top"));
|
||||||
|
|
||||||
|
private static final String[] LOG_SUFFIXES = new String[] { "_log", "_stem" };
|
||||||
|
|
||||||
protected final boolean large;
|
protected final boolean large;
|
||||||
|
|
||||||
public WaterWheelRenderer(Context context, boolean large) {
|
public WaterWheelRenderer(Context context, boolean large) {
|
||||||
|
@ -60,9 +61,8 @@ public class WaterWheelRenderer<T extends WaterWheelBlockEntity> extends Kinetic
|
||||||
protected SuperByteBuffer getRotatedModel(T be, BlockState state) {
|
protected SuperByteBuffer getRotatedModel(T be, BlockState state) {
|
||||||
WaterWheelModelKey key = new WaterWheelModelKey(large, state, be.material);
|
WaterWheelModelKey key = new WaterWheelModelKey(large, state, be.material);
|
||||||
return CreateClient.BUFFER_CACHE.get(WATER_WHEEL, key, () -> {
|
return CreateClient.BUFFER_CACHE.get(WATER_WHEEL, key, () -> {
|
||||||
BakedModel model = WaterWheelRenderer.generateModel(key);
|
BakedModel model = generateModel(key);
|
||||||
BlockState state1 = key.state();
|
BlockState state1 = key.state();
|
||||||
// TODO waterwheels
|
|
||||||
Direction dir;
|
Direction dir;
|
||||||
if (key.large()) {
|
if (key.large()) {
|
||||||
dir = Direction.fromAxisAndDirection(state1.getValue(LargeWaterWheelBlock.AXIS), AxisDirection.POSITIVE);
|
dir = Direction.fromAxisAndDirection(state1.getValue(LargeWaterWheelBlock.AXIS), AxisDirection.POSITIVE);
|
||||||
|
@ -74,25 +74,24 @@ public class WaterWheelRenderer<T extends WaterWheelBlockEntity> extends Kinetic
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PartialModel getTemplateModel(boolean large, boolean extension) {
|
|
||||||
if (large) {
|
|
||||||
if (extension) {
|
|
||||||
return AllPartialModels.LARGE_WATER_WHEEL_EXTENSION;
|
|
||||||
} else {
|
|
||||||
return AllPartialModels.LARGE_WATER_WHEEL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return AllPartialModels.WATER_WHEEL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BakedModel generateModel(WaterWheelModelKey key) {
|
public static BakedModel generateModel(WaterWheelModelKey key) {
|
||||||
|
BakedModel template;
|
||||||
|
if (key.large()) {
|
||||||
boolean extension = key.state()
|
boolean extension = key.state()
|
||||||
.getOptionalValue(LargeWaterWheelBlock.EXTENSION)
|
.getValue(LargeWaterWheelBlock.EXTENSION);
|
||||||
.orElse(false);
|
if (extension) {
|
||||||
BakedModel template = getTemplateModel(key.large(), extension).get();
|
template = AllPartialModels.LARGE_WATER_WHEEL_EXTENSION.get();
|
||||||
|
} else {
|
||||||
|
template = AllPartialModels.LARGE_WATER_WHEEL.get();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
template = AllPartialModels.WATER_WHEEL.get();
|
||||||
|
}
|
||||||
|
|
||||||
BlockState planksBlockState = key.material();
|
return generateModel(template, key.material());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BakedModel generateModel(BakedModel template, BlockState planksBlockState) {
|
||||||
Block planksBlock = planksBlockState.getBlock();
|
Block planksBlock = planksBlockState.getBlock();
|
||||||
ResourceLocation id = RegisteredObjects.getKeyOrThrow(planksBlock);
|
ResourceLocation id = RegisteredObjects.getKeyOrThrow(planksBlock);
|
||||||
String path = id.getPath();
|
String path = id.getPath();
|
||||||
|
@ -104,7 +103,7 @@ public class WaterWheelRenderer<T extends WaterWheelBlockEntity> extends Kinetic
|
||||||
|
|
||||||
Map<TextureAtlasSprite, TextureAtlasSprite> map = new Reference2ReferenceOpenHashMap<>();
|
Map<TextureAtlasSprite, TextureAtlasSprite> map = new Reference2ReferenceOpenHashMap<>();
|
||||||
map.put(OAK_PLANKS_TEMPLATE.get(), getSpriteOnSide(planksBlockState, Direction.UP));
|
map.put(OAK_PLANKS_TEMPLATE.get(), getSpriteOnSide(planksBlockState, Direction.UP));
|
||||||
map.put(OAK_LOG_TEMPLATE.get(), getSpriteOnSide(logBlockState, Direction.NORTH));
|
map.put(OAK_LOG_TEMPLATE.get(), getSpriteOnSide(logBlockState, Direction.SOUTH));
|
||||||
map.put(OAK_LOG_TOP_TEMPLATE.get(), getSpriteOnSide(logBlockState, Direction.UP));
|
map.put(OAK_LOG_TOP_TEMPLATE.get(), getSpriteOnSide(logBlockState, Direction.UP));
|
||||||
|
|
||||||
return BakedModelHelper.generateModel(template, map::get);
|
return BakedModelHelper.generateModel(template, map::get);
|
||||||
|
@ -114,7 +113,7 @@ public class WaterWheelRenderer<T extends WaterWheelBlockEntity> extends Kinetic
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BlockState getLogBlockState(String namespace, String wood) {
|
private static BlockState getLogBlockState(String namespace, String wood) {
|
||||||
for (String suffix : new String[] { "_log", "_stem" }) {
|
for (String suffix : LOG_SUFFIXES) {
|
||||||
Optional<BlockState> state =
|
Optional<BlockState> state =
|
||||||
ForgeRegistries.BLOCKS.getHolder(new ResourceLocation(namespace, wood + suffix))
|
ForgeRegistries.BLOCKS.getHolder(new ResourceLocation(namespace, wood + suffix))
|
||||||
.map(Holder::value)
|
.map(Holder::value)
|
||||||
|
@ -125,18 +124,29 @@ public class WaterWheelRenderer<T extends WaterWheelBlockEntity> extends Kinetic
|
||||||
return Blocks.OAK_LOG.defaultBlockState();
|
return Blocks.OAK_LOG.defaultBlockState();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TextureAtlasSprite getSpriteOnSide(BlockState blockstate, Direction side) {
|
private static TextureAtlasSprite getSpriteOnSide(BlockState state, Direction side) {
|
||||||
BakedModel blockModel = Minecraft.getInstance()
|
BakedModel model = Minecraft.getInstance()
|
||||||
.getBlockRenderer()
|
.getBlockRenderer()
|
||||||
.getBlockModel(blockstate);
|
.getBlockModel(state);
|
||||||
if (blockModel == null)
|
if (model == null)
|
||||||
return null;
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
List<BakedQuad> quads = blockModel.getQuads(blockstate, side, RandomSource.create());
|
|
||||||
if (quads.isEmpty())
|
|
||||||
return null;
|
return null;
|
||||||
|
RandomSource random = RandomSource.create();
|
||||||
|
random.setSeed(42L);
|
||||||
|
List<BakedQuad> quads = model.getQuads(state, side, random, ModelData.EMPTY, null);
|
||||||
|
if (!quads.isEmpty()) {
|
||||||
return quads.get(0)
|
return quads.get(0)
|
||||||
.getSprite();
|
.getSprite();
|
||||||
}
|
}
|
||||||
|
random.setSeed(42L);
|
||||||
|
quads = model.getQuads(state, null, random, ModelData.EMPTY, null);
|
||||||
|
if (!quads.isEmpty()) {
|
||||||
|
for (BakedQuad quad : quads) {
|
||||||
|
if (quad.getDirection() == side) {
|
||||||
|
return quad.getSprite();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return model.getParticleIcon(ModelData.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import net.minecraft.tags.BlockTags;
|
||||||
import net.minecraft.tags.FluidTags;
|
import net.minecraft.tags.FluidTags;
|
||||||
import net.minecraft.world.effect.MobEffect;
|
import net.minecraft.world.effect.MobEffect;
|
||||||
import net.minecraft.world.effect.MobEffectInstance;
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
|
import net.minecraft.world.effect.MobEffects;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
@ -39,6 +40,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
import net.minecraft.world.level.material.Fluids;
|
import net.minecraft.world.level.material.Fluids;
|
||||||
import net.minecraft.world.phys.AABB;
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraftforge.common.ForgeConfig;
|
||||||
import net.minecraftforge.common.Tags;
|
import net.minecraftforge.common.Tags;
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
import net.minecraftforge.fluids.FluidStack;
|
import net.minecraftforge.fluids.FluidStack;
|
||||||
|
@ -54,6 +56,7 @@ public class OpenEndedPipe extends FlowSource {
|
||||||
registerEffectHandler(new MilkEffectHandler());
|
registerEffectHandler(new MilkEffectHandler());
|
||||||
registerEffectHandler(new WaterEffectHandler());
|
registerEffectHandler(new WaterEffectHandler());
|
||||||
registerEffectHandler(new LavaEffectHandler());
|
registerEffectHandler(new LavaEffectHandler());
|
||||||
|
registerEffectHandler(new TeaEffectHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Level world;
|
private Level world;
|
||||||
|
@ -443,4 +446,23 @@ public class OpenEndedPipe extends FlowSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class TeaEffectHandler implements IEffectHandler {
|
||||||
|
@Override
|
||||||
|
public boolean canApplyEffects(OpenEndedPipe pipe, FluidStack fluid) {
|
||||||
|
return fluid.getFluid().isSame(AllFluids.TEA.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyEffects(OpenEndedPipe pipe, FluidStack fluid) {
|
||||||
|
Level world = pipe.getWorld();
|
||||||
|
if (world.getGameTime() % 5 != 0)
|
||||||
|
return;
|
||||||
|
List<LivingEntity> entities = world
|
||||||
|
.getEntitiesOfClass(LivingEntity.class, pipe.getAOE(), LivingEntity::isAffectedByPotions);
|
||||||
|
for (LivingEntity entity : entities) {
|
||||||
|
entity.addEffect(new MobEffectInstance(MobEffects.DIG_SPEED, 21, 0, false, false, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,4 +125,8 @@ public class HosePulleyFluidHandler implements IFluidHandler {
|
||||||
return internalTank.isFluidValid(tank, stack);
|
return internalTank.isFluidValid(tank, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SmartFluidTank getInternalTank() {
|
||||||
|
return internalTank;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,14 +38,24 @@ public class SpoutRenderer extends SafeBlockEntityRenderer<SpoutBlockEntity> {
|
||||||
.getValue(partialTicks);
|
.getValue(partialTicks);
|
||||||
|
|
||||||
if (!fluidStack.isEmpty() && level != 0) {
|
if (!fluidStack.isEmpty() && level != 0) {
|
||||||
|
boolean top = fluidStack.getFluid()
|
||||||
|
.getAttributes()
|
||||||
|
.isLighterThanAir();
|
||||||
|
|
||||||
level = Math.max(level, 0.175f);
|
level = Math.max(level, 0.175f);
|
||||||
float min = 2.5f / 16f;
|
float min = 2.5f / 16f;
|
||||||
float max = min + (11 / 16f);
|
float max = min + (11 / 16f);
|
||||||
float yOffset = (11 / 16f) * level;
|
float yOffset = (11 / 16f) * level;
|
||||||
|
|
||||||
ms.pushPose();
|
ms.pushPose();
|
||||||
ms.translate(0, yOffset, 0);
|
if (!top) ms.translate(0, yOffset, 0);
|
||||||
FluidRenderer.renderFluidBox(fluidStack, min, min - yOffset, min, max, min, max, buffer, ms, light,
|
else ms.translate(0, max - min, 0);
|
||||||
false);
|
|
||||||
|
FluidRenderer.renderFluidBox(fluidStack,
|
||||||
|
min, min - yOffset, min,
|
||||||
|
max, min, max,
|
||||||
|
buffer, ms, light, false);
|
||||||
|
|
||||||
ms.popPose();
|
ms.popPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ 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.components.structureMovement.ITransformableBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||||
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.relays.elementary.EncasedBlock;
|
||||||
|
@ -36,7 +38,9 @@ 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.Level;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Mirror;
|
||||||
import net.minecraft.world.level.block.PipeBlock;
|
import net.minecraft.world.level.block.PipeBlock;
|
||||||
|
import net.minecraft.world.level.block.Rotation;
|
||||||
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;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
@ -46,7 +50,8 @@ 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>, EncasedBlock {
|
public class EncasedPipeBlock extends Block
|
||||||
|
implements IWrenchable, ISpecialBlockItemRequirement, IBE<FluidPipeBlockEntity>, EncasedBlock, ITransformableBlock {
|
||||||
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;
|
||||||
|
|
||||||
private final Supplier<Block> casing;
|
private final Supplier<Block> casing;
|
||||||
|
@ -173,4 +178,20 @@ public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBloc
|
||||||
EncasedPipeBlock.transferSixWayProperties(state, defaultBlockState()));
|
EncasedPipeBlock.transferSixWayProperties(state, defaultBlockState()));
|
||||||
FluidTransportBehaviour.loadFlows(level, pos);
|
FluidTransportBehaviour.loadFlows(level, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState rotate(BlockState pState, Rotation pRotation) {
|
||||||
|
return FluidPipeBlockRotation.rotate(pState, pRotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState mirror(BlockState pState, Mirror pMirror) {
|
||||||
|
return FluidPipeBlockRotation.mirror(pState, pMirror);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState transform(BlockState state, StructureTransform transform) {
|
||||||
|
return FluidPipeBlockRotation.transform(state, transform);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
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.components.structureMovement.ITransformableBlock;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||||
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;
|
||||||
|
@ -36,7 +38,9 @@ import net.minecraft.world.level.BlockGetter;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Mirror;
|
||||||
import net.minecraft.world.level.block.PipeBlock;
|
import net.minecraft.world.level.block.PipeBlock;
|
||||||
|
import net.minecraft.world.level.block.Rotation;
|
||||||
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
|
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
@ -50,8 +54,8 @@ import net.minecraft.world.phys.Vec3;
|
||||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
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,
|
||||||
implements SimpleWaterloggedBlock, IWrenchableWithBracket, IBE<FluidPipeBlockEntity>, EncasableBlock {
|
IBE<FluidPipeBlockEntity>, EncasableBlock, ITransformableBlock {
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
@ -337,4 +341,20 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState rotate(BlockState pState, Rotation pRotation) {
|
||||||
|
return FluidPipeBlockRotation.rotate(pState, pRotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState mirror(BlockState pState, Mirror pMirror) {
|
||||||
|
return FluidPipeBlockRotation.mirror(pState, pMirror);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState transform(BlockState state, StructureTransform transform) {
|
||||||
|
return FluidPipeBlockRotation.transform(state, transform);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.simibubi.create.content.contraptions.fluids.pipes;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.level.block.Mirror;
|
||||||
|
import net.minecraft.world.level.block.PipeBlock;
|
||||||
|
import net.minecraft.world.level.block.Rotation;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||||
|
|
||||||
|
public class FluidPipeBlockRotation {
|
||||||
|
|
||||||
|
public static final Map<Direction, BooleanProperty> FACING_TO_PROPERTY_MAP = PipeBlock.PROPERTY_BY_DIRECTION;
|
||||||
|
|
||||||
|
public static BlockState rotate(BlockState state, Rotation rotation) {
|
||||||
|
BlockState rotated = state;
|
||||||
|
for (Direction direction : Iterate.horizontalDirections)
|
||||||
|
rotated = rotated.setValue(FACING_TO_PROPERTY_MAP.get(rotation.rotate(direction)),
|
||||||
|
state.getValue(FACING_TO_PROPERTY_MAP.get(direction)));
|
||||||
|
return rotated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockState mirror(BlockState state, Mirror mirror) {
|
||||||
|
BlockState mirrored = state;
|
||||||
|
for (Direction direction : Iterate.horizontalDirections)
|
||||||
|
mirrored = mirrored.setValue(FACING_TO_PROPERTY_MAP.get(mirror.mirror(direction)),
|
||||||
|
state.getValue(FACING_TO_PROPERTY_MAP.get(direction)));
|
||||||
|
return mirrored;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockState transform(BlockState state, StructureTransform transform) {
|
||||||
|
if (transform.mirror != null)
|
||||||
|
state = mirror(state, transform.mirror);
|
||||||
|
|
||||||
|
if (transform.rotationAxis == Direction.Axis.Y)
|
||||||
|
return rotate(state, transform.rotation);
|
||||||
|
|
||||||
|
BlockState rotated = state;
|
||||||
|
for (Direction direction : Iterate.directions)
|
||||||
|
rotated = rotated.setValue(FACING_TO_PROPERTY_MAP.get(transform.rotateFacing(direction)),
|
||||||
|
state.getValue(FACING_TO_PROPERTY_MAP.get(direction)));
|
||||||
|
return rotated;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -92,8 +92,7 @@ public class SmartFluidPipeBlock extends FaceAttachedHorizontalDirectionalBlock
|
||||||
boolean blockTypeChanged = state.getBlock() != newState.getBlock();
|
boolean blockTypeChanged = state.getBlock() != newState.getBlock();
|
||||||
if (blockTypeChanged && !world.isClientSide)
|
if (blockTypeChanged && !world.isClientSide)
|
||||||
FluidPropagator.propagateChangedPipe(world, pos, state);
|
FluidPropagator.propagateChangedPipe(world, pos, state);
|
||||||
if (state.hasBlockEntity() && (blockTypeChanged || !newState.hasBlockEntity()))
|
IBE.onRemove(state, world, pos, newState);
|
||||||
world.removeBlockEntity(pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -44,7 +44,8 @@ public class SequencedAssemblyRecipe implements Recipe<RecipeWrapper> {
|
||||||
protected List<SequencedRecipe<?>> sequence;
|
protected List<SequencedRecipe<?>> sequence;
|
||||||
protected int loops;
|
protected int loops;
|
||||||
protected ProcessingOutput transitionalItem;
|
protected ProcessingOutput transitionalItem;
|
||||||
protected List<ProcessingOutput> resultPool;
|
|
||||||
|
public final List<ProcessingOutput> resultPool;
|
||||||
|
|
||||||
public SequencedAssemblyRecipe(ResourceLocation recipeId, SequencedAssemblyRecipeSerializer serializer) {
|
public SequencedAssemblyRecipe(ResourceLocation recipeId, SequencedAssemblyRecipeSerializer serializer) {
|
||||||
this.id = recipeId;
|
this.id = recipeId;
|
||||||
|
|
|
@ -2,6 +2,11 @@ package com.simibubi.create.content.contraptions.relays.advanced;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour;
|
||||||
|
import com.simibubi.create.compat.computercraft.ComputerCraftProxy;
|
||||||
import com.simibubi.create.content.contraptions.RotationPropagator;
|
import com.simibubi.create.content.contraptions.RotationPropagator;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
|
import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.motor.KineticScrollValueBehaviour;
|
import com.simibubi.create.content.contraptions.components.motor.KineticScrollValueBehaviour;
|
||||||
|
@ -20,11 +25,14 @@ import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
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.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
|
||||||
public class SpeedControllerBlockEntity extends KineticBlockEntity {
|
public class SpeedControllerBlockEntity extends KineticBlockEntity {
|
||||||
|
|
||||||
public static final int DEFAULT_SPEED = 16;
|
public static final int DEFAULT_SPEED = 16;
|
||||||
protected ScrollValueBehaviour targetSpeed;
|
public ScrollValueBehaviour targetSpeed;
|
||||||
|
public AbstractComputerBehaviour computerBehaviour;
|
||||||
|
|
||||||
boolean hasBracket;
|
boolean hasBracket;
|
||||||
|
|
||||||
|
@ -50,6 +58,7 @@ public class SpeedControllerBlockEntity extends KineticBlockEntity {
|
||||||
targetSpeed.value = DEFAULT_SPEED;
|
targetSpeed.value = DEFAULT_SPEED;
|
||||||
targetSpeed.withCallback(i -> this.updateTargetRotation());
|
targetSpeed.withCallback(i -> this.updateTargetRotation());
|
||||||
behaviours.add(targetSpeed);
|
behaviours.add(targetSpeed);
|
||||||
|
behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this));
|
||||||
|
|
||||||
registerAwardables(behaviours, AllAdvancements.SPEED_CONTROLLER);
|
registerAwardables(behaviours, AllAdvancements.SPEED_CONTROLLER);
|
||||||
}
|
}
|
||||||
|
@ -125,6 +134,20 @@ public class SpeedControllerBlockEntity extends KineticBlockEntity {
|
||||||
.isHorizontal();
|
.isHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
|
||||||
|
if (computerBehaviour.isPeripheralCap(cap))
|
||||||
|
return computerBehaviour.getPeripheralCapability();
|
||||||
|
return super.getCapability(cap, side);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateCaps() {
|
||||||
|
super.invalidateCaps();
|
||||||
|
computerBehaviour.removePeripheral();
|
||||||
|
}
|
||||||
|
|
||||||
private class ControllerValueBoxTransform extends ValueBoxTransform.Sided {
|
private class ControllerValueBoxTransform extends ValueBoxTransform.Sided {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -35,6 +35,9 @@ public class ConfigureSequencedGearshiftPacket extends BlockEntityConfigurationP
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void applySettings(SequencedGearshiftBlockEntity be) {
|
protected void applySettings(SequencedGearshiftBlockEntity be) {
|
||||||
|
if (be.computerBehaviour.hasAttachedComputer())
|
||||||
|
return;
|
||||||
|
|
||||||
be.run(-1);
|
be.run(-1);
|
||||||
be.instructions = Instruction.deserializeAll(instructions);
|
be.instructions = Instruction.deserializeAll(instructions);
|
||||||
be.sendData();
|
be.sendData();
|
||||||
|
|
|
@ -19,8 +19,12 @@ public class Instruction {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Instruction(SequencerInstructions instruction, int value) {
|
public Instruction(SequencerInstructions instruction, int value) {
|
||||||
|
this(instruction, InstructionSpeedModifiers.FORWARD, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instruction(SequencerInstructions instruction, InstructionSpeedModifiers speedModifier, int value) {
|
||||||
this.instruction = instruction;
|
this.instruction = instruction;
|
||||||
speedModifier = InstructionSpeedModifiers.FORWARD;
|
this.speedModifier = speedModifier;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.simibubi.create.content.contraptions.relays.advanced.sequencer;
|
package com.simibubi.create.content.contraptions.relays.advanced.sequencer;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.simibubi.create.foundation.utility.Components;
|
import com.simibubi.create.foundation.utility.Components;
|
||||||
|
@ -36,4 +37,11 @@ public enum InstructionSpeedModifiers {
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static InstructionSpeedModifiers getByModifier(int modifier) {
|
||||||
|
return Arrays.stream(InstructionSpeedModifiers.values())
|
||||||
|
.filter(speedModifier -> speedModifier.value == modifier)
|
||||||
|
.findAny()
|
||||||
|
.orElse(InstructionSpeedModifiers.FORWARD);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
package com.simibubi.create.content.contraptions.relays.advanced.sequencer;
|
package com.simibubi.create.content.contraptions.relays.advanced.sequencer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour;
|
||||||
|
import com.simibubi.create.compat.computercraft.ComputerCraftProxy;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
|
import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
|
||||||
import com.simibubi.create.content.contraptions.relays.encased.SplitShaftBlockEntity;
|
import com.simibubi.create.content.contraptions.relays.encased.SplitShaftBlockEntity;
|
||||||
|
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -12,6 +20,8 @@ import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
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.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
|
||||||
public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
|
public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
|
||||||
|
|
||||||
|
@ -22,6 +32,8 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
|
||||||
int timer;
|
int timer;
|
||||||
boolean poweredPreviously;
|
boolean poweredPreviously;
|
||||||
|
|
||||||
|
public AbstractComputerBehaviour computerBehaviour;
|
||||||
|
|
||||||
public record SequenceContext(SequencerInstructions instruction, double relativeValue) {
|
public record SequenceContext(SequencerInstructions instruction, double relativeValue) {
|
||||||
|
|
||||||
public static SequenceContext fromGearshift(SequencerInstructions instruction, double kineticSpeed,
|
public static SequenceContext fromGearshift(SequencerInstructions instruction, double kineticSpeed,
|
||||||
|
@ -61,6 +73,12 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
|
||||||
poweredPreviously = false;
|
poweredPreviously = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||||
|
super.addBehaviours(behaviours);
|
||||||
|
behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
@ -103,6 +121,8 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onRedstoneUpdate(boolean isPowered, boolean isRunning) {
|
public void onRedstoneUpdate(boolean isPowered, boolean isRunning) {
|
||||||
|
if (computerBehaviour.hasAttachedComputer())
|
||||||
|
return;
|
||||||
if (!poweredPreviously && isPowered)
|
if (!poweredPreviously && isPowered)
|
||||||
risingFlank();
|
risingFlank();
|
||||||
poweredPreviously = isPowered;
|
poweredPreviously = isPowered;
|
||||||
|
@ -136,7 +156,7 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void run(int instructionIndex) {
|
public void run(int instructionIndex) {
|
||||||
Instruction instruction = getInstruction(instructionIndex);
|
Instruction instruction = getInstruction(instructionIndex);
|
||||||
if (instruction == null || instruction.instruction == SequencerInstructions.END) {
|
if (instruction == null || instruction.instruction == SequencerInstructions.END) {
|
||||||
if (getModifier() != 0)
|
if (getModifier() != 0)
|
||||||
|
@ -193,6 +213,20 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
|
||||||
super.read(compound, clientPacket);
|
super.read(compound, clientPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
|
||||||
|
if (computerBehaviour.isPeripheralCap(cap))
|
||||||
|
return computerBehaviour.getPeripheralCapability();
|
||||||
|
return super.getCapability(cap, side);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateCaps() {
|
||||||
|
super.invalidateCaps();
|
||||||
|
computerBehaviour.removePeripheral();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getRotationSpeedModifier(Direction face) {
|
public float getRotationSpeedModifier(Direction face) {
|
||||||
if (isVirtual())
|
if (isVirtual())
|
||||||
|
@ -208,4 +242,8 @@ public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity {
|
||||||
.getSpeedModifier();
|
.getSpeedModifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector<Instruction> getInstructions() {
|
||||||
|
return this.instructions;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import java.util.Vector;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.compat.computercraft.ComputerScreen;
|
||||||
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
|
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
|
||||||
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||||
import com.simibubi.create.foundation.gui.AllIcons;
|
import com.simibubi.create.foundation.gui.AllIcons;
|
||||||
|
@ -15,7 +16,6 @@ import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
import com.simibubi.create.foundation.utility.Components;
|
import com.simibubi.create.foundation.utility.Components;
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.nbt.ListTag;
|
import net.minecraft.nbt.ListTag;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
@ -25,22 +25,26 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen {
|
||||||
private final ItemStack renderedItem = AllBlocks.SEQUENCED_GEARSHIFT.asStack();
|
private final ItemStack renderedItem = AllBlocks.SEQUENCED_GEARSHIFT.asStack();
|
||||||
private final AllGuiTextures background = AllGuiTextures.SEQUENCER;
|
private final AllGuiTextures background = AllGuiTextures.SEQUENCER;
|
||||||
private IconButton confirmButton;
|
private IconButton confirmButton;
|
||||||
|
private SequencedGearshiftBlockEntity be;
|
||||||
|
|
||||||
private ListTag compareTag;
|
private ListTag compareTag;
|
||||||
private Vector<Instruction> instructions;
|
private Vector<Instruction> instructions;
|
||||||
private BlockPos pos;
|
|
||||||
|
|
||||||
private Vector<Vector<ScrollInput>> inputs;
|
private Vector<Vector<ScrollInput>> inputs;
|
||||||
|
|
||||||
public SequencedGearshiftScreen(SequencedGearshiftBlockEntity be) {
|
public SequencedGearshiftScreen(SequencedGearshiftBlockEntity be) {
|
||||||
super(Lang.translateDirect("gui.sequenced_gearshift.title"));
|
super(Lang.translateDirect("gui.sequenced_gearshift.title"));
|
||||||
this.instructions = be.instructions;
|
this.instructions = be.instructions;
|
||||||
this.pos = be.getBlockPos();
|
this.be = be;
|
||||||
compareTag = Instruction.serializeAll(instructions);
|
compareTag = Instruction.serializeAll(instructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
|
if (be.computerBehaviour.hasAttachedComputer())
|
||||||
|
minecraft.setScreen(
|
||||||
|
new ComputerScreen(title, this::renderAdditional, this, be.computerBehaviour::hasAttachedComputer));
|
||||||
|
|
||||||
setWindowSize(background.width, background.height);
|
setWindowSize(background.width, background.height);
|
||||||
setWindowOffset(-20, 0);
|
setWindowOffset(-20, 0);
|
||||||
super.init();
|
super.init();
|
||||||
|
@ -55,8 +59,7 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen {
|
||||||
for (int row = 0; row < instructions.size(); row++)
|
for (int row = 0; row < instructions.size(); row++)
|
||||||
initInputsOfRow(row, x, y);
|
initInputsOfRow(row, x, y);
|
||||||
|
|
||||||
confirmButton =
|
confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM);
|
||||||
new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM);
|
|
||||||
confirmButton.withCallback(() -> {
|
confirmButton.withCallback(() -> {
|
||||||
onClose();
|
onClose();
|
||||||
});
|
});
|
||||||
|
@ -127,6 +130,15 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen {
|
||||||
modifier.setState(instruction.speedModifier.ordinal());
|
modifier.setState(instruction.speedModifier.ordinal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
|
||||||
|
if (be.computerBehaviour.hasAttachedComputer())
|
||||||
|
minecraft.setScreen(
|
||||||
|
new ComputerScreen(title, this::renderAdditional, this, be.computerBehaviour::hasAttachedComputer));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
|
||||||
int x = guiLeft;
|
int x = guiLeft;
|
||||||
|
@ -134,6 +146,13 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen {
|
||||||
|
|
||||||
background.render(ms, x, y, this);
|
background.render(ms, x, y, this);
|
||||||
|
|
||||||
|
for (int row = 0; row < instructions.capacity(); row++) {
|
||||||
|
AllGuiTextures toDraw = AllGuiTextures.SEQUENCER_EMPTY;
|
||||||
|
int yOffset = toDraw.height * row;
|
||||||
|
|
||||||
|
toDraw.render(ms, x, y + 14 + yOffset, this);
|
||||||
|
}
|
||||||
|
|
||||||
for (int row = 0; row < instructions.capacity(); row++) {
|
for (int row = 0; row < instructions.capacity(); row++) {
|
||||||
AllGuiTextures toDraw = AllGuiTextures.SEQUENCER_EMPTY;
|
AllGuiTextures toDraw = AllGuiTextures.SEQUENCER_EMPTY;
|
||||||
int yOffset = toDraw.height * row;
|
int yOffset = toDraw.height * row;
|
||||||
|
@ -157,9 +176,13 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen {
|
||||||
}
|
}
|
||||||
|
|
||||||
font.draw(ms, title, x + (background.width - 8) / 2 - font.width(title) / 2, y + 4, 0x592424);
|
font.draw(ms, title, x + (background.width - 8) / 2 - font.width(title) / 2, y + 4, 0x592424);
|
||||||
|
renderAdditional(ms, mouseX, mouseY, partialTicks, x, y, background);
|
||||||
|
}
|
||||||
|
|
||||||
GuiGameElement.of(renderedItem)
|
private void renderAdditional(PoseStack ms, int mouseX, int mouseY, float partialTicks, int guiLeft, int guiTop,
|
||||||
.<GuiGameElement.GuiRenderBuilder>at(x + background.width + 6, y + background.height - 56, -200)
|
AllGuiTextures background) {
|
||||||
|
GuiGameElement.of(renderedItem).<GuiGameElement
|
||||||
|
.GuiRenderBuilder>at(guiLeft + background.width + 6, guiTop + background.height - 56, 100)
|
||||||
.scale(5)
|
.scale(5)
|
||||||
.render(ms);
|
.render(ms);
|
||||||
}
|
}
|
||||||
|
@ -172,7 +195,8 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen {
|
||||||
ListTag serialized = Instruction.serializeAll(instructions);
|
ListTag serialized = Instruction.serializeAll(instructions);
|
||||||
if (serialized.equals(compareTag))
|
if (serialized.equals(compareTag))
|
||||||
return;
|
return;
|
||||||
AllPackets.getChannel().sendToServer(new ConfigureSequencedGearshiftPacket(pos, serialized));
|
AllPackets.getChannel()
|
||||||
|
.sendToServer(new ConfigureSequencedGearshiftPacket(be.getBlockPos(), serialized));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -12,7 +12,7 @@ import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
public class GaugeBlockEntity extends KineticBlockEntity implements IHaveGoggleInformation {
|
public abstract class GaugeBlockEntity extends KineticBlockEntity implements IHaveGoggleInformation {
|
||||||
|
|
||||||
public float dialTarget;
|
public float dialTarget;
|
||||||
public float dialState;
|
public float dialState;
|
||||||
|
@ -52,4 +52,5 @@ public class GaugeBlockEntity extends KineticBlockEntity implements IHaveGoggleI
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,24 +2,41 @@ package com.simibubi.create.content.contraptions.relays.gauge;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour;
|
||||||
|
import com.simibubi.create.compat.computercraft.ComputerCraftProxy;
|
||||||
import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel;
|
import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel;
|
||||||
|
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
import com.simibubi.create.foundation.utility.Color;
|
import com.simibubi.create.foundation.utility.Color;
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
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.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
|
||||||
public class SpeedGaugeBlockEntity extends GaugeBlockEntity {
|
public class SpeedGaugeBlockEntity extends GaugeBlockEntity {
|
||||||
|
|
||||||
|
public AbstractComputerBehaviour computerBehaviour;
|
||||||
|
|
||||||
public SpeedGaugeBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
public SpeedGaugeBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||||
super(type, pos, state);
|
super(type, pos, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||||
|
super.addBehaviours(behaviours);
|
||||||
|
behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSpeedChanged(float prevSpeed) {
|
public void onSpeedChanged(float prevSpeed) {
|
||||||
super.onSpeedChanged(prevSpeed);
|
super.onSpeedChanged(prevSpeed);
|
||||||
|
@ -62,4 +79,19 @@ public class SpeedGaugeBlockEntity extends GaugeBlockEntity {
|
||||||
.forGoggles(tooltip);
|
.forGoggles(tooltip);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
|
||||||
|
if (computerBehaviour.isPeripheralCap(cap))
|
||||||
|
return computerBehaviour.getPeripheralCapability();
|
||||||
|
return super.getCapability(cap, side);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateCaps() {
|
||||||
|
super.invalidateCaps();
|
||||||
|
computerBehaviour.removePeripheral();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,11 @@ package com.simibubi.create.content.contraptions.relays.gauge;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour;
|
||||||
|
import com.simibubi.create.compat.computercraft.ComputerCraftProxy;
|
||||||
import com.simibubi.create.content.contraptions.base.IRotate.StressImpact;
|
import com.simibubi.create.content.contraptions.base.IRotate.StressImpact;
|
||||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||||
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
|
||||||
|
@ -13,14 +18,19 @@ import com.simibubi.create.foundation.utility.LangBuilder;
|
||||||
|
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
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.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
|
||||||
public class StressGaugeBlockEntity extends GaugeBlockEntity {
|
public class StressGaugeBlockEntity extends GaugeBlockEntity {
|
||||||
|
|
||||||
|
public AbstractComputerBehaviour computerBehaviour;
|
||||||
|
|
||||||
static BlockPos lastSent;
|
static BlockPos lastSent;
|
||||||
|
|
||||||
public StressGaugeBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
public StressGaugeBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||||
|
@ -30,6 +40,7 @@ public class StressGaugeBlockEntity extends GaugeBlockEntity {
|
||||||
@Override
|
@Override
|
||||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||||
super.addBehaviours(behaviours);
|
super.addBehaviours(behaviours);
|
||||||
|
behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this));
|
||||||
registerAwardables(behaviours, AllAdvancements.STRESSOMETER, AllAdvancements.STRESSOMETER_MAXED);
|
registerAwardables(behaviours, AllAdvancements.STRESSOMETER, AllAdvancements.STRESSOMETER_MAXED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,4 +152,18 @@ public class StressGaugeBlockEntity extends GaugeBlockEntity {
|
||||||
award(AllAdvancements.STRESSOMETER_MAXED);
|
award(AllAdvancements.STRESSOMETER_MAXED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
|
||||||
|
if (computerBehaviour.isPeripheralCap(cap))
|
||||||
|
return computerBehaviour.getPeripheralCapability();
|
||||||
|
return super.getCapability(cap, side);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateCaps() {
|
||||||
|
super.invalidateCaps();
|
||||||
|
computerBehaviour.removePeripheral();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -440,7 +440,7 @@ public class ClipboardScreen extends AbstractSimiScreen {
|
||||||
if (currentEntries.get(editingIndex).text.getString()
|
if (currentEntries.get(editingIndex).text.getString()
|
||||||
.isEmpty() && currentEntries.size() > 1) {
|
.isEmpty() && currentEntries.size() > 1) {
|
||||||
currentEntries.remove(editingIndex);
|
currentEntries.remove(editingIndex);
|
||||||
editingIndex -= 1;
|
editingIndex = Math.max(0, editingIndex - 1);
|
||||||
editContext.setCursorToEnd();
|
editContext.setCursorToEnd();
|
||||||
return true;
|
return true;
|
||||||
} else if (hasControlDown()) {
|
} else if (hasControlDown()) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import static net.minecraft.world.level.block.state.properties.BlockStatePropert
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.AllShapes;
|
import com.simibubi.create.AllShapes;
|
||||||
|
import com.simibubi.create.AllTags;
|
||||||
import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
|
import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
|
||||||
import com.simibubi.create.content.contraptions.fluids.pipes.BracketBlock;
|
import com.simibubi.create.content.contraptions.fluids.pipes.BracketBlock;
|
||||||
import com.simibubi.create.content.contraptions.relays.elementary.BracketedBlockEntityBehaviour;
|
import com.simibubi.create.content.contraptions.relays.elementary.BracketedBlockEntityBehaviour;
|
||||||
|
@ -223,7 +224,7 @@ public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenc
|
||||||
for (Direction d2 : Iterate.directionsInAxis(axis == Axis.X ? Axis.Z : Axis.X)) {
|
for (Direction d2 : Iterate.directionsInAxis(axis == Axis.X ? Axis.Z : Axis.X)) {
|
||||||
BlockState above = level.getBlockState(pos.above()
|
BlockState above = level.getBlockState(pos.above()
|
||||||
.relative(d2));
|
.relative(d2));
|
||||||
if (AllBlocks.TRACK.has(above)) {
|
if (AllTags.AllBlockTags.GIRDABLE_TRACKS.matches(above)) {
|
||||||
TrackShape shape = above.getValue(TrackBlock.SHAPE);
|
TrackShape shape = above.getValue(TrackBlock.SHAPE);
|
||||||
if (shape == (axis == Axis.X ? TrackShape.XO : TrackShape.ZO))
|
if (shape == (axis == Axis.X ? TrackShape.XO : TrackShape.ZO))
|
||||||
state = state.setValue(updateProperty, true);
|
state = state.setValue(updateProperty, true);
|
||||||
|
|
|
@ -9,7 +9,6 @@ import java.util.Optional;
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.simibubi.create.AllBlocks;
|
|
||||||
import com.simibubi.create.AllItems;
|
import com.simibubi.create.AllItems;
|
||||||
import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintCraftingInventory;
|
import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintCraftingInventory;
|
||||||
import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection;
|
import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection;
|
||||||
|
@ -106,7 +105,7 @@ public class BlueprintOverlayRenderer {
|
||||||
|
|
||||||
int tracks = info.requiredTracks;
|
int tracks = info.requiredTracks;
|
||||||
while (tracks > 0) {
|
while (tracks > 0) {
|
||||||
ingredients.add(Pair.of(AllBlocks.TRACK.asStack(Math.min(64, tracks)), info.hasRequiredTracks));
|
ingredients.add(Pair.of(new ItemStack(info.trackMaterial.getBlock(), Math.min(64, tracks)), info.hasRequiredTracks));
|
||||||
tracks -= 64;
|
tracks -= 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringB
|
||||||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.SidedFilteringBehaviour;
|
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.SidedFilteringBehaviour;
|
||||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.INamedIconOptions;
|
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.INamedIconOptions;
|
||||||
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
|
import com.simibubi.create.foundation.blockEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
|
||||||
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
import com.simibubi.create.foundation.gui.AllIcons;
|
import com.simibubi.create.foundation.gui.AllIcons;
|
||||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||||
import com.simibubi.create.foundation.utility.Components;
|
import com.simibubi.create.foundation.utility.Components;
|
||||||
|
@ -174,7 +175,7 @@ public class BrassTunnelBlockEntity extends BeltTunnelBlockEntity implements IHa
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (selectionMode.get() != SelectionMode.SYNCHRONIZE || syncedOutputActive) {
|
if (selectionMode.get() != SelectionMode.SYNCHRONIZE || syncedOutputActive) {
|
||||||
distributionProgress = 10;
|
distributionProgress = AllConfigs.server().logistics.brassTunnelTimer.get();
|
||||||
sendData();
|
sendData();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
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.minecraftforge.common.capabilities.Capability;
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
|
@ -33,4 +34,8 @@ public class DepotBlockEntity extends SmartBlockEntity {
|
||||||
return depotBehaviour.getItemCapability(cap, side);
|
return depotBehaviour.getItemCapability(cap, side);
|
||||||
return super.getCapability(cap, side);
|
return super.getCapability(cap, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ItemStack getHeldItem() {
|
||||||
|
return depotBehaviour.getHeldItemStack();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ import java.util.Map;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.compat.Mods;
|
||||||
|
import com.simibubi.create.content.logistics.block.display.source.ComputerDisplaySource;
|
||||||
import com.simibubi.create.content.logistics.block.display.source.DeathCounterDisplaySource;
|
import com.simibubi.create.content.logistics.block.display.source.DeathCounterDisplaySource;
|
||||||
import com.simibubi.create.content.logistics.block.display.source.DisplaySource;
|
import com.simibubi.create.content.logistics.block.display.source.DisplaySource;
|
||||||
import com.simibubi.create.content.logistics.block.display.source.EnchantPowerDisplaySource;
|
import com.simibubi.create.content.logistics.block.display.source.EnchantPowerDisplaySource;
|
||||||
|
@ -241,5 +243,14 @@ public class AllDisplayBehaviours {
|
||||||
assignBlockEntity(register(Create.asResource("scoreboard_display_source"), new ScoreboardDisplaySource()), BlockEntityType.COMMAND_BLOCK);
|
assignBlockEntity(register(Create.asResource("scoreboard_display_source"), new ScoreboardDisplaySource()), BlockEntityType.COMMAND_BLOCK);
|
||||||
assignBlockEntity(register(Create.asResource("enchant_power_display_source"), new EnchantPowerDisplaySource()), BlockEntityType.ENCHANTING_TABLE);
|
assignBlockEntity(register(Create.asResource("enchant_power_display_source"), new EnchantPowerDisplaySource()), BlockEntityType.ENCHANTING_TABLE);
|
||||||
assignBlock(register(Create.asResource("redstone_power_display_source"), new RedstonePowerDisplaySource()), Blocks.TARGET);
|
assignBlock(register(Create.asResource("redstone_power_display_source"), new RedstonePowerDisplaySource()), Blocks.TARGET);
|
||||||
|
|
||||||
|
Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> {
|
||||||
|
DisplayBehaviour computerDisplaySource = register(Create.asResource("computer_display_source"), new ComputerDisplaySource());
|
||||||
|
|
||||||
|
assignTile(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "wired_modem_full"));
|
||||||
|
assignTile(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_normal"));
|
||||||
|
assignTile(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_advanced"));
|
||||||
|
assignTile(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_command"));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,11 @@ package com.simibubi.create.content.logistics.block.display;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour;
|
||||||
|
import com.simibubi.create.compat.computercraft.ComputerCraftProxy;
|
||||||
import com.simibubi.create.content.logistics.block.display.source.DisplaySource;
|
import com.simibubi.create.content.logistics.block.display.source.DisplaySource;
|
||||||
import com.simibubi.create.content.logistics.block.display.target.DisplayTarget;
|
import com.simibubi.create.content.logistics.block.display.target.DisplayTarget;
|
||||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||||
|
@ -18,6 +23,8 @@ import net.minecraft.nbt.NbtUtils;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
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.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
|
||||||
public class DisplayLinkBlockEntity extends SmartBlockEntity {
|
public class DisplayLinkBlockEntity extends SmartBlockEntity {
|
||||||
|
|
||||||
|
@ -33,6 +40,7 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity {
|
||||||
private boolean sendPulse;
|
private boolean sendPulse;
|
||||||
|
|
||||||
public int refreshTicks;
|
public int refreshTicks;
|
||||||
|
public AbstractComputerBehaviour computerBehaviour;
|
||||||
|
|
||||||
public DisplayLinkBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
public DisplayLinkBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||||
super(type, pos, state);
|
super(type, pos, state);
|
||||||
|
@ -44,6 +52,12 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity {
|
||||||
glow.chase(0, 0.5f, Chaser.EXP);
|
glow.chase(0, 0.5f, Chaser.EXP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
||||||
|
behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this));
|
||||||
|
registerAwardables(behaviours, AllAdvancements.DISPLAY_LINK, AllAdvancements.DISPLAY_BOARD);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
@ -61,7 +75,7 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshTicks++;
|
refreshTicks++;
|
||||||
if (refreshTicks < activeSource.getPassiveRefreshTicks())
|
if (refreshTicks < activeSource.getPassiveRefreshTicks() || !activeSource.shouldPassiveReset())
|
||||||
return;
|
return;
|
||||||
tickSource();
|
tickSource();
|
||||||
}
|
}
|
||||||
|
@ -118,11 +132,6 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity {
|
||||||
award(AllAdvancements.DISPLAY_LINK);
|
award(AllAdvancements.DISPLAY_LINK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
|
|
||||||
registerAwardables(behaviours, AllAdvancements.DISPLAY_LINK, AllAdvancements.DISPLAY_BOARD);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSafe(CompoundTag tag) {
|
public void writeSafe(CompoundTag tag) {
|
||||||
super.writeSafe(tag);
|
super.writeSafe(tag);
|
||||||
|
@ -173,6 +182,21 @@ public class DisplayLinkBlockEntity extends SmartBlockEntity {
|
||||||
sourceConfig = data.copy();
|
sourceConfig = data.copy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
|
||||||
|
if (computerBehaviour.isPeripheralCap(cap))
|
||||||
|
return computerBehaviour.getPeripheralCapability();
|
||||||
|
|
||||||
|
return super.getCapability(cap, side);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateCaps() {
|
||||||
|
super.invalidateCaps();
|
||||||
|
computerBehaviour.removePeripheral();
|
||||||
|
}
|
||||||
|
|
||||||
public void target(BlockPos targetPosition) {
|
public void target(BlockPos targetPosition) {
|
||||||
this.targetOffset = targetPosition.subtract(worldPosition);
|
this.targetOffset = targetPosition.subtract(worldPosition);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.simibubi.create.content.logistics.block.display.source;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.display.DisplayLinkContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats;
|
||||||
|
import com.simibubi.create.foundation.utility.Components;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
|
||||||
|
public class ComputerDisplaySource extends DisplaySource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MutableComponent> provideText(DisplayLinkContext context, DisplayTargetStats stats) {
|
||||||
|
List<MutableComponent> components = new ArrayList<>();
|
||||||
|
ListTag tag = context.sourceConfig().getList("ComputerSourceList", Tag.TAG_STRING);
|
||||||
|
|
||||||
|
for (int i = 0; i < tag.size(); i++) {
|
||||||
|
components.add(Components.literal(tag.getString(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPassiveReset() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -49,6 +49,10 @@ public abstract class DisplaySource extends DisplayBehaviour {
|
||||||
return 100;
|
return 100;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public boolean shouldPassiveReset() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected String getTranslationKey() {
|
protected String getTranslationKey() {
|
||||||
return id.getPath();
|
return id.getPath();
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,10 @@ public class NixieTubeBlockEntity extends SmartBlockEntity {
|
||||||
customText = Optional.empty();
|
customText = Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getRedstoneStrength() {
|
||||||
|
return redstoneStrength;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -127,6 +127,8 @@ public class FilterItem extends Item implements MenuProvider {
|
||||||
for (Tag inbt : attributes) {
|
for (Tag inbt : attributes) {
|
||||||
CompoundTag compound = (CompoundTag) inbt;
|
CompoundTag compound = (CompoundTag) inbt;
|
||||||
ItemAttribute attribute = ItemAttribute.fromNBT(compound);
|
ItemAttribute attribute = ItemAttribute.fromNBT(compound);
|
||||||
|
if (attribute == null)
|
||||||
|
continue;
|
||||||
boolean inverted = compound.getBoolean("Inverted");
|
boolean inverted = compound.getBoolean("Inverted");
|
||||||
if (count > 3) {
|
if (count > 3) {
|
||||||
list.add(Components.literal("- ...")
|
list.add(Components.literal("- ...")
|
||||||
|
@ -194,15 +196,19 @@ public class FilterItem extends Item implements MenuProvider {
|
||||||
return test(world, stack, filter, true);
|
return test(world, stack, filter, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean test(Level world, ItemStack stack, ItemStack filter, boolean matchNBT) {
|
public static boolean test(Level world, ItemStack stack, ItemStack filter, boolean matchNBT) {
|
||||||
if (filter.isEmpty())
|
if (filter.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!(filter.getItem() instanceof FilterItem))
|
if (!(filter.getItem() instanceof FilterItem))
|
||||||
return (matchNBT ? ItemHandlerHelper.canItemStacksStack(filter, stack) : ItemStack.isSame(filter, stack));
|
return testDirect(filter, stack, matchNBT);
|
||||||
|
|
||||||
boolean defaults = !filter.hasTag();
|
boolean defaults = !filter.hasTag();
|
||||||
|
|
||||||
|
if (defaults) {
|
||||||
|
return testDirect(filter, stack, matchNBT);
|
||||||
|
}
|
||||||
|
|
||||||
if (AllItems.FILTER.get() == filter.getItem()) {
|
if (AllItems.FILTER.get() == filter.getItem()) {
|
||||||
ItemStackHandler filterItems = getFilterItems(filter);
|
ItemStackHandler filterItems = getFilterItems(filter);
|
||||||
boolean respectNBT = defaults ? false
|
boolean respectNBT = defaults ? false
|
||||||
|
@ -211,24 +217,32 @@ public class FilterItem extends Item implements MenuProvider {
|
||||||
boolean blacklist = defaults ? false
|
boolean blacklist = defaults ? false
|
||||||
: filter.getTag()
|
: filter.getTag()
|
||||||
.getBoolean("Blacklist");
|
.getBoolean("Blacklist");
|
||||||
|
boolean isEmpty = true;
|
||||||
for (int slot = 0; slot < filterItems.getSlots(); slot++) {
|
for (int slot = 0; slot < filterItems.getSlots(); slot++) {
|
||||||
ItemStack stackInSlot = filterItems.getStackInSlot(slot);
|
ItemStack stackInSlot = filterItems.getStackInSlot(slot);
|
||||||
if (stackInSlot.isEmpty())
|
if (stackInSlot.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
|
isEmpty = false;
|
||||||
boolean matches = test(world, stack, stackInSlot, respectNBT);
|
boolean matches = test(world, stack, stackInSlot, respectNBT);
|
||||||
if (matches)
|
if (matches)
|
||||||
return !blacklist;
|
return !blacklist;
|
||||||
}
|
}
|
||||||
|
if (isEmpty) {
|
||||||
|
return testDirect(filter, stack, matchNBT);
|
||||||
|
}
|
||||||
return blacklist;
|
return blacklist;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AllItems.ATTRIBUTE_FILTER.get() == filter.getItem()) {
|
if (AllItems.ATTRIBUTE_FILTER.get() == filter.getItem()) {
|
||||||
WhitelistMode whitelistMode = WhitelistMode.values()[defaults ? 0
|
|
||||||
: filter.getTag()
|
|
||||||
.getInt("WhitelistMode")];
|
|
||||||
ListTag attributes = defaults ? new ListTag()
|
ListTag attributes = defaults ? new ListTag()
|
||||||
: filter.getTag()
|
: filter.getTag()
|
||||||
.getList("MatchedAttributes", Tag.TAG_COMPOUND);
|
.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) {
|
for (Tag inbt : attributes) {
|
||||||
CompoundTag compound = (CompoundTag) inbt;
|
CompoundTag compound = (CompoundTag) inbt;
|
||||||
ItemAttribute attribute = ItemAttribute.fromNBT(compound);
|
ItemAttribute attribute = ItemAttribute.fromNBT(compound);
|
||||||
|
@ -270,7 +284,7 @@ public class FilterItem extends Item implements MenuProvider {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean test(Level world, FluidStack stack, ItemStack filter, boolean matchNBT) {
|
public static boolean test(Level world, FluidStack stack, ItemStack filter, boolean matchNBT) {
|
||||||
if (filter.isEmpty())
|
if (filter.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
if (stack.isEmpty())
|
if (stack.isEmpty())
|
||||||
|
@ -313,4 +327,12 @@ public class FilterItem extends Item implements MenuProvider {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean testDirect(ItemStack filter, ItemStack stack, boolean matchNBT) {
|
||||||
|
if (matchNBT) {
|
||||||
|
return ItemHandlerHelper.canItemStacksStack(filter, stack);
|
||||||
|
} else {
|
||||||
|
return ItemStack.isSame(filter, stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.AllRecipeTypes;
|
import com.simibubi.create.AllRecipeTypes;
|
||||||
import com.simibubi.create.content.contraptions.processing.InWorldProcessing;
|
import com.simibubi.create.content.contraptions.processing.InWorldProcessing;
|
||||||
|
@ -78,6 +79,7 @@ public interface ItemAttribute {
|
||||||
return attributeType;
|
return attributeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
static ItemAttribute fromNBT(CompoundTag nbt) {
|
static ItemAttribute fromNBT(CompoundTag nbt) {
|
||||||
for (ItemAttribute itemAttribute : types)
|
for (ItemAttribute itemAttribute : types)
|
||||||
if (itemAttribute.canRead(nbt))
|
if (itemAttribute.canRead(nbt))
|
||||||
|
|
|
@ -0,0 +1,361 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
import com.mojang.math.Vector3f;
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.AllBogeyStyles;
|
||||||
|
import com.simibubi.create.AllItems;
|
||||||
|
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
||||||
|
import com.simibubi.create.content.logistics.trains.entity.BogeyStyle;
|
||||||
|
import com.simibubi.create.content.logistics.trains.entity.Carriage;
|
||||||
|
import com.simibubi.create.content.logistics.trains.entity.CarriageBogey;
|
||||||
|
import com.simibubi.create.content.logistics.trains.entity.TravellingPoint;
|
||||||
|
import com.simibubi.create.content.logistics.trains.track.AbstractBogeyBlockEntity;
|
||||||
|
import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement;
|
||||||
|
import com.simibubi.create.content.schematics.ItemRequirement;
|
||||||
|
import com.simibubi.create.foundation.block.IBE;
|
||||||
|
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
import com.simibubi.create.foundation.utility.RegisteredObjects;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
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.BlockGetter;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Rotation;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.block.state.StateDefinition;
|
||||||
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||||
|
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
||||||
|
import net.minecraft.world.level.block.state.properties.Property;
|
||||||
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
|
public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> extends Block implements IBE<T>, ProperWaterloggedBlock, ISpecialBlockItemRequirement, IWrenchable {
|
||||||
|
public static final EnumProperty<Direction.Axis> AXIS = BlockStateProperties.HORIZONTAL_AXIS;
|
||||||
|
static final List<ResourceLocation> BOGEYS = new ArrayList<>();
|
||||||
|
public BogeySizes.BogeySize size;
|
||||||
|
|
||||||
|
|
||||||
|
public AbstractBogeyBlock(Properties pProperties, BogeySizes.BogeySize size) {
|
||||||
|
super(pProperties);
|
||||||
|
registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false));
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<TrackMaterial.TrackType> getValidPathfindingTypes(BogeyStyle style) {
|
||||||
|
return ImmutableSet.of(getTrackType(style));
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract TrackMaterial.TrackType getTrackType(BogeyStyle style);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only for internal Create use. If you have your own style set, do not call this method
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static void registerStandardBogey(ResourceLocation block) {
|
||||||
|
BOGEYS.add(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||||
|
builder.add(AXIS, WATERLOGGED);
|
||||||
|
super.createBlockStateDefinition(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState,
|
||||||
|
LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) {
|
||||||
|
updateWater(pLevel, pState, pCurrentPos);
|
||||||
|
return pState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FluidState getFluidState(BlockState pState) {
|
||||||
|
return fluidState(pState);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final EnumSet<Direction> STICKY_X = EnumSet.of(Direction.EAST, Direction.WEST);
|
||||||
|
static final EnumSet<Direction> STICKY_Z = EnumSet.of(Direction.SOUTH, Direction.NORTH);
|
||||||
|
|
||||||
|
public EnumSet<Direction> getStickySurfaces(BlockGetter world, BlockPos pos, BlockState state) {
|
||||||
|
return state.getValue(BlockStateProperties.HORIZONTAL_AXIS) == Direction.Axis.X ? STICKY_X : STICKY_Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract double getWheelPointSpacing();
|
||||||
|
|
||||||
|
public abstract double getWheelRadius();
|
||||||
|
|
||||||
|
public Vec3 getConnectorAnchorOffset(boolean upsideDown) {
|
||||||
|
return getConnectorAnchorOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should be implemented, but not called directly
|
||||||
|
*/
|
||||||
|
protected abstract Vec3 getConnectorAnchorOffset();
|
||||||
|
|
||||||
|
public boolean allowsSingleBogeyCarriage() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract BogeyStyle getDefaultStyle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Legacy system doesn't capture bogey tile entities when constructing a train
|
||||||
|
*/
|
||||||
|
public boolean captureTileEntityForTrain() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void render(@Nullable BlockState state, float wheelAngle, PoseStack ms, float partialTicks,
|
||||||
|
MultiBufferSource buffers, int light, int overlay, BogeyStyle style, CompoundTag bogeyData) {
|
||||||
|
if (style == null)
|
||||||
|
style = getDefaultStyle();
|
||||||
|
|
||||||
|
final Optional<BogeyRenderer.CommonRenderer> commonRenderer
|
||||||
|
= style.getInWorldCommonRenderInstance();
|
||||||
|
final BogeyRenderer renderer = style.getInWorldRenderInstance(this.getSize());
|
||||||
|
if (state != null) {
|
||||||
|
ms.translate(.5f, .5f, .5f);
|
||||||
|
if (state.getValue(AXIS) == Direction.Axis.X)
|
||||||
|
ms.mulPose(Vector3f.YP.rotationDegrees(90));
|
||||||
|
}
|
||||||
|
ms.translate(0, -1.5 - 1 / 128f, 0);
|
||||||
|
VertexConsumer vb = buffers.getBuffer(RenderType.cutoutMipped());
|
||||||
|
if (bogeyData == null)
|
||||||
|
bogeyData = new CompoundTag();
|
||||||
|
renderer.render(bogeyData, wheelAngle, ms, light, vb, state == null);
|
||||||
|
CompoundTag finalBogeyData = bogeyData;
|
||||||
|
commonRenderer.ifPresent(common ->
|
||||||
|
common.render(finalBogeyData, wheelAngle, ms, light, vb, state == null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeySizes.BogeySize getSize() {
|
||||||
|
return this.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Direction getBogeyUpDirection() {
|
||||||
|
return Direction.UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTrackAxisAlongFirstCoordinate(BlockState state) {
|
||||||
|
return state.getValue(AXIS) == Direction.Axis.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public BlockState getMatchingBogey(Direction upDirection, boolean axisAlongFirst) {
|
||||||
|
if (upDirection != Direction.UP)
|
||||||
|
return null;
|
||||||
|
return defaultBlockState().setValue(AXIS, axisAlongFirst ? Direction.Axis.X : Direction.Axis.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand,
|
||||||
|
BlockHitResult hit) {
|
||||||
|
if (level.isClientSide)
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
ItemStack stack = player.getItemInHand(hand);
|
||||||
|
|
||||||
|
if (!player.isShiftKeyDown() && stack.is(AllItems.WRENCH.get()) && !player.getCooldowns().isOnCooldown(stack.getItem())
|
||||||
|
&& AllBogeyStyles.BOGEY_STYLES.size() > 1) {
|
||||||
|
|
||||||
|
BlockEntity be = level.getBlockEntity(pos);
|
||||||
|
|
||||||
|
if (!(be instanceof AbstractBogeyBlockEntity sbte))
|
||||||
|
return InteractionResult.FAIL;
|
||||||
|
|
||||||
|
player.getCooldowns().addCooldown(stack.getItem(), 20);
|
||||||
|
BogeyStyle currentStyle = sbte.getStyle();
|
||||||
|
|
||||||
|
BogeySizes.BogeySize size = getSize();
|
||||||
|
|
||||||
|
BogeyStyle style = this.getNextStyle(currentStyle);
|
||||||
|
if (style == currentStyle)
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
|
||||||
|
Set<BogeySizes.BogeySize> validSizes = style.validSizes();
|
||||||
|
|
||||||
|
for (int i = 0; i < BogeySizes.count(); i++) {
|
||||||
|
if (validSizes.contains(size)) break;
|
||||||
|
size = size.increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
sbte.setBogeyStyle(style);
|
||||||
|
|
||||||
|
CompoundTag defaultData = style.defaultData;
|
||||||
|
sbte.setBogeyData(sbte.getBogeyData().merge(defaultData));
|
||||||
|
|
||||||
|
if (size == getSize()) {
|
||||||
|
player.displayClientMessage(Lang.translateDirect("bogey.style.updated_style")
|
||||||
|
.append(": ").append(style.displayName), true);
|
||||||
|
} else {
|
||||||
|
CompoundTag oldData = sbte.getBogeyData();
|
||||||
|
level.setBlock(pos, this.getStateOfSize(sbte, size), 3);
|
||||||
|
BlockEntity newBlockEntity = level.getBlockEntity(pos);
|
||||||
|
if (!(newBlockEntity instanceof AbstractBogeyBlockEntity newTileEntity))
|
||||||
|
return InteractionResult.FAIL;
|
||||||
|
newTileEntity.setBogeyData(oldData);
|
||||||
|
player.displayClientMessage(Lang.translateDirect("bogey.style.updated_style_and_size")
|
||||||
|
.append(": ").append(style.displayName), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return InteractionResult.CONSUME;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InteractionResult.PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If, instead of using the style-based cycling system you prefer to use separate blocks, return them from this method
|
||||||
|
*/
|
||||||
|
protected List<ResourceLocation> getBogeyBlockCycle() {
|
||||||
|
return BOGEYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getRotatedBlockState(BlockState state, Direction targetedFace) {
|
||||||
|
Block block = state.getBlock();
|
||||||
|
List<ResourceLocation> bogeyCycle = getBogeyBlockCycle();
|
||||||
|
int indexOf = bogeyCycle.indexOf(RegisteredObjects.getKeyOrThrow(block));
|
||||||
|
if (indexOf == -1)
|
||||||
|
return state;
|
||||||
|
int index = (indexOf + 1) % bogeyCycle.size();
|
||||||
|
Direction bogeyUpDirection = getBogeyUpDirection();
|
||||||
|
boolean trackAxisAlongFirstCoordinate = isTrackAxisAlongFirstCoordinate(state);
|
||||||
|
|
||||||
|
while (index != indexOf) {
|
||||||
|
ResourceLocation id = bogeyCycle.get(index);
|
||||||
|
Block newBlock = ForgeRegistries.BLOCKS.getValue(id);
|
||||||
|
if (newBlock instanceof AbstractBogeyBlock<?> bogey) {
|
||||||
|
BlockState matchingBogey = bogey.getMatchingBogey(bogeyUpDirection, trackAxisAlongFirstCoordinate);
|
||||||
|
if (matchingBogey != null)
|
||||||
|
return copyProperties(state, matchingBogey);
|
||||||
|
}
|
||||||
|
index = (index + 1) % bogeyCycle.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockState getNextSize(Level level, BlockPos pos) {
|
||||||
|
BlockEntity te = level.getBlockEntity(pos);
|
||||||
|
if (te instanceof AbstractBogeyBlockEntity sbte)
|
||||||
|
return this.getNextSize(sbte);
|
||||||
|
return level.getBlockState(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of BlockState Properties to copy between sizes
|
||||||
|
*/
|
||||||
|
public List<Property<?>> propertiesToCopy() {
|
||||||
|
return ImmutableList.of(WATERLOGGED, AXIS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// generic method needed to satisfy Property and BlockState's generic requirements
|
||||||
|
private <V extends Comparable<V>> BlockState copyProperty(BlockState source, BlockState target, Property<V> property) {
|
||||||
|
if (source.hasProperty(property) && target.hasProperty(property)) {
|
||||||
|
return target.setValue(property, source.getValue(property));
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockState copyProperties(BlockState source, BlockState target) {
|
||||||
|
for (Property<?> property : propertiesToCopy())
|
||||||
|
target = copyProperty(source, target, property);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockState getNextSize(AbstractBogeyBlockEntity sbte) {
|
||||||
|
BogeySizes.BogeySize size = this.getSize();
|
||||||
|
BogeyStyle style = sbte.getStyle();
|
||||||
|
BlockState nextBlock = style.getNextBlock(size).defaultBlockState();
|
||||||
|
nextBlock = copyProperties(sbte.getBlockState(), nextBlock);
|
||||||
|
return nextBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockState getStateOfSize(AbstractBogeyBlockEntity sbte, BogeySizes.BogeySize size) {
|
||||||
|
BogeyStyle style = sbte.getStyle();
|
||||||
|
BlockState state = style.getBlockOfSize(size).defaultBlockState();
|
||||||
|
return copyProperties(sbte.getBlockState(), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyStyle getNextStyle(Level level, BlockPos pos) {
|
||||||
|
BlockEntity te = level.getBlockEntity(pos);
|
||||||
|
if (te instanceof AbstractBogeyBlockEntity sbte)
|
||||||
|
return this.getNextStyle(sbte.getStyle());
|
||||||
|
return getDefaultStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyStyle getNextStyle(BogeyStyle style) {
|
||||||
|
Collection<BogeyStyle> allStyles = style.getCycleGroup().values();
|
||||||
|
if (allStyles.size() <= 1)
|
||||||
|
return style;
|
||||||
|
List<BogeyStyle> list = new ArrayList<>(allStyles);
|
||||||
|
return Iterate.cycleValue(list, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull BlockState rotate(@NotNull BlockState pState, Rotation pRotation) {
|
||||||
|
return switch (pRotation) {
|
||||||
|
case COUNTERCLOCKWISE_90, CLOCKWISE_90 -> pState.cycle(AXIS);
|
||||||
|
default -> pState;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) {
|
||||||
|
return new ItemRequirement(ItemRequirement.ItemUseType.CONSUME, AllBlocks.RAILWAY_CASING.asStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canBeUpsideDown() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUpsideDown(BlockState state) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockState getVersion(BlockState base, boolean upsideDown) {
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.entity.item.ItemEntity;
|
import net.minecraft.world.entity.item.ItemEntity;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.GameRules;
|
import net.minecraft.world.level.GameRules;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.phys.AABB;
|
import net.minecraft.world.phys.AABB;
|
||||||
|
@ -42,6 +43,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
public Couple<Integer> smoothing;
|
public Couple<Integer> smoothing;
|
||||||
public boolean primary;
|
public boolean primary;
|
||||||
public boolean hasGirder;
|
public boolean hasGirder;
|
||||||
|
protected TrackMaterial trackMaterial;
|
||||||
|
|
||||||
// runtime
|
// runtime
|
||||||
|
|
||||||
|
@ -58,19 +60,20 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
private AABB bounds;
|
private AABB bounds;
|
||||||
|
|
||||||
public BezierConnection(Couple<BlockPos> positions, Couple<Vec3> starts, Couple<Vec3> axes, Couple<Vec3> normals,
|
public BezierConnection(Couple<BlockPos> positions, Couple<Vec3> starts, Couple<Vec3> axes, Couple<Vec3> normals,
|
||||||
boolean primary, boolean girder) {
|
boolean primary, boolean girder, TrackMaterial material) {
|
||||||
tePositions = positions;
|
tePositions = positions;
|
||||||
this.starts = starts;
|
this.starts = starts;
|
||||||
this.axes = axes;
|
this.axes = axes;
|
||||||
this.normals = normals;
|
this.normals = normals;
|
||||||
this.primary = primary;
|
this.primary = primary;
|
||||||
this.hasGirder = girder;
|
this.hasGirder = girder;
|
||||||
|
this.trackMaterial = material;
|
||||||
resolved = false;
|
resolved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BezierConnection secondary() {
|
public BezierConnection secondary() {
|
||||||
BezierConnection bezierConnection =
|
BezierConnection bezierConnection = new BezierConnection(tePositions.swap(), starts.swap(), axes.swap(),
|
||||||
new BezierConnection(tePositions.swap(), starts.swap(), axes.swap(), normals.swap(), !primary, hasGirder);
|
normals.swap(), !primary, hasGirder, trackMaterial);
|
||||||
if (smoothing != null)
|
if (smoothing != null)
|
||||||
bezierConnection.smoothing = smoothing.swap();
|
bezierConnection.smoothing = smoothing.swap();
|
||||||
return bezierConnection;
|
return bezierConnection;
|
||||||
|
@ -80,6 +83,26 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
return secondary().secondary();
|
return secondary().secondary();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean coupleEquals(Couple<?> a, Couple<?> b) {
|
||||||
|
return (a.getFirst()
|
||||||
|
.equals(b.getFirst())
|
||||||
|
&& a.getSecond()
|
||||||
|
.equals(b.getSecond()))
|
||||||
|
|| (a.getFirst() instanceof Vec3 aFirst && a.getSecond() instanceof Vec3 aSecond
|
||||||
|
&& b.getFirst() instanceof Vec3 bFirst && b.getSecond() instanceof Vec3 bSecond
|
||||||
|
&& aFirst.closerThan(bFirst, 1e-6) && aSecond.closerThan(bSecond, 1e-6));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equalsSansMaterial(BezierConnection other) {
|
||||||
|
return equalsSansMaterialInner(other) || equalsSansMaterialInner(other.secondary());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean equalsSansMaterialInner(BezierConnection other) {
|
||||||
|
return this == other || (other != null && coupleEquals(this.tePositions, other.tePositions)
|
||||||
|
&& coupleEquals(this.starts, other.starts) && coupleEquals(this.axes, other.axes)
|
||||||
|
&& coupleEquals(this.normals, other.normals) && this.hasGirder == other.hasGirder);
|
||||||
|
}
|
||||||
|
|
||||||
public BezierConnection(CompoundTag compound, BlockPos localTo) {
|
public BezierConnection(CompoundTag compound, BlockPos localTo) {
|
||||||
this(Couple.deserializeEach(compound.getList("Positions", Tag.TAG_COMPOUND), NbtUtils::readBlockPos)
|
this(Couple.deserializeEach(compound.getList("Positions", Tag.TAG_COMPOUND), NbtUtils::readBlockPos)
|
||||||
.map(b -> b.offset(localTo)),
|
.map(b -> b.offset(localTo)),
|
||||||
|
@ -87,7 +110,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
.map(v -> v.add(Vec3.atLowerCornerOf(localTo))),
|
.map(v -> v.add(Vec3.atLowerCornerOf(localTo))),
|
||||||
Couple.deserializeEach(compound.getList("Axes", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
|
Couple.deserializeEach(compound.getList("Axes", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
|
||||||
Couple.deserializeEach(compound.getList("Normals", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
|
Couple.deserializeEach(compound.getList("Normals", Tag.TAG_COMPOUND), VecHelper::readNBTCompound),
|
||||||
compound.getBoolean("Primary"), compound.getBoolean("Girder"));
|
compound.getBoolean("Primary"), compound.getBoolean("Girder"), TrackMaterial.deserialize(compound.getString("Material")));
|
||||||
|
|
||||||
if (compound.contains("Smoothing"))
|
if (compound.contains("Smoothing"))
|
||||||
smoothing =
|
smoothing =
|
||||||
|
@ -105,6 +128,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
compound.put("Starts", starts.serializeEach(VecHelper::writeNBTCompound));
|
compound.put("Starts", starts.serializeEach(VecHelper::writeNBTCompound));
|
||||||
compound.put("Axes", axes.serializeEach(VecHelper::writeNBTCompound));
|
compound.put("Axes", axes.serializeEach(VecHelper::writeNBTCompound));
|
||||||
compound.put("Normals", normals.serializeEach(VecHelper::writeNBTCompound));
|
compound.put("Normals", normals.serializeEach(VecHelper::writeNBTCompound));
|
||||||
|
compound.putString("Material", getMaterial().id.toString());
|
||||||
|
|
||||||
if (smoothing != null)
|
if (smoothing != null)
|
||||||
compound.put("Smoothing", smoothing.serializeEach(NBTHelper::intToCompound));
|
compound.put("Smoothing", smoothing.serializeEach(NBTHelper::intToCompound));
|
||||||
|
@ -115,7 +139,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
public BezierConnection(FriendlyByteBuf buffer) {
|
public BezierConnection(FriendlyByteBuf buffer) {
|
||||||
this(Couple.create(buffer::readBlockPos), Couple.create(() -> VecHelper.read(buffer)),
|
this(Couple.create(buffer::readBlockPos), Couple.create(() -> VecHelper.read(buffer)),
|
||||||
Couple.create(() -> VecHelper.read(buffer)), Couple.create(() -> VecHelper.read(buffer)),
|
Couple.create(() -> VecHelper.read(buffer)), Couple.create(() -> VecHelper.read(buffer)),
|
||||||
buffer.readBoolean(), buffer.readBoolean());
|
buffer.readBoolean(), buffer.readBoolean(), TrackMaterial.deserialize(buffer.readUtf()));
|
||||||
if (buffer.readBoolean())
|
if (buffer.readBoolean())
|
||||||
smoothing = Couple.create(buffer::readVarInt);
|
smoothing = Couple.create(buffer::readVarInt);
|
||||||
}
|
}
|
||||||
|
@ -127,6 +151,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
normals.forEach(v -> VecHelper.write(v, buffer));
|
normals.forEach(v -> VecHelper.write(v, buffer));
|
||||||
buffer.writeBoolean(primary);
|
buffer.writeBoolean(primary);
|
||||||
buffer.writeBoolean(hasGirder);
|
buffer.writeBoolean(hasGirder);
|
||||||
|
buffer.writeUtf(getMaterial().id.toString());
|
||||||
buffer.writeBoolean(smoothing != null);
|
buffer.writeBoolean(smoothing != null);
|
||||||
if (smoothing != null)
|
if (smoothing != null)
|
||||||
smoothing.forEach(buffer::writeVarInt);
|
smoothing.forEach(buffer::writeVarInt);
|
||||||
|
@ -333,7 +358,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
Inventory inv = player.getInventory();
|
Inventory inv = player.getInventory();
|
||||||
int tracks = getTrackItemCost();
|
int tracks = getTrackItemCost();
|
||||||
while (tracks > 0) {
|
while (tracks > 0) {
|
||||||
inv.placeItemBackInInventory(AllBlocks.TRACK.asStack(Math.min(64, tracks)));
|
inv.placeItemBackInInventory(new ItemStack(getMaterial().getBlock(), Math.min(64, tracks)));
|
||||||
tracks -= 64;
|
tracks -= 64;
|
||||||
}
|
}
|
||||||
int girders = getGirderItemCost();
|
int girders = getGirderItemCost();
|
||||||
|
@ -361,7 +386,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
continue;
|
continue;
|
||||||
Vec3 v = VecHelper.offsetRandomly(segment.position, level.random, .125f)
|
Vec3 v = VecHelper.offsetRandomly(segment.position, level.random, .125f)
|
||||||
.add(origin);
|
.add(origin);
|
||||||
ItemEntity entity = new ItemEntity(level, v.x, v.y, v.z, AllBlocks.TRACK.asStack());
|
ItemEntity entity = new ItemEntity(level, v.x, v.y, v.z, getMaterial().asStack());
|
||||||
entity.setDefaultPickUpDelay();
|
entity.setDefaultPickUpDelay();
|
||||||
level.addFreshEntity(entity);
|
level.addFreshEntity(entity);
|
||||||
if (!hasGirder)
|
if (!hasGirder)
|
||||||
|
@ -375,7 +400,7 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void spawnDestroyParticles(Level level) {
|
public void spawnDestroyParticles(Level level) {
|
||||||
BlockParticleOption data = new BlockParticleOption(ParticleTypes.BLOCK, AllBlocks.TRACK.getDefaultState());
|
BlockParticleOption data = new BlockParticleOption(ParticleTypes.BLOCK, getMaterial().getBlock().defaultBlockState());
|
||||||
BlockParticleOption girderData =
|
BlockParticleOption girderData =
|
||||||
new BlockParticleOption(ParticleTypes.BLOCK, AllBlocks.METAL_GIRDER.getDefaultState());
|
new BlockParticleOption(ParticleTypes.BLOCK, AllBlocks.METAL_GIRDER.getDefaultState());
|
||||||
if (!(level instanceof ServerLevel slevel))
|
if (!(level instanceof ServerLevel slevel))
|
||||||
|
@ -393,6 +418,14 @@ public class BezierConnection implements Iterable<BezierConnection.Segment> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TrackMaterial getMaterial() {
|
||||||
|
return trackMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaterial(TrackMaterial material) {
|
||||||
|
trackMaterial = material;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Segment {
|
public static class Segment {
|
||||||
|
|
||||||
public int index;
|
public int index;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.simibubi.create.content.logistics.trains;
|
package com.simibubi.create.content.logistics.trains;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.simibubi.create.content.logistics.trains.track.StandardBogeyBlockEntity;
|
import com.simibubi.create.content.logistics.trains.track.AbstractBogeyBlockEntity;
|
||||||
import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer;
|
import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
|
@ -17,11 +17,11 @@ public class BogeyBlockEntityRenderer<T extends BlockEntity> extends SafeBlockEn
|
||||||
protected void renderSafe(T be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light,
|
protected void renderSafe(T be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light,
|
||||||
int overlay) {
|
int overlay) {
|
||||||
BlockState blockState = be.getBlockState();
|
BlockState blockState = be.getBlockState();
|
||||||
float angle = 0;
|
if (be instanceof AbstractBogeyBlockEntity sbte) {
|
||||||
if (be instanceof StandardBogeyBlockEntity sbte)
|
float angle = sbte.getVirtualAngle(partialTicks);
|
||||||
angle = sbte.getVirtualAngle(partialTicks);
|
if (blockState.getBlock() instanceof AbstractBogeyBlock<?> bogey)
|
||||||
if (blockState.getBlock()instanceof IBogeyBlock bogey)
|
bogey.render(blockState, angle, ms, partialTicks, buffer, light, overlay, sbte.getStyle(), sbte.getBogeyData());
|
||||||
bogey.render(blockState, angle, ms, partialTicks, buffer, light, overlay);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,309 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.MaterialManager;
|
||||||
|
import com.jozufozu.flywheel.core.Materials;
|
||||||
|
import com.jozufozu.flywheel.core.PartialModel;
|
||||||
|
import com.jozufozu.flywheel.core.materials.model.ModelData;
|
||||||
|
import com.jozufozu.flywheel.util.transform.Transform;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.render.CachedBufferer;
|
||||||
|
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public abstract class BogeyRenderer {
|
||||||
|
Map<String, ModelData[]> contraptionModelData = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A common interface for getting transform data for both in-world and in-contraption model data safely from a
|
||||||
|
* partial model
|
||||||
|
*
|
||||||
|
* @param model The key for the model data to instantiate or retrieve
|
||||||
|
* @param ms The posestack used for contraption model data
|
||||||
|
* @param inInstancedContraption The type of model needed
|
||||||
|
* @param size The amount of models needed
|
||||||
|
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||||
|
*/
|
||||||
|
public Transform<?>[] getTransformsFromPartial(PartialModel model, PoseStack ms, boolean inInstancedContraption, int size) {
|
||||||
|
return (inInstancedContraption) ? transformContraptionModelData(keyFromModel(model), ms) : createModelData(model, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A common interface for getting transform data for both in-world and in-contraption model data safely from a
|
||||||
|
* blockstate
|
||||||
|
*
|
||||||
|
* @param state The key for the model data to instantiate or retrieve
|
||||||
|
* @param ms The posestack used for contraption model data
|
||||||
|
* @param inContraption The type of model needed
|
||||||
|
* @param size The amount of models needed
|
||||||
|
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||||
|
*/
|
||||||
|
public Transform<?>[] getTransformsFromBlockState(BlockState state, PoseStack ms, boolean inContraption, int size) {
|
||||||
|
return inContraption ? transformContraptionModelData(keyFromModel(state), ms) : createModelData(state, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for calling both in-world and in-contraption rendering
|
||||||
|
*
|
||||||
|
* @param bogeyData Custom data stored on the bogey able to be used for rendering
|
||||||
|
* @param wheelAngle The angle of the wheel
|
||||||
|
* @param ms The posestack to render to
|
||||||
|
* @param light (Optional) Light used for in-world rendering
|
||||||
|
* @param vb (Optional) Vertex Consumer used for in-world rendering
|
||||||
|
*/
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public abstract void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for calling in-contraption rendering ensuring that falsey data is handled correctly
|
||||||
|
*
|
||||||
|
* @param bogeyData Custom data stored on the bogey able to be used for rendering
|
||||||
|
* @param wheelAngle The angle of the wheel
|
||||||
|
* @param ms The posestack to render to
|
||||||
|
*/
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms) {
|
||||||
|
this.render(bogeyData, wheelAngle, ms, 0, null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract BogeySizes.BogeySize getSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to collect Contraption Model Data for in-contraption rendering, should not be utilised directly when
|
||||||
|
* rendering to prevent render type mismatch
|
||||||
|
*
|
||||||
|
* @param key The key used to access the model
|
||||||
|
* @param ms Posestack of the contraption to bind the model data to
|
||||||
|
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||||
|
*/
|
||||||
|
private Transform<?>[] transformContraptionModelData(String key, PoseStack ms) {
|
||||||
|
ModelData[] modelData = contraptionModelData.get(key);
|
||||||
|
Arrays.stream(modelData).forEach(modelDataElement -> modelDataElement.setTransform(ms));
|
||||||
|
return modelData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for in world rendering, creates a set count of model data to be rendered, allowing for a generic response
|
||||||
|
* when rendering multiple models both in-world and in-contraption for example, with wheels
|
||||||
|
*
|
||||||
|
* @param model The partial model of the model data ot be made
|
||||||
|
* @param size The Amount of models needed
|
||||||
|
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||||
|
*/
|
||||||
|
private Transform<?>[] createModelData(PartialModel model, int size) {
|
||||||
|
BlockState air = Blocks.AIR.defaultBlockState();
|
||||||
|
SuperByteBuffer[] data = { CachedBufferer.partial(model, air) };
|
||||||
|
return expandArrayToLength(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for in world rendering, creates a set count of model data to be rendered, allowing for a generic response
|
||||||
|
* when rendering multiple models both in-world and in-contraption for example, with wheels
|
||||||
|
*
|
||||||
|
* @param state The state of the model data to be made
|
||||||
|
* @param size Amount of models needed
|
||||||
|
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||||
|
*/
|
||||||
|
private Transform<?>[] createModelData(BlockState state, int size) {
|
||||||
|
SuperByteBuffer[] data = { CachedBufferer.block(state) };
|
||||||
|
return expandArrayToLength(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function to clone in-world models to a set size to allow for common handling of rendering with multiple
|
||||||
|
* instances of the same model for example with wheels
|
||||||
|
*
|
||||||
|
* @param data An in-world model to be replicated
|
||||||
|
* @param size Amount of models needed
|
||||||
|
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||||
|
*/
|
||||||
|
private Transform<?>[] expandArrayToLength(SuperByteBuffer[] data, int size) {
|
||||||
|
return Arrays.stream(Collections.nCopies(size, data).toArray())
|
||||||
|
.flatMap(inner -> Arrays.stream((SuperByteBuffer[]) inner))
|
||||||
|
.toArray(SuperByteBuffer[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to collect or create a single model from a partial model used for both in-world and
|
||||||
|
* in-contraption rendering
|
||||||
|
*
|
||||||
|
* @param model The key of the model to be collected or instantiated
|
||||||
|
* @param ms Posestack to bind the model to if it is within a contraption
|
||||||
|
* @param inInstancedContraption Type of rendering required
|
||||||
|
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||||
|
*/
|
||||||
|
public Transform<?> getTransformFromPartial(PartialModel model, PoseStack ms, boolean inInstancedContraption) {
|
||||||
|
BlockState air = Blocks.AIR.defaultBlockState();
|
||||||
|
return inInstancedContraption ? contraptionModelData.get(keyFromModel(model))[0].setTransform(ms)
|
||||||
|
: CachedBufferer.partial(model, air);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A common interface for getting transform data for blockstates, for a single model
|
||||||
|
*
|
||||||
|
* @param state The state of the model to be collected or instantiated
|
||||||
|
* @param ms Posestack to bind the model to if it is within a contraption
|
||||||
|
* @param inContraption Type of model required
|
||||||
|
* @return A generic transform which can be used for both in-world and in-contraption models
|
||||||
|
*/
|
||||||
|
public Transform<?> getTransformFromBlockState(BlockState state, PoseStack ms, boolean inContraption) {
|
||||||
|
return (inContraption) ? contraptionModelData.get(keyFromModel(state))[0].setTransform(ms)
|
||||||
|
: CachedBufferer.block(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides render implementations a point in setup to instantiate all model data to be needed
|
||||||
|
*
|
||||||
|
* @param materialManager The material manager
|
||||||
|
*/
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public abstract void initialiseContraptionModelData(MaterialManager materialManager);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates instances of models for in-world rendering to a set length from a provided partial model
|
||||||
|
*
|
||||||
|
* @param materialManager The material manager
|
||||||
|
* @param model Partial model to be instanced
|
||||||
|
* @param count Amount of models neeeded
|
||||||
|
*/
|
||||||
|
public void createModelInstances(MaterialManager materialManager, PartialModel model, int count) {
|
||||||
|
ModelData[] modelData = new ModelData[count];
|
||||||
|
materialManager.defaultSolid().material(Materials.TRANSFORMED)
|
||||||
|
.getModel(model).createInstances(modelData);
|
||||||
|
contraptionModelData.put(keyFromModel(model), modelData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates instances of models for in-contraption rendering to a set length from a provided blockstate
|
||||||
|
*
|
||||||
|
* @param materialManager The material manager
|
||||||
|
* @param state Blockstate of the model to be created
|
||||||
|
* @param count Amount of models needed
|
||||||
|
*/
|
||||||
|
public void createModelInstances(MaterialManager materialManager, BlockState state, int count) {
|
||||||
|
ModelData[] modelData = new ModelData[count];
|
||||||
|
materialManager.defaultSolid().material(Materials.TRANSFORMED)
|
||||||
|
.getModel(state).createInstances(modelData);
|
||||||
|
contraptionModelData.put(keyFromModel(state), modelData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a single instance of models for in-contraption rendering from a provided blockstate
|
||||||
|
*
|
||||||
|
* @param materialManager The material manager
|
||||||
|
* @param state Blockstate of the model to be created
|
||||||
|
*/
|
||||||
|
public void createModelInstance(MaterialManager materialManager, BlockState state) {
|
||||||
|
this.createModelInstances(materialManager, state, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to create a single model instance for in-contraption rendering
|
||||||
|
*
|
||||||
|
* @param materialManager The material manager
|
||||||
|
* @param models The type of model to create instances of
|
||||||
|
*/
|
||||||
|
public void createModelInstances(MaterialManager materialManager, PartialModel... models) {
|
||||||
|
for (PartialModel model : models)
|
||||||
|
createModelInstances(materialManager, model, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles scale for all model data and renders non contraption model data
|
||||||
|
*
|
||||||
|
* @param b The model data itself
|
||||||
|
* @param ms Pose stack to render to
|
||||||
|
* @param light light level of the scene
|
||||||
|
* @param vb Vertex Consumber to render to
|
||||||
|
* @param <B> Generic alias for both contraption and in-world model data
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static <B extends Transform<?>> void finalize(B b, PoseStack ms, int light, @Nullable VertexConsumer vb) {
|
||||||
|
b.scale(1 - 1/512f);
|
||||||
|
if (b instanceof SuperByteBuffer byteBuf && vb != null)
|
||||||
|
byteBuf.light(light).renderInto(ms, vb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatic handling for setting empty transforms for all model data
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void emptyTransforms() {
|
||||||
|
for (ModelData[] data : contraptionModelData.values())
|
||||||
|
for (ModelData model : data)
|
||||||
|
model.setEmptyTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatic handling for updating all model data's light
|
||||||
|
*
|
||||||
|
* @param blockLight the blocklight to be applied
|
||||||
|
* @param skyLight the skylight to be applied
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void updateLight(int blockLight, int skyLight) {
|
||||||
|
for (ModelData[] data : contraptionModelData.values())
|
||||||
|
for (ModelData model : data)
|
||||||
|
model.setBlockLight(blockLight).setSkyLight(skyLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatic handling for clearing all model data of a contraption
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
for (ModelData[] data : contraptionModelData.values())
|
||||||
|
for (ModelData model : data)
|
||||||
|
model.delete();
|
||||||
|
contraptionModelData.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a model key from a partial model, so it can be easily accessed
|
||||||
|
*
|
||||||
|
* @param partialModel the model we want a unique key for
|
||||||
|
* @return Key of the model
|
||||||
|
*/
|
||||||
|
|
||||||
|
private String keyFromModel(PartialModel partialModel) {
|
||||||
|
return partialModel.getLocation().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a model key from a blockstate, so it can be easily accessed
|
||||||
|
*
|
||||||
|
* @param state Blockstate of the model
|
||||||
|
* @return Key of the model
|
||||||
|
*/
|
||||||
|
|
||||||
|
private String keyFromModel(BlockState state) {
|
||||||
|
return state.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class CommonRenderer extends BogeyRenderer {
|
||||||
|
@Override
|
||||||
|
public BogeySizes.BogeySize getSize() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains;
|
||||||
|
|
||||||
|
import com.simibubi.create.Create;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class BogeySizes {
|
||||||
|
private static final Collection<BogeySize> BOGEY_SIZES = new HashSet<>();
|
||||||
|
public static final BogeySize SMALL = new BogeySize(Create.ID, "small", 6.5f / 16f);
|
||||||
|
public static final BogeySize LARGE = new BogeySize(Create.ID, "large", 12.5f / 16f);
|
||||||
|
|
||||||
|
static {
|
||||||
|
BOGEY_SIZES.add(SMALL);
|
||||||
|
BOGEY_SIZES.add(LARGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BogeySize addSize(String modId, String name, float size) {
|
||||||
|
ResourceLocation location = new ResourceLocation(modId, name);
|
||||||
|
return addSize(location, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BogeySize addSize(ResourceLocation location, float size) {
|
||||||
|
BogeySize customSize = new BogeySize(location, size);
|
||||||
|
BOGEY_SIZES.add(customSize);
|
||||||
|
return customSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<BogeySize> getAllSizesSmallToLarge() {
|
||||||
|
return BOGEY_SIZES.stream()
|
||||||
|
.sorted(Comparator.comparing(BogeySize::wheelRadius))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<BogeySize> getAllSizesLargeToSmall() {
|
||||||
|
List<BogeySize> sizes = getAllSizesSmallToLarge();
|
||||||
|
Collections.reverse(sizes);
|
||||||
|
return sizes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int count() {
|
||||||
|
return BOGEY_SIZES.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public record BogeySize(ResourceLocation location, float wheelRadius) {
|
||||||
|
public BogeySize(String modId, String name, float wheelRadius) {
|
||||||
|
this(new ResourceLocation(modId, name), wheelRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeySize increment() {
|
||||||
|
List<BogeySize> values = getAllSizesSmallToLarge();
|
||||||
|
int ordinal = values.indexOf(this);
|
||||||
|
return values.get((ordinal + 1) % values.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean is(BogeySize size) {
|
||||||
|
return size.location == this.location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -265,13 +265,17 @@ public class GlobalRailwayManager {
|
||||||
public void clientTick() {
|
public void clientTick() {
|
||||||
if (isTrackGraphDebugActive())
|
if (isTrackGraphDebugActive())
|
||||||
for (TrackGraph trackGraph : trackNetworks.values())
|
for (TrackGraph trackGraph : trackNetworks.values())
|
||||||
TrackGraphVisualizer.debugViewGraph(trackGraph);
|
TrackGraphVisualizer.debugViewGraph(trackGraph, isTrackGraphDebugExtended());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isTrackGraphDebugActive() {
|
private static boolean isTrackGraphDebugActive() {
|
||||||
return KineticDebugger.isF3DebugModeActive() && AllConfigs.client().showTrackGraphOnF3.get();
|
return KineticDebugger.isF3DebugModeActive() && AllConfigs.client().showTrackGraphOnF3.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isTrackGraphDebugExtended() {
|
||||||
|
return AllConfigs.client().showExtendedTrackGraphOnF3.get();
|
||||||
|
}
|
||||||
|
|
||||||
public GlobalRailwayManager sided(LevelAccessor level) {
|
public GlobalRailwayManager sided(LevelAccessor level) {
|
||||||
if (level != null && !level.isClientSide())
|
if (level != null && !level.isClientSide())
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
package com.simibubi.create.content.logistics.trains;
|
|
||||||
|
|
||||||
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.MaterialManager;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
|
||||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
|
||||||
import com.simibubi.create.content.logistics.trains.entity.BogeyInstance;
|
|
||||||
import com.simibubi.create.content.logistics.trains.entity.CarriageBogey;
|
|
||||||
import com.simibubi.create.foundation.utility.RegisteredObjects;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.level.BlockGetter;
|
|
||||||
import net.minecraft.world.level.block.Block;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
|
||||||
import net.minecraft.world.phys.Vec3;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
|
||||||
|
|
||||||
public interface IBogeyBlock extends IWrenchable {
|
|
||||||
|
|
||||||
static final List<ResourceLocation> BOGEYS = new ArrayList<>();
|
|
||||||
|
|
||||||
public static void register(ResourceLocation block) {
|
|
||||||
BOGEYS.add(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
public EnumSet<Direction> getStickySurfaces(BlockGetter world, BlockPos pos, BlockState state);
|
|
||||||
|
|
||||||
public double getWheelPointSpacing();
|
|
||||||
|
|
||||||
public double getWheelRadius();
|
|
||||||
|
|
||||||
public boolean allowsSingleBogeyCarriage();
|
|
||||||
|
|
||||||
public Vec3 getConnectorAnchorOffset();
|
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
|
||||||
public void render(@Nullable BlockState state, float wheelAngle, PoseStack ms, float partialTicks,
|
|
||||||
MultiBufferSource buffers, int light, int overlay);
|
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
|
||||||
public BogeyInstance createInstance(MaterialManager materialManager, CarriageBogey bogey);
|
|
||||||
|
|
||||||
public default Direction getBogeyUpDirection() {
|
|
||||||
return Direction.UP;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTrackAxisAlongFirstCoordinate(BlockState state);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public BlockState getMatchingBogey(Direction upDirection, boolean axisAlongFirst);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default BlockState getRotatedBlockState(BlockState state, Direction targetedFace) {
|
|
||||||
Block block = state.getBlock();
|
|
||||||
int indexOf = BOGEYS.indexOf(RegisteredObjects.getKeyOrThrow(block));
|
|
||||||
if (indexOf == -1)
|
|
||||||
return state;
|
|
||||||
|
|
||||||
int index = (indexOf + 1) % BOGEYS.size();
|
|
||||||
Direction bogeyUpDirection = getBogeyUpDirection();
|
|
||||||
boolean trackAxisAlongFirstCoordinate = isTrackAxisAlongFirstCoordinate(state);
|
|
||||||
|
|
||||||
while (index != indexOf) {
|
|
||||||
ResourceLocation id = BOGEYS.get(index);
|
|
||||||
Block newBlock = ForgeRegistries.BLOCKS.getValue(id);
|
|
||||||
if (newBlock instanceof IBogeyBlock bogey) {
|
|
||||||
BlockState matchingBogey = bogey.getMatchingBogey(bogeyUpDirection, trackAxisAlongFirstCoordinate);
|
|
||||||
if (matchingBogey != null)
|
|
||||||
return matchingBogey.hasProperty(WATERLOGGED)
|
|
||||||
? matchingBogey.setValue(WATERLOGGED, state.getValue(WATERLOGGED))
|
|
||||||
: matchingBogey;
|
|
||||||
}
|
|
||||||
index = (index + 1) % BOGEYS.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -25,6 +25,7 @@ import net.minecraft.resources.ResourceKey;
|
||||||
import net.minecraft.server.level.ServerLevel;
|
import net.minecraft.server.level.ServerLevel;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
import net.minecraft.world.level.BlockGetter;
|
||||||
import net.minecraft.world.level.Level;
|
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.level.block.state.BlockState;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
@ -85,20 +86,38 @@ public interface ITrackBlock {
|
||||||
Function<Vec3, Integer> yOffsetFactory = v -> getYOffsetAt(world, pos, state, v);
|
Function<Vec3, Integer> yOffsetFactory = v -> getYOffsetAt(world, pos, state, v);
|
||||||
|
|
||||||
addToListIfConnected(connectedTo, list, offsetFactory, b -> shape.getNormal(), dimensionFactory,
|
addToListIfConnected(connectedTo, list, offsetFactory, b -> shape.getNormal(), dimensionFactory,
|
||||||
yOffsetFactory, axis, null);
|
yOffsetFactory, axis, null, (b, v) -> getMaterialSimple(world, v));
|
||||||
});
|
});
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TrackMaterial getMaterialSimple(BlockGetter world, Vec3 pos) {
|
||||||
|
return getMaterialSimple(world, pos, TrackMaterial.ANDESITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TrackMaterial getMaterialSimple(BlockGetter world, Vec3 pos, TrackMaterial defaultMaterial) {
|
||||||
|
if (defaultMaterial == null)
|
||||||
|
defaultMaterial = TrackMaterial.ANDESITE;
|
||||||
|
if (world != null) {
|
||||||
|
Block block = world.getBlockState(new BlockPos(pos)).getBlock();
|
||||||
|
if (block instanceof ITrackBlock track) {
|
||||||
|
return track.getMaterial();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
public static void addToListIfConnected(@Nullable TrackNodeLocation fromEnd, Collection<DiscoveredLocation> list,
|
public static void addToListIfConnected(@Nullable TrackNodeLocation fromEnd, Collection<DiscoveredLocation> list,
|
||||||
BiFunction<Double, Boolean, Vec3> offsetFactory, Function<Boolean, Vec3> normalFactory,
|
BiFunction<Double, Boolean, Vec3> offsetFactory, Function<Boolean, Vec3> normalFactory,
|
||||||
Function<Boolean, ResourceKey<Level>> dimensionFactory, Function<Vec3, Integer> yOffsetFactory, Vec3 axis,
|
Function<Boolean, ResourceKey<Level>> dimensionFactory, Function<Vec3, Integer> yOffsetFactory, Vec3 axis,
|
||||||
BezierConnection viaTurn) {
|
BezierConnection viaTurn, BiFunction<Boolean, Vec3, TrackMaterial> materialFactory) {
|
||||||
|
|
||||||
Vec3 firstOffset = offsetFactory.apply(0.5d, true);
|
Vec3 firstOffset = offsetFactory.apply(0.5d, true);
|
||||||
DiscoveredLocation firstLocation =
|
DiscoveredLocation firstLocation =
|
||||||
new DiscoveredLocation(dimensionFactory.apply(true), firstOffset).viaTurn(viaTurn)
|
new DiscoveredLocation(dimensionFactory.apply(true), firstOffset).viaTurn(viaTurn)
|
||||||
|
.materialA(materialFactory.apply(true, offsetFactory.apply(0.0d, true)))
|
||||||
|
.materialB(materialFactory.apply(true, offsetFactory.apply(1.0d, true)))
|
||||||
.withNormal(normalFactory.apply(true))
|
.withNormal(normalFactory.apply(true))
|
||||||
.withDirection(axis)
|
.withDirection(axis)
|
||||||
.withYOffset(yOffsetFactory.apply(firstOffset));
|
.withYOffset(yOffsetFactory.apply(firstOffset));
|
||||||
|
@ -106,6 +125,8 @@ public interface ITrackBlock {
|
||||||
Vec3 secondOffset = offsetFactory.apply(0.5d, false);
|
Vec3 secondOffset = offsetFactory.apply(0.5d, false);
|
||||||
DiscoveredLocation secondLocation =
|
DiscoveredLocation secondLocation =
|
||||||
new DiscoveredLocation(dimensionFactory.apply(false), secondOffset).viaTurn(viaTurn)
|
new DiscoveredLocation(dimensionFactory.apply(false), secondOffset).viaTurn(viaTurn)
|
||||||
|
.materialA(materialFactory.apply(false, offsetFactory.apply(0.0d, false)))
|
||||||
|
.materialB(materialFactory.apply(false, offsetFactory.apply(1.0d, false)))
|
||||||
.withNormal(normalFactory.apply(false))
|
.withNormal(normalFactory.apply(false))
|
||||||
.withDirection(axis)
|
.withDirection(axis)
|
||||||
.withYOffset(yOffsetFactory.apply(secondOffset));
|
.withYOffset(yOffsetFactory.apply(secondOffset));
|
||||||
|
@ -169,4 +190,6 @@ public interface ITrackBlock {
|
||||||
.normalize()) < 0 ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE);
|
.normalize()) < 0 ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TrackMaterial getMaterial();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains;
|
||||||
|
|
||||||
|
import static com.simibubi.create.AllPartialModels.BOGEY_DRIVE;
|
||||||
|
import static com.simibubi.create.AllPartialModels.BOGEY_FRAME;
|
||||||
|
import static com.simibubi.create.AllPartialModels.BOGEY_PIN;
|
||||||
|
import static com.simibubi.create.AllPartialModels.BOGEY_PISTON;
|
||||||
|
import static com.simibubi.create.AllPartialModels.LARGE_BOGEY_WHEELS;
|
||||||
|
import static com.simibubi.create.AllPartialModels.SMALL_BOGEY_WHEELS;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.MaterialManager;
|
||||||
|
import com.jozufozu.flywheel.util.transform.Transform;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock;
|
||||||
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
|
||||||
|
public class StandardBogeyRenderer {
|
||||||
|
public static class CommonStandardBogeyRenderer extends BogeyRenderer.CommonRenderer {
|
||||||
|
@Override
|
||||||
|
public void initialiseContraptionModelData(MaterialManager materialManager) {
|
||||||
|
createModelInstances(materialManager, AllBlocks.SHAFT.getDefaultState()
|
||||||
|
.setValue(ShaftBlock.AXIS, Direction.Axis.Z), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
|
||||||
|
boolean inInstancedContraption = vb == null;
|
||||||
|
Transform<?>[] shafts = getTransformsFromBlockState(AllBlocks.SHAFT.getDefaultState()
|
||||||
|
.setValue(ShaftBlock.AXIS, Direction.Axis.Z), ms, inInstancedContraption, 2);
|
||||||
|
for (int i : Iterate.zeroAndOne) {
|
||||||
|
shafts[i].translate(-.5f, .25f, i * -1)
|
||||||
|
.centre()
|
||||||
|
.rotateZ(wheelAngle)
|
||||||
|
.unCentre();
|
||||||
|
finalize(shafts[i], ms, light, vb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class SmallStandardBogeyRenderer extends BogeyRenderer {
|
||||||
|
@Override
|
||||||
|
public void initialiseContraptionModelData(MaterialManager materialManager) {
|
||||||
|
createModelInstances(materialManager, SMALL_BOGEY_WHEELS, 2);
|
||||||
|
createModelInstances(materialManager, BOGEY_FRAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BogeySizes.BogeySize getSize() {
|
||||||
|
return BogeySizes.SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
|
||||||
|
boolean inInstancedContraption = vb == null;
|
||||||
|
Transform<?> transform = getTransformFromPartial(BOGEY_FRAME, ms, inInstancedContraption);
|
||||||
|
finalize(transform, ms, light, vb);
|
||||||
|
|
||||||
|
Transform<?>[] wheels = getTransformsFromPartial(SMALL_BOGEY_WHEELS, ms, inInstancedContraption, 2);
|
||||||
|
for (int side : Iterate.positiveAndNegative) {
|
||||||
|
if (!inInstancedContraption)
|
||||||
|
ms.pushPose();
|
||||||
|
Transform<?> wheel = wheels[(side + 1)/2];
|
||||||
|
wheel.translate(0, 12 / 16f, side)
|
||||||
|
.rotateX(wheelAngle);
|
||||||
|
finalize(wheel, ms, light, vb);
|
||||||
|
if (!inInstancedContraption)
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LargeStandardBogeyRenderer extends BogeyRenderer {
|
||||||
|
@Override
|
||||||
|
public void initialiseContraptionModelData(MaterialManager materialManager) {
|
||||||
|
createModelInstances(materialManager, LARGE_BOGEY_WHEELS, BOGEY_DRIVE, BOGEY_PISTON, BOGEY_PIN);
|
||||||
|
createModelInstances(materialManager, AllBlocks.SHAFT.getDefaultState()
|
||||||
|
.setValue(ShaftBlock.AXIS, Direction.Axis.X), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BogeySizes.BogeySize getSize() {
|
||||||
|
return BogeySizes.LARGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
|
||||||
|
boolean inInstancedContraption = vb == null;
|
||||||
|
|
||||||
|
Transform<?>[] secondaryShafts = getTransformsFromBlockState(AllBlocks.SHAFT.getDefaultState()
|
||||||
|
.setValue(ShaftBlock.AXIS, Direction.Axis.X), ms, inInstancedContraption, 2);
|
||||||
|
|
||||||
|
for (int i : Iterate.zeroAndOne) {
|
||||||
|
Transform<?> secondShaft = secondaryShafts[i];
|
||||||
|
secondShaft.translate(-.5f, .25f, .5f + i * -2)
|
||||||
|
.centre()
|
||||||
|
.rotateX(wheelAngle)
|
||||||
|
.unCentre();
|
||||||
|
finalize(secondShaft, ms, light, vb);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform<?> bogeyDrive = getTransformFromPartial(BOGEY_DRIVE, ms, inInstancedContraption);
|
||||||
|
finalize(bogeyDrive, ms, light, vb);
|
||||||
|
|
||||||
|
Transform<?> bogeyPiston = getTransformFromPartial(BOGEY_PISTON, ms, inInstancedContraption)
|
||||||
|
.translate(0, 0, 1 / 4f * Math.sin(AngleHelper.rad(wheelAngle)));
|
||||||
|
finalize(bogeyPiston, ms, light, vb);
|
||||||
|
|
||||||
|
if (!inInstancedContraption)
|
||||||
|
ms.pushPose();
|
||||||
|
|
||||||
|
Transform<?> bogeyWheels = getTransformFromPartial(LARGE_BOGEY_WHEELS, ms, inInstancedContraption)
|
||||||
|
.translate(0, 1, 0)
|
||||||
|
.rotateX(wheelAngle);
|
||||||
|
finalize(bogeyWheels, ms, light, vb);
|
||||||
|
|
||||||
|
Transform<?> bogeyPin = getTransformFromPartial(BOGEY_PIN, ms, inInstancedContraption)
|
||||||
|
.translate(0, 1, 0)
|
||||||
|
.rotateX(wheelAngle)
|
||||||
|
.translate(0, 1 / 4f, 0)
|
||||||
|
.rotateX(-wheelAngle);
|
||||||
|
finalize(bogeyPin, ms, light, vb);
|
||||||
|
|
||||||
|
if (!inInstancedContraption)
|
||||||
|
ms.popPose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,13 +24,19 @@ public class TrackEdge {
|
||||||
BezierConnection turn;
|
BezierConnection turn;
|
||||||
EdgeData edgeData;
|
EdgeData edgeData;
|
||||||
boolean interDimensional;
|
boolean interDimensional;
|
||||||
|
TrackMaterial trackMaterial;
|
||||||
|
|
||||||
public TrackEdge(TrackNode node1, TrackNode node2, BezierConnection turn) {
|
public TrackEdge(TrackNode node1, TrackNode node2, BezierConnection turn, TrackMaterial trackMaterial) {
|
||||||
this.interDimensional = !node1.location.dimension.equals(node2.location.dimension);
|
this.interDimensional = !node1.location.dimension.equals(node2.location.dimension);
|
||||||
this.edgeData = new EdgeData(this);
|
this.edgeData = new EdgeData(this);
|
||||||
this.node1 = node1;
|
this.node1 = node1;
|
||||||
this.node2 = node2;
|
this.node2 = node2;
|
||||||
this.turn = turn;
|
this.turn = turn;
|
||||||
|
this.trackMaterial = trackMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterial getTrackMaterial() {
|
||||||
|
return trackMaterial;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTurn() {
|
public boolean isTurn() {
|
||||||
|
@ -230,13 +236,15 @@ public class TrackEdge {
|
||||||
public CompoundTag write(DimensionPalette dimensions) {
|
public CompoundTag write(DimensionPalette dimensions) {
|
||||||
CompoundTag baseCompound = isTurn() ? turn.write(BlockPos.ZERO) : new CompoundTag();
|
CompoundTag baseCompound = isTurn() ? turn.write(BlockPos.ZERO) : new CompoundTag();
|
||||||
baseCompound.put("Signals", edgeData.write(dimensions));
|
baseCompound.put("Signals", edgeData.write(dimensions));
|
||||||
|
baseCompound.putString("Material", getTrackMaterial().id.toString());
|
||||||
return baseCompound;
|
return baseCompound;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TrackEdge read(TrackNode node1, TrackNode node2, CompoundTag tag, TrackGraph graph,
|
public static TrackEdge read(TrackNode node1, TrackNode node2, CompoundTag tag, TrackGraph graph,
|
||||||
DimensionPalette dimensions) {
|
DimensionPalette dimensions) {
|
||||||
TrackEdge trackEdge =
|
TrackEdge trackEdge =
|
||||||
new TrackEdge(node1, node2, tag.contains("Positions") ? new BezierConnection(tag, BlockPos.ZERO) : null);
|
new TrackEdge(node1, node2, tag.contains("Positions") ? new BezierConnection(tag, BlockPos.ZERO) : null,
|
||||||
|
TrackMaterial.deserialize(tag.getString("Material")));
|
||||||
trackEdge.edgeData = EdgeData.read(tag.getCompound("Signals"), trackEdge, graph, dimensions);
|
trackEdge.edgeData = EdgeData.read(tag.getCompound("Signals"), trackEdge, graph, dimensions);
|
||||||
return trackEdge;
|
return trackEdge;
|
||||||
}
|
}
|
||||||
|
|
|
@ -393,14 +393,15 @@ public class TrackGraph {
|
||||||
return connectionsFrom.get(nodes.getSecond());
|
return connectionsFrom.get(nodes.getSecond());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connectNodes(LevelAccessor reader, TrackNodeLocation location, TrackNodeLocation location2,
|
public void connectNodes(LevelAccessor reader, DiscoveredLocation location, DiscoveredLocation location2,
|
||||||
@Nullable BezierConnection turn) {
|
@Nullable BezierConnection turn) {
|
||||||
TrackNode node1 = nodes.get(location);
|
TrackNode node1 = nodes.get(location);
|
||||||
TrackNode node2 = nodes.get(location2);
|
TrackNode node2 = nodes.get(location2);
|
||||||
|
|
||||||
boolean bezier = turn != null;
|
boolean bezier = turn != null;
|
||||||
TrackEdge edge = new TrackEdge(node1, node2, turn);
|
TrackMaterial material = bezier ? turn.getMaterial() : location2.materialA;
|
||||||
TrackEdge edge2 = new TrackEdge(node2, node1, bezier ? turn.secondary() : null);
|
TrackEdge edge = new TrackEdge(node1, node2, turn, material);
|
||||||
|
TrackEdge edge2 = new TrackEdge(node2, node1, bezier ? turn.secondary() : null, material);
|
||||||
|
|
||||||
for (TrackGraph graph : Create.RAILWAYS.trackNetworks.values()) {
|
for (TrackGraph graph : Create.RAILWAYS.trackNetworks.values()) {
|
||||||
for (TrackNode otherNode1 : graph.nodes.values()) {
|
for (TrackNode otherNode1 : graph.nodes.values()) {
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class TrackGraphSync {
|
||||||
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(Pair.of(Couple.create(node1.getNetId(), node2.getNetId()), edge.getTrackMaterial()), edge.getTurn()));
|
||||||
currentPayload++;
|
currentPayload++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ public class TrackGraphSync {
|
||||||
if (currentGraphSyncPacket.addedNodes.remove(nodeId) == null)
|
if (currentGraphSyncPacket.addedNodes.remove(nodeId) == null)
|
||||||
currentGraphSyncPacket.removedNodes.add(nodeId);
|
currentGraphSyncPacket.removedNodes.add(nodeId);
|
||||||
currentGraphSyncPacket.addedEdges.removeIf(pair -> {
|
currentGraphSyncPacket.addedEdges.removeIf(pair -> {
|
||||||
Couple<Integer> ids = pair.getFirst();
|
Couple<Integer> ids = pair.getFirst().getFirst();
|
||||||
return ids.getFirst()
|
return ids.getFirst()
|
||||||
.intValue() == nodeId
|
.intValue() == nodeId
|
||||||
|| ids.getSecond()
|
|| ids.getSecond()
|
||||||
|
@ -156,7 +156,7 @@ public class TrackGraphSync {
|
||||||
graph.connectionsByNode.get(node)
|
graph.connectionsByNode.get(node)
|
||||||
.forEach((node2, edge) -> {
|
.forEach((node2, edge) -> {
|
||||||
Couple<Integer> key = Couple.create(node.getNetId(), node2.getNetId());
|
Couple<Integer> key = Couple.create(node.getNetId(), node2.getNetId());
|
||||||
currentPacket.addedEdges.add(Pair.of(key, edge.getTurn()));
|
currentPacket.addedEdges.add(Pair.of(Pair.of(key, edge.getTrackMaterial()), edge.getTurn()));
|
||||||
currentPacket.syncEdgeData(node, node2, edge);
|
currentPacket.syncEdgeData(node, node2, edge);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import net.minecraft.world.phys.Vec3;
|
||||||
public class TrackGraphSyncPacket extends TrackGraphPacket {
|
public class TrackGraphSyncPacket extends TrackGraphPacket {
|
||||||
|
|
||||||
Map<Integer, Pair<TrackNodeLocation, Vec3>> addedNodes;
|
Map<Integer, Pair<TrackNodeLocation, Vec3>> addedNodes;
|
||||||
List<Pair<Couple<Integer>, BezierConnection>> addedEdges;
|
List<Pair<Pair<Couple<Integer>, TrackMaterial>, BezierConnection>> addedEdges;
|
||||||
List<Integer> removedNodes;
|
List<Integer> removedNodes;
|
||||||
List<TrackEdgePoint> addedEdgePoints;
|
List<TrackEdgePoint> addedEdgePoints;
|
||||||
List<UUID> removedEdgePoints;
|
List<UUID> removedEdgePoints;
|
||||||
|
@ -79,7 +79,7 @@ public class TrackGraphSyncPacket extends TrackGraphPacket {
|
||||||
size = buffer.readVarInt();
|
size = buffer.readVarInt();
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
addedEdges.add(
|
addedEdges.add(
|
||||||
Pair.of(Couple.create(buffer::readVarInt), buffer.readBoolean() ? new BezierConnection(buffer) : null));
|
Pair.of(Pair.of(Couple.create(buffer::readVarInt), TrackMaterial.deserialize(buffer.readUtf())), buffer.readBoolean() ? new BezierConnection(buffer) : null));
|
||||||
|
|
||||||
size = buffer.readVarInt();
|
size = buffer.readVarInt();
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
|
@ -134,8 +134,9 @@ public class TrackGraphSyncPacket extends TrackGraphPacket {
|
||||||
|
|
||||||
buffer.writeVarInt(addedEdges.size());
|
buffer.writeVarInt(addedEdges.size());
|
||||||
addedEdges.forEach(pair -> {
|
addedEdges.forEach(pair -> {
|
||||||
pair.getFirst()
|
pair.getFirst().getFirst()
|
||||||
.forEach(buffer::writeVarInt);
|
.forEach(buffer::writeVarInt);
|
||||||
|
buffer.writeUtf(pair.getFirst().getSecond().id.toString());
|
||||||
BezierConnection turn = pair.getSecond();
|
BezierConnection turn = pair.getSecond();
|
||||||
buffer.writeBoolean(turn != null);
|
buffer.writeBoolean(turn != null);
|
||||||
if (turn != null)
|
if (turn != null)
|
||||||
|
@ -192,13 +193,13 @@ public class TrackGraphSyncPacket extends TrackGraphPacket {
|
||||||
graph.loadNode(nodeLocation.getFirst(), nodeId, nodeLocation.getSecond());
|
graph.loadNode(nodeLocation.getFirst(), nodeId, nodeLocation.getSecond());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Pair<Couple<Integer>, BezierConnection> pair : addedEdges) {
|
for (Pair<Pair<Couple<Integer>, TrackMaterial>, BezierConnection> pair : addedEdges) {
|
||||||
Couple<TrackNode> nodes = pair.getFirst()
|
Couple<TrackNode> nodes = pair.getFirst().getFirst()
|
||||||
.map(graph::getNode);
|
.map(graph::getNode);
|
||||||
TrackNode node1 = nodes.getFirst();
|
TrackNode node1 = nodes.getFirst();
|
||||||
TrackNode node2 = nodes.getSecond();
|
TrackNode node2 = nodes.getSecond();
|
||||||
if (node1 != null && node2 != null)
|
if (node1 != null && node2 != null)
|
||||||
graph.putConnection(node1, node2, new TrackEdge(node1, node2, pair.getSecond()));
|
graph.putConnection(node1, node2, new TrackEdge(node1, node2, pair.getSecond(), pair.getFirst().getSecond()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TrackEdgePoint edgePoint : addedEdgePoints)
|
for (TrackEdgePoint edgePoint : addedEdgePoints)
|
||||||
|
|
|
@ -37,7 +37,6 @@ public class TrackGraphVisualizer {
|
||||||
|
|
||||||
Vec3 camera = cameraEntity.getEyePosition();
|
Vec3 camera = cameraEntity.getEyePosition();
|
||||||
Outliner outliner = CreateClient.OUTLINER;
|
Outliner outliner = CreateClient.OUTLINER;
|
||||||
boolean ctrl = false; // AllKeys.isKeyDown(GLFW.GLFW_KEY_LEFT_CONTROL);
|
|
||||||
Map<UUID, SignalEdgeGroup> allGroups = Create.RAILWAYS.sided(null).signalEdgeGroups;
|
Map<UUID, SignalEdgeGroup> allGroups = Create.RAILWAYS.sided(null).signalEdgeGroups;
|
||||||
float width = 1 / 8f;
|
float width = 1 / 8f;
|
||||||
|
|
||||||
|
@ -213,7 +212,7 @@ public class TrackGraphVisualizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void debugViewGraph(TrackGraph graph) {
|
public static void debugViewGraph(TrackGraph graph, boolean extended) {
|
||||||
Minecraft mc = Minecraft.getInstance();
|
Minecraft mc = Minecraft.getInstance();
|
||||||
Entity cameraEntity = mc.cameraEntity;
|
Entity cameraEntity = mc.cameraEntity;
|
||||||
if (cameraEntity == null)
|
if (cameraEntity == null)
|
||||||
|
@ -266,6 +265,17 @@ public class TrackGraphVisualizer {
|
||||||
|
|
||||||
yOffset = new Vec3(0, (other.hashCode() > hashCode ? 6 : 4) / 16f, 0);
|
yOffset = new Vec3(0, (other.hashCode() > hashCode ? 6 : 4) / 16f, 0);
|
||||||
if (!edge.isTurn()) {
|
if (!edge.isTurn()) {
|
||||||
|
if (extended) {
|
||||||
|
Vec3 materialPos = edge.getPosition(graph, 0.5)
|
||||||
|
.add(0, 1, 0);
|
||||||
|
CreateClient.OUTLINER.showItem(Pair.of(edge, edge.edgeData), materialPos,
|
||||||
|
edge.getTrackMaterial()
|
||||||
|
.asStack());
|
||||||
|
CreateClient.OUTLINER.showAABB(edge.edgeData, AABB.ofSize(materialPos, .25, 0, .25)
|
||||||
|
.move(0, -0.5, 0))
|
||||||
|
.lineWidth(1 / 16f)
|
||||||
|
.colored(graph.color);
|
||||||
|
}
|
||||||
CreateClient.OUTLINER.showLine(edge, edge.getPosition(graph, 0)
|
CreateClient.OUTLINER.showLine(edge, edge.getPosition(graph, 0)
|
||||||
.add(yOffset),
|
.add(yOffset),
|
||||||
edge.getPosition(graph, 1)
|
edge.getPosition(graph, 1)
|
||||||
|
@ -277,6 +287,16 @@ public class TrackGraphVisualizer {
|
||||||
|
|
||||||
Vec3 previous = null;
|
Vec3 previous = null;
|
||||||
BezierConnection turn = edge.getTurn();
|
BezierConnection turn = edge.getTurn();
|
||||||
|
if (extended) {
|
||||||
|
Vec3 materialPos = edge.getPosition(graph, 0.5)
|
||||||
|
.add(0, 1, 0);
|
||||||
|
CreateClient.OUTLINER.showItem(Pair.of(edge, edge.edgeData), materialPos, edge.getTrackMaterial()
|
||||||
|
.asStack());
|
||||||
|
CreateClient.OUTLINER.showAABB(edge.edgeData, AABB.ofSize(materialPos, .25, 0, .25)
|
||||||
|
.move(0, -0.5, 0))
|
||||||
|
.lineWidth(1 / 16f)
|
||||||
|
.colored(graph.color);
|
||||||
|
}
|
||||||
for (int i = 0; i <= turn.getSegmentCount(); i++) {
|
for (int i = 0; i <= turn.getSegmentCount(); i++) {
|
||||||
Vec3 current = edge.getPosition(graph, i * 1f / turn.getSegmentCount());
|
Vec3 current = edge.getPosition(graph, i * 1f / turn.getSegmentCount());
|
||||||
if (previous != null)
|
if (previous != null)
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains;
|
||||||
|
|
||||||
|
import static com.simibubi.create.content.logistics.trains.TrackMaterialFactory.make;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.core.PartialModel;
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.AllPartialModels;
|
||||||
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.content.logistics.trains.track.TrackBlock;
|
||||||
|
import com.tterrag.registrate.util.nullness.NonNullSupplier;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.BlockItem;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
|
|
||||||
|
public class TrackMaterial {
|
||||||
|
public static final Map<ResourceLocation, TrackMaterial> ALL = new HashMap<>();
|
||||||
|
|
||||||
|
public static final TrackMaterial ANDESITE = make(Create.asResource("andesite"))
|
||||||
|
.lang("Andesite")
|
||||||
|
.block(NonNullSupplier.lazy(() -> AllBlocks.TRACK))
|
||||||
|
.particle(Create.asResource("block/palettes/stone_types/polished/andesite_cut_polished"))
|
||||||
|
.defaultModels()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public final ResourceLocation id;
|
||||||
|
public final String langName;
|
||||||
|
public final NonNullSupplier<NonNullSupplier<? extends TrackBlock>> trackBlock;
|
||||||
|
public final Ingredient sleeperIngredient;
|
||||||
|
public final Ingredient railsIngredient;
|
||||||
|
public final ResourceLocation particle;
|
||||||
|
public final TrackType trackType;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final TrackMaterial.TrackType.TrackBlockFactory customFactory;
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
protected TrackModelHolder modelHolder;
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public TrackModelHolder getModelHolder() {
|
||||||
|
return modelHolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterial(ResourceLocation id, String langName, NonNullSupplier<NonNullSupplier<? extends TrackBlock>> trackBlock,
|
||||||
|
ResourceLocation particle, Ingredient sleeperIngredient, Ingredient railsIngredient,
|
||||||
|
TrackType trackType, Supplier<Supplier<TrackModelHolder>> modelHolder) {
|
||||||
|
this(id, langName, trackBlock, particle, sleeperIngredient, railsIngredient, trackType, modelHolder, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterial(ResourceLocation id, String langName, NonNullSupplier<NonNullSupplier<? extends TrackBlock>> trackBlock,
|
||||||
|
ResourceLocation particle, Ingredient sleeperIngredient, Ingredient railsIngredient,
|
||||||
|
TrackType trackType, Supplier<Supplier<TrackModelHolder>> modelHolder,
|
||||||
|
@Nullable TrackType.TrackBlockFactory customFactory) {
|
||||||
|
this.id = id;
|
||||||
|
this.langName = langName;
|
||||||
|
this.trackBlock = trackBlock;
|
||||||
|
this.sleeperIngredient = sleeperIngredient;
|
||||||
|
this.railsIngredient = railsIngredient;
|
||||||
|
this.particle = particle;
|
||||||
|
this.trackType = trackType;
|
||||||
|
this.customFactory = customFactory;
|
||||||
|
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.modelHolder = modelHolder.get().get());
|
||||||
|
ALL.put(this.id, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NonNullSupplier<? extends TrackBlock> getBlockSupplier() {
|
||||||
|
return this.trackBlock.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackBlock getBlock() {
|
||||||
|
return getBlockSupplier().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack asStack() {
|
||||||
|
return asStack(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack asStack(int count) {
|
||||||
|
return new ItemStack(getBlock(), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackBlock createBlock(BlockBehaviour.Properties properties) {
|
||||||
|
return (this.customFactory != null ? this.customFactory : this.trackType.factory)
|
||||||
|
.create(properties, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFromMod(String modId) {
|
||||||
|
return this.id.getNamespace().equals(modId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<TrackMaterial> allFromMod(String modid) {
|
||||||
|
return ALL.values().stream().filter(tm -> tm.isFromMod(modid)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<NonNullSupplier<? extends Block>> allBlocksFromMod(String modid) {
|
||||||
|
List<NonNullSupplier<? extends Block>> list = new ArrayList<>();
|
||||||
|
for (TrackMaterial material : allFromMod(modid)) {
|
||||||
|
list.add(material.getBlockSupplier());
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<NonNullSupplier<? extends Block>> allBlocks() {
|
||||||
|
List<NonNullSupplier<? extends Block>> list = new ArrayList<>();
|
||||||
|
for (TrackMaterial material : ALL.values()) {
|
||||||
|
list.add(material.getBlockSupplier());
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String resourceName() {
|
||||||
|
return this.id.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TrackMaterial deserialize(String serializedName) {
|
||||||
|
if (serializedName.isBlank()) // Data migrating from 0.5
|
||||||
|
return ANDESITE;
|
||||||
|
|
||||||
|
ResourceLocation id = ResourceLocation.tryParse(serializedName);
|
||||||
|
if (ALL.containsKey(id))
|
||||||
|
return ALL.get(id);
|
||||||
|
|
||||||
|
Create.LOGGER.error("Failed to locate serialized track material: " + serializedName);
|
||||||
|
return ANDESITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TrackType {
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface TrackBlockFactory {
|
||||||
|
TrackBlock create(BlockBehaviour.Properties properties, TrackMaterial material);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final TrackType STANDARD = new TrackType(Create.asResource("standard"), TrackBlock::new);
|
||||||
|
|
||||||
|
public final ResourceLocation id;
|
||||||
|
protected final TrackBlockFactory factory;
|
||||||
|
|
||||||
|
public TrackType(ResourceLocation id, TrackBlockFactory factory) {
|
||||||
|
this.id = id;
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TrackMaterial fromItem(Item item) {
|
||||||
|
if (item instanceof BlockItem blockItem && blockItem.getBlock() instanceof ITrackBlock trackBlock)
|
||||||
|
return trackBlock.getMaterial();
|
||||||
|
return TrackMaterial.ANDESITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public record TrackModelHolder(PartialModel tie, PartialModel segment_left, PartialModel segment_right) {
|
||||||
|
static final TrackModelHolder DEFAULT = new TrackModelHolder(AllPartialModels.TRACK_TIE,
|
||||||
|
AllPartialModels.TRACK_SEGMENT_LEFT, AllPartialModels.TRACK_SEGMENT_RIGHT);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.core.PartialModel;
|
||||||
|
import com.simibubi.create.AllTags;
|
||||||
|
import com.simibubi.create.content.logistics.trains.track.TrackBlock;
|
||||||
|
import com.tterrag.registrate.util.nullness.NonNullSupplier;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.crafting.Ingredient;
|
||||||
|
import net.minecraft.world.level.ItemLike;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.fml.DistExecutor;
|
||||||
|
|
||||||
|
public class TrackMaterialFactory {
|
||||||
|
private final ResourceLocation id;
|
||||||
|
private String langName;
|
||||||
|
private NonNullSupplier<NonNullSupplier<? extends TrackBlock>> trackBlock;
|
||||||
|
private Ingredient sleeperIngredient = Ingredient.EMPTY;
|
||||||
|
private Ingredient railsIngredient = Ingredient.fromValues(Stream.of(new Ingredient.TagValue(AllTags.forgeItemTag("nuggets/iron")), new Ingredient.TagValue(AllTags.forgeItemTag("nuggets/zinc"))));
|
||||||
|
private ResourceLocation particle;
|
||||||
|
private TrackMaterial.TrackType trackType = TrackMaterial.TrackType.STANDARD;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private TrackMaterial.TrackType.TrackBlockFactory customFactory = null;
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
private TrackMaterial.TrackModelHolder modelHolder;
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
private PartialModel tieModel;
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
private PartialModel leftSegmentModel;
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
private PartialModel rightSegmentModel;
|
||||||
|
|
||||||
|
public TrackMaterialFactory(ResourceLocation id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TrackMaterialFactory make(ResourceLocation id) { // Convenience function for static import
|
||||||
|
return new TrackMaterialFactory(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory lang(String langName) {
|
||||||
|
this.langName = langName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory block(NonNullSupplier<NonNullSupplier<? extends TrackBlock>> trackBlock) {
|
||||||
|
this.trackBlock = trackBlock;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory defaultModels() { // was setBuiltin
|
||||||
|
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.modelHolder = TrackMaterial.TrackModelHolder.DEFAULT);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory sleeper(Ingredient sleeperIngredient) {
|
||||||
|
this.sleeperIngredient = sleeperIngredient;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory sleeper(ItemLike... items) {
|
||||||
|
this.sleeperIngredient = Ingredient.of(items);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory rails(Ingredient railsIngredient) {
|
||||||
|
this.railsIngredient = railsIngredient;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory rails(ItemLike... items) {
|
||||||
|
this.railsIngredient = Ingredient.of(items);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory noRecipeGen() {
|
||||||
|
this.railsIngredient = Ingredient.EMPTY;
|
||||||
|
this.sleeperIngredient = Ingredient.EMPTY;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory particle(ResourceLocation particle) {
|
||||||
|
this.particle = particle;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory trackType(TrackMaterial.TrackType trackType) {
|
||||||
|
this.trackType = trackType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory standardModels() { // was defaultModels
|
||||||
|
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||||
|
String namespace = id.getNamespace();
|
||||||
|
String prefix = "block/track/" + id.getPath() + "/";
|
||||||
|
tieModel = new PartialModel(new ResourceLocation(namespace, prefix + "tie"));
|
||||||
|
leftSegmentModel = new PartialModel(new ResourceLocation(namespace, prefix + "segment_left"));
|
||||||
|
rightSegmentModel = new PartialModel(new ResourceLocation(namespace, prefix + "segment_right"));
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory customModels(Supplier<Supplier<PartialModel>> tieModel, Supplier<Supplier<PartialModel>> leftSegmentModel, Supplier<Supplier<PartialModel>> rightSegmentModel) {
|
||||||
|
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||||
|
this.tieModel = tieModel.get().get();
|
||||||
|
this.leftSegmentModel = leftSegmentModel.get().get();
|
||||||
|
this.rightSegmentModel = rightSegmentModel.get().get();
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterialFactory customBlockFactory(TrackMaterial.TrackType.TrackBlockFactory factory) {
|
||||||
|
this.customFactory = factory;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackMaterial build() {
|
||||||
|
assert trackBlock != null;
|
||||||
|
assert langName != null;
|
||||||
|
assert particle != null;
|
||||||
|
assert trackType != null;
|
||||||
|
assert sleeperIngredient != null;
|
||||||
|
assert railsIngredient != null;
|
||||||
|
assert id != null;
|
||||||
|
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
|
||||||
|
assert modelHolder != null;
|
||||||
|
if (tieModel != null || leftSegmentModel != null || rightSegmentModel != null) {
|
||||||
|
assert tieModel != null && leftSegmentModel != null && rightSegmentModel != null;
|
||||||
|
modelHolder = new TrackMaterial.TrackModelHolder(tieModel, leftSegmentModel, rightSegmentModel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return new TrackMaterial(id, langName, trackBlock, particle, sleeperIngredient, railsIngredient, trackType, () -> () -> modelHolder, customFactory);
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,8 +25,8 @@ public class TrackNodeLocation extends Vec3i {
|
||||||
this(vec.x, vec.y, vec.z);
|
this(vec.x, vec.y, vec.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TrackNodeLocation(double p_121865_, double p_121866_, double p_121867_) {
|
public TrackNodeLocation(double x, double y, double z) {
|
||||||
super(Math.round(p_121865_ * 2), Math.floor(p_121866_) * 2, Math.round(p_121867_ * 2));
|
super(Math.round(x * 2), Math.floor(y) * 2, Math.round(z * 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TrackNodeLocation in(Level level) {
|
public TrackNodeLocation in(Level level) {
|
||||||
|
@ -122,9 +122,11 @@ public class TrackNodeLocation extends Vec3i {
|
||||||
boolean forceNode = false;
|
boolean forceNode = false;
|
||||||
Vec3 direction;
|
Vec3 direction;
|
||||||
Vec3 normal;
|
Vec3 normal;
|
||||||
|
TrackMaterial materialA;
|
||||||
|
TrackMaterial materialB;
|
||||||
|
|
||||||
public DiscoveredLocation(Level level, double p_121865_, double p_121866_, double p_121867_) {
|
public DiscoveredLocation(Level level, double x, double y, double z) {
|
||||||
super(p_121865_, p_121866_, p_121867_);
|
super(x, y, z);
|
||||||
in(level);
|
in(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +139,22 @@ public class TrackNodeLocation extends Vec3i {
|
||||||
this(level.dimension(), vec);
|
this(level.dimension(), vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DiscoveredLocation materialA(TrackMaterial material) {
|
||||||
|
this.materialA = material;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiscoveredLocation materialB(TrackMaterial material) {
|
||||||
|
this.materialB = material;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiscoveredLocation materials(TrackMaterial materialA, TrackMaterial materialB) {
|
||||||
|
this.materialA = materialA;
|
||||||
|
this.materialB = materialB;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public DiscoveredLocation viaTurn(BezierConnection turn) {
|
public DiscoveredLocation viaTurn(BezierConnection turn) {
|
||||||
this.turn = turn;
|
this.turn = turn;
|
||||||
if (turn != null)
|
if (turn != null)
|
||||||
|
@ -176,6 +194,10 @@ public class TrackNodeLocation extends Vec3i {
|
||||||
return forceNode;
|
return forceNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean differentMaterials() {
|
||||||
|
return materialA != materialB;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean notInLineWith(Vec3 direction) {
|
public boolean notInLineWith(Vec3 direction) {
|
||||||
return this.direction != null
|
return this.direction != null
|
||||||
&& Math.max(direction.dot(this.direction), direction.dot(this.direction.scale(-1))) < 7 / 8f;
|
&& Math.max(direction.dot(this.direction), direction.dot(this.direction.scale(-1))) < 7 / 8f;
|
||||||
|
|
|
@ -8,6 +8,7 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.api.event.TrackGraphMergeEvent;
|
||||||
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
|
import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation;
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalPropagator;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalPropagator;
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@ import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.level.LevelAccessor;
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
|
||||||
public class TrackPropagator {
|
public class TrackPropagator {
|
||||||
|
|
||||||
|
@ -135,6 +137,7 @@ public class TrackPropagator {
|
||||||
if (graph == null)
|
if (graph == null)
|
||||||
graph = other;
|
graph = other;
|
||||||
else {
|
else {
|
||||||
|
MinecraftForge.EVENT_BUS.post(new TrackGraphMergeEvent(other, graph));
|
||||||
other.transferAll(graph);
|
other.transferAll(graph);
|
||||||
manager.removeGraphAndGroup(other);
|
manager.removeGraphAndGroup(other);
|
||||||
sync.graphRemoved(other);
|
sync.graphRemoved(other);
|
||||||
|
@ -234,6 +237,8 @@ public class TrackPropagator {
|
||||||
return true;
|
return true;
|
||||||
if (location.shouldForceNode())
|
if (location.shouldForceNode())
|
||||||
return true;
|
return true;
|
||||||
|
if (location.differentMaterials())
|
||||||
|
return true;
|
||||||
if (next.stream()
|
if (next.stream()
|
||||||
.anyMatch(DiscoveredLocation::shouldForceNode))
|
.anyMatch(DiscoveredLocation::shouldForceNode))
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.entity;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.MaterialManager;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
import com.simibubi.create.content.logistics.trains.BogeyRenderer;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
|
||||||
|
public class BackupBogeyRenderer extends BogeyRenderer.CommonRenderer {
|
||||||
|
public static BackupBogeyRenderer INSTANCE = new BackupBogeyRenderer();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialiseContraptionModelData(MaterialManager materialManager) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,235 +1,69 @@
|
||||||
package com.simibubi.create.content.logistics.trains.entity;
|
package com.simibubi.create.content.logistics.trains.entity;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.Material;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.MaterialManager;
|
import com.jozufozu.flywheel.api.MaterialManager;
|
||||||
import com.jozufozu.flywheel.core.Materials;
|
|
||||||
import com.jozufozu.flywheel.core.materials.model.ModelData;
|
|
||||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.content.logistics.trains.BogeyRenderer;
|
||||||
import com.simibubi.create.AllPartialModels;
|
import com.simibubi.create.content.logistics.trains.BogeySizes;
|
||||||
import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock;
|
|
||||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.LightLayer;
|
import net.minecraft.world.level.LightLayer;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
public sealed class BogeyInstance {
|
public final class BogeyInstance {
|
||||||
|
private final BogeySizes.BogeySize size;
|
||||||
|
private final BogeyStyle style;
|
||||||
|
|
||||||
public final CarriageBogey bogey;
|
public final CarriageBogey bogey;
|
||||||
private final ModelData[] shafts;
|
public final BogeyRenderer renderer;
|
||||||
|
public final Optional<BogeyRenderer.CommonRenderer> commonRenderer;
|
||||||
|
|
||||||
protected BogeyInstance(CarriageBogey bogey, MaterialManager materialManager) {
|
public BogeyInstance(CarriageBogey bogey, BogeyStyle style, BogeySizes.BogeySize size,
|
||||||
|
MaterialManager materialManager) {
|
||||||
this.bogey = bogey;
|
this.bogey = bogey;
|
||||||
|
this.size = size;
|
||||||
|
this.style = style;
|
||||||
|
|
||||||
shafts = new ModelData[2];
|
this.renderer = this.style.createRendererInstance(this.size);
|
||||||
|
this.commonRenderer = this.style.getNewCommonRenderInstance();
|
||||||
materialManager.defaultSolid()
|
|
||||||
.material(Materials.TRANSFORMED)
|
|
||||||
.getModel(AllBlocks.SHAFT.getDefaultState()
|
|
||||||
.setValue(ShaftBlock.AXIS, Direction.Axis.Z))
|
|
||||||
.createInstances(shafts);
|
|
||||||
|
|
||||||
|
commonRenderer.ifPresent(bogeyRenderer -> bogeyRenderer.initialiseContraptionModelData(materialManager));
|
||||||
|
renderer.initialiseContraptionModelData(materialManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove() {
|
void hiddenFrame() {
|
||||||
for (ModelData shaft : shafts)
|
|
||||||
shaft.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hiddenFrame() {
|
|
||||||
beginFrame(0, null);
|
beginFrame(0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void beginFrame(float wheelAngle, PoseStack ms) {
|
public void beginFrame(float wheelAngle, PoseStack ms) {
|
||||||
if (ms == null) {
|
if (ms == null) {
|
||||||
for (int i : Iterate.zeroAndOne)
|
renderer.emptyTransforms();
|
||||||
shafts[i].setEmptyTransform();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i : Iterate.zeroAndOne)
|
commonRenderer.ifPresent(bogeyRenderer -> bogeyRenderer.render(bogey.bogeyData, wheelAngle, ms));
|
||||||
shafts[i].setTransform(ms)
|
renderer.render(bogey.bogeyData, wheelAngle, ms);
|
||||||
.translate(-.5f, .25f, i * -1)
|
|
||||||
.centre()
|
|
||||||
.rotateZ(wheelAngle)
|
|
||||||
.unCentre();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLight(BlockAndTintGetter world, CarriageContraptionEntity entity) {
|
public void updateLight(BlockAndTintGetter world, CarriageContraptionEntity entity) {
|
||||||
var lightPos = new BlockPos(getLightPos(entity));
|
var lightPos = new BlockPos(getLightPos(entity));
|
||||||
|
commonRenderer
|
||||||
updateLight(world.getBrightness(LightLayer.BLOCK, lightPos), world.getBrightness(LightLayer.SKY, lightPos));
|
.ifPresent(bogeyRenderer -> bogeyRenderer.updateLight(world.getBrightness(LightLayer.BLOCK, lightPos),
|
||||||
|
world.getBrightness(LightLayer.SKY, lightPos)));
|
||||||
|
renderer.updateLight(world.getBrightness(LightLayer.BLOCK, lightPos),
|
||||||
|
world.getBrightness(LightLayer.SKY, lightPos));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vec3 getLightPos(CarriageContraptionEntity entity) {
|
private Vec3 getLightPos(CarriageContraptionEntity entity) {
|
||||||
if (bogey.getAnchorPosition() != null) {
|
return bogey.getAnchorPosition() != null ? bogey.getAnchorPosition()
|
||||||
return bogey.getAnchorPosition();
|
: entity.getLightProbePosition(AnimationTickHolder.getPartialTicks());
|
||||||
} else {
|
|
||||||
return entity.getLightProbePosition(AnimationTickHolder.getPartialTicks());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLight(int blockLight, int skyLight) {
|
@FunctionalInterface
|
||||||
for (ModelData shaft : shafts) {
|
interface BogeyInstanceFactory {
|
||||||
shaft.setBlockLight(blockLight)
|
BogeyInstance create(CarriageBogey bogey, BogeySizes.BogeySize size, MaterialManager materialManager);
|
||||||
.setSkyLight(skyLight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Frame extends BogeyInstance {
|
|
||||||
|
|
||||||
private final ModelData frame;
|
|
||||||
private final ModelData[] wheels;
|
|
||||||
|
|
||||||
public Frame(CarriageBogey bogey, MaterialManager materialManager) {
|
|
||||||
super(bogey, materialManager);
|
|
||||||
|
|
||||||
frame = materialManager.defaultSolid()
|
|
||||||
.material(Materials.TRANSFORMED)
|
|
||||||
.getModel(AllPartialModels.BOGEY_FRAME)
|
|
||||||
.createInstance();
|
|
||||||
|
|
||||||
wheels = new ModelData[2];
|
|
||||||
|
|
||||||
materialManager.defaultSolid()
|
|
||||||
.material(Materials.TRANSFORMED)
|
|
||||||
.getModel(AllPartialModels.SMALL_BOGEY_WHEELS)
|
|
||||||
.createInstances(wheels);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beginFrame(float wheelAngle, PoseStack ms) {
|
|
||||||
super.beginFrame(wheelAngle, ms);
|
|
||||||
|
|
||||||
if (ms == null) {
|
|
||||||
frame.setEmptyTransform();
|
|
||||||
for (int side : Iterate.positiveAndNegative)
|
|
||||||
wheels[(side + 1) / 2].setEmptyTransform();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
frame.setTransform(ms);
|
|
||||||
|
|
||||||
for (int side : Iterate.positiveAndNegative) {
|
|
||||||
wheels[(side + 1) / 2].setTransform(ms)
|
|
||||||
.translate(0, 12 / 16f, side)
|
|
||||||
.rotateX(wheelAngle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateLight(int blockLight, int skyLight) {
|
|
||||||
super.updateLight(blockLight, skyLight);
|
|
||||||
frame.setBlockLight(blockLight)
|
|
||||||
.setSkyLight(skyLight);
|
|
||||||
for (ModelData wheel : wheels)
|
|
||||||
wheel.setBlockLight(blockLight)
|
|
||||||
.setSkyLight(skyLight);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
super.remove();
|
|
||||||
frame.delete();
|
|
||||||
for (ModelData wheel : wheels)
|
|
||||||
wheel.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Drive extends BogeyInstance {
|
|
||||||
|
|
||||||
private final ModelData[] secondShaft;
|
|
||||||
private final ModelData drive;
|
|
||||||
private final ModelData piston;
|
|
||||||
private final ModelData wheels;
|
|
||||||
private final ModelData pin;
|
|
||||||
|
|
||||||
public Drive(CarriageBogey bogey, MaterialManager materialManager) {
|
|
||||||
super(bogey, materialManager);
|
|
||||||
Material<ModelData> mat = materialManager.defaultSolid()
|
|
||||||
.material(Materials.TRANSFORMED);
|
|
||||||
|
|
||||||
secondShaft = new ModelData[2];
|
|
||||||
|
|
||||||
mat.getModel(AllBlocks.SHAFT.getDefaultState()
|
|
||||||
.setValue(ShaftBlock.AXIS, Direction.Axis.X))
|
|
||||||
.createInstances(secondShaft);
|
|
||||||
|
|
||||||
drive = mat.getModel(AllPartialModels.BOGEY_DRIVE)
|
|
||||||
.createInstance();
|
|
||||||
piston = mat.getModel(AllPartialModels.BOGEY_PISTON)
|
|
||||||
.createInstance();
|
|
||||||
wheels = mat.getModel(AllPartialModels.LARGE_BOGEY_WHEELS)
|
|
||||||
.createInstance();
|
|
||||||
pin = mat.getModel(AllPartialModels.BOGEY_PIN)
|
|
||||||
.createInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beginFrame(float wheelAngle, PoseStack ms) {
|
|
||||||
super.beginFrame(wheelAngle, ms);
|
|
||||||
|
|
||||||
if (ms == null) {
|
|
||||||
for (int i : Iterate.zeroAndOne)
|
|
||||||
secondShaft[i].setEmptyTransform();
|
|
||||||
drive.setEmptyTransform();
|
|
||||||
piston.setEmptyTransform();
|
|
||||||
wheels.setEmptyTransform();
|
|
||||||
pin.setEmptyTransform();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i : Iterate.zeroAndOne)
|
|
||||||
secondShaft[i].setTransform(ms)
|
|
||||||
.translate(-.5f, .25f, .5f + i * -2)
|
|
||||||
.centre()
|
|
||||||
.rotateX(wheelAngle)
|
|
||||||
.unCentre();
|
|
||||||
|
|
||||||
drive.setTransform(ms);
|
|
||||||
piston.setTransform(ms)
|
|
||||||
.translate(0, 0, 1 / 4f * Math.sin(AngleHelper.rad(wheelAngle)));
|
|
||||||
|
|
||||||
wheels.setTransform(ms)
|
|
||||||
.translate(0, 1, 0)
|
|
||||||
.rotateX(wheelAngle);
|
|
||||||
pin.setTransform(ms)
|
|
||||||
.translate(0, 1, 0)
|
|
||||||
.rotateX(wheelAngle)
|
|
||||||
.translate(0, 1 / 4f, 0)
|
|
||||||
.rotateX(-wheelAngle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateLight(int blockLight, int skyLight) {
|
|
||||||
super.updateLight(blockLight, skyLight);
|
|
||||||
for (ModelData shaft : secondShaft)
|
|
||||||
shaft.setBlockLight(blockLight)
|
|
||||||
.setSkyLight(skyLight);
|
|
||||||
drive.setBlockLight(blockLight)
|
|
||||||
.setSkyLight(skyLight);
|
|
||||||
piston.setBlockLight(blockLight)
|
|
||||||
.setSkyLight(skyLight);
|
|
||||||
wheels.setBlockLight(blockLight)
|
|
||||||
.setSkyLight(skyLight);
|
|
||||||
pin.setBlockLight(blockLight)
|
|
||||||
.setSkyLight(skyLight);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
super.remove();
|
|
||||||
for (ModelData shaft : secondShaft)
|
|
||||||
shaft.delete();
|
|
||||||
drive.delete();
|
|
||||||
piston.delete();
|
|
||||||
wheels.delete();
|
|
||||||
pin.delete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
package com.simibubi.create.content.logistics.trains.entity;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.MaterialManager;
|
||||||
|
import com.simibubi.create.AllBogeyStyles;
|
||||||
|
import com.simibubi.create.AllSoundEvents;
|
||||||
|
import com.simibubi.create.content.logistics.trains.BogeyRenderer;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.trains.BogeyRenderer.CommonRenderer;
|
||||||
|
import com.simibubi.create.content.logistics.trains.BogeySizes;
|
||||||
|
|
||||||
|
import net.minecraft.core.particles.ParticleOptions;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.sounds.SoundEvent;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
|
||||||
|
public class BogeyStyle {
|
||||||
|
private final Optional<Supplier<? extends CommonRenderer>> commonRendererFactory;
|
||||||
|
|
||||||
|
public final ResourceLocation name;
|
||||||
|
public final ResourceLocation cycleGroup;
|
||||||
|
private final Optional<CommonRenderer> commonRenderer;
|
||||||
|
private final Map<BogeySizes.BogeySize, SizeData> sizes;
|
||||||
|
public final Component displayName;
|
||||||
|
public final ResourceLocation soundType;
|
||||||
|
public final ParticleOptions contactParticle;
|
||||||
|
public final ParticleOptions smokeParticle;
|
||||||
|
public final CompoundTag defaultData;
|
||||||
|
|
||||||
|
public BogeyStyle(ResourceLocation name, ResourceLocation cycleGroup, Component displayName, ResourceLocation soundType, ParticleOptions contactParticle, ParticleOptions smokeParticle,
|
||||||
|
CompoundTag defaultData, Map<BogeySizes.BogeySize, SizeData> sizes, Optional<Supplier<? extends CommonRenderer>> commonRenderer) {
|
||||||
|
this.name = name;
|
||||||
|
this.cycleGroup = cycleGroup;
|
||||||
|
this.displayName = displayName;
|
||||||
|
this.soundType = soundType;
|
||||||
|
this.contactParticle = contactParticle;
|
||||||
|
this.smokeParticle = smokeParticle;
|
||||||
|
this.defaultData = defaultData;
|
||||||
|
|
||||||
|
this.sizes = sizes;
|
||||||
|
|
||||||
|
this.commonRendererFactory = commonRenderer;
|
||||||
|
this.commonRenderer = commonRenderer.map(Supplier::get);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<ResourceLocation, BogeyStyle> getCycleGroup() {
|
||||||
|
return AllBogeyStyles.getCycleGroup(cycleGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block getNextBlock(BogeySizes.BogeySize currentSize) {
|
||||||
|
return Stream.iterate(currentSize.increment(), BogeySizes.BogeySize::increment)
|
||||||
|
.filter(sizes::containsKey)
|
||||||
|
.findFirst()
|
||||||
|
.map(size -> ForgeRegistries.BLOCKS.getValue(sizes.get(size).block()))
|
||||||
|
.orElse(ForgeRegistries.BLOCKS.getValue(sizes.get(currentSize).block()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block getBlockOfSize(BogeySizes.BogeySize size) {
|
||||||
|
return ForgeRegistries.BLOCKS.getValue(sizes.get(size).block());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<BogeySizes.BogeySize> validSizes() {
|
||||||
|
return sizes.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public SoundEvent getSoundType() {
|
||||||
|
AllSoundEvents.SoundEntry entry = AllSoundEvents.ALL.get(this.soundType);
|
||||||
|
if (entry == null || entry.getMainEvent() == null) entry = AllSoundEvents.TRAIN2;
|
||||||
|
return entry.getMainEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyRenderer createRendererInstance(BogeySizes.BogeySize size) {
|
||||||
|
return this.sizes.get(size).createRenderInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyRenderer getInWorldRenderInstance(BogeySizes.BogeySize size) {
|
||||||
|
SizeData sizeData = this.sizes.get(size);
|
||||||
|
return sizeData != null ? sizeData.getInWorldInstance() : BackupBogeyRenderer.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<CommonRenderer> getInWorldCommonRenderInstance() {
|
||||||
|
return this.commonRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<CommonRenderer> getNewCommonRenderInstance() {
|
||||||
|
return this.commonRendererFactory.map(Supplier::get);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyInstance createInstance(CarriageBogey bogey, BogeySizes.BogeySize size, MaterialManager materialManager) {
|
||||||
|
return new BogeyInstance(bogey, this, size, materialManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record SizeData(ResourceLocation block, Supplier<? extends BogeyRenderer> rendererFactory, BogeyRenderer instance) {
|
||||||
|
public BogeyRenderer createRenderInstance() {
|
||||||
|
return rendererFactory.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyRenderer getInWorldInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -85,6 +85,11 @@ public class Carriage {
|
||||||
bogey2.carriage = this;
|
bogey2.carriage = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOnIncompatibleTrack() {
|
||||||
|
return leadingBogey().type.isOnIncompatibleTrack(this, true)
|
||||||
|
|| trailingBogey().type.isOnIncompatibleTrack(this, false);
|
||||||
|
}
|
||||||
|
|
||||||
public void setTrain(Train train) {
|
public void setTrain(Train train) {
|
||||||
this.train = train;
|
this.train = train;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +108,7 @@ public class Carriage {
|
||||||
|
|
||||||
DimensionalCarriageEntity dimensional = getDimensional(level);
|
DimensionalCarriageEntity dimensional = getDimensional(level);
|
||||||
dimensional.alignEntity(entity);
|
dimensional.alignEntity(entity);
|
||||||
dimensional.removeAndSaveEntity(entity, false);
|
dimensional.removeAndSaveEntity(entity, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DimensionalCarriageEntity getDimensional(Level level) {
|
public DimensionalCarriageEntity getDimensional(Level level) {
|
||||||
|
@ -306,6 +311,9 @@ public class Carriage {
|
||||||
double leadingWheelSpacing = leadingBogey.type.getWheelPointSpacing();
|
double leadingWheelSpacing = leadingBogey.type.getWheelPointSpacing();
|
||||||
double trailingWheelSpacing = trailingBogey.type.getWheelPointSpacing();
|
double trailingWheelSpacing = trailingBogey.type.getWheelPointSpacing();
|
||||||
|
|
||||||
|
boolean leadingUpsideDown = leadingBogey.isUpsideDown();
|
||||||
|
boolean trailingUpsideDown = trailingBogey.isUpsideDown();
|
||||||
|
|
||||||
for (boolean leading : Iterate.trueAndFalse) {
|
for (boolean leading : Iterate.trueAndFalse) {
|
||||||
TravellingPoint point = leading ? getLeadingPoint() : getTrailingPoint();
|
TravellingPoint point = leading ? getLeadingPoint() : getTrailingPoint();
|
||||||
TravellingPoint otherPoint = !leading ? getLeadingPoint() : getTrailingPoint();
|
TravellingPoint otherPoint = !leading ? getLeadingPoint() : getTrailingPoint();
|
||||||
|
@ -321,26 +329,31 @@ public class Carriage {
|
||||||
|
|
||||||
dce.positionAnchor = dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition()
|
dce.positionAnchor = dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition()
|
||||||
: pivoted(dce, dimension, point,
|
: pivoted(dce, dimension, point,
|
||||||
leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2);
|
leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2,
|
||||||
|
leadingUpsideDown, trailingUpsideDown);
|
||||||
|
|
||||||
|
boolean backAnchorFlip = trailingBogey.isUpsideDown() ^ leadingBogey.isUpsideDown();
|
||||||
|
|
||||||
if (isOnTwoBogeys()) {
|
if (isOnTwoBogeys()) {
|
||||||
dce.rotationAnchors.setFirst(dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition()
|
dce.rotationAnchors.setFirst(dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition()
|
||||||
: pivoted(dce, dimension, point,
|
: pivoted(dce, dimension, point,
|
||||||
leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2));
|
leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2,
|
||||||
dce.rotationAnchors.setSecond(dimension.equals(trailingBogeyDim) ? trailingBogey.getAnchorPosition()
|
leadingUpsideDown, trailingUpsideDown));
|
||||||
|
dce.rotationAnchors.setSecond(dimension.equals(trailingBogeyDim) ? trailingBogey.getAnchorPosition(backAnchorFlip)
|
||||||
: pivoted(dce, dimension, point,
|
: pivoted(dce, dimension, point,
|
||||||
leading ? leadingWheelSpacing / 2 + bogeySpacing : trailingWheelSpacing / 2));
|
leading ? leadingWheelSpacing / 2 + bogeySpacing : trailingWheelSpacing / 2,
|
||||||
|
leadingUpsideDown, trailingUpsideDown));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (dimension.equals(otherDimension)) {
|
if (dimension.equals(otherDimension)) {
|
||||||
dce.rotationAnchors = leadingBogey.points.map(tp -> tp.getPosition(train.graph));
|
dce.rotationAnchors = leadingBogey.points.map(tp -> tp.getPosition(train.graph));
|
||||||
} else {
|
} else {
|
||||||
dce.rotationAnchors
|
dce.rotationAnchors.setFirst(leadingBogey.points.getFirst() == point
|
||||||
.setFirst(leadingBogey.points.getFirst() == point ? point.getPosition(train.graph)
|
? point.getPosition(train.graph)
|
||||||
: pivoted(dce, dimension, point, leadingWheelSpacing));
|
: pivoted(dce, dimension, point, leadingWheelSpacing, leadingUpsideDown, trailingUpsideDown));
|
||||||
dce.rotationAnchors
|
dce.rotationAnchors.setSecond(leadingBogey.points.getSecond() == point
|
||||||
.setSecond(leadingBogey.points.getSecond() == point ? point.getPosition(train.graph)
|
? point.getPosition(train.graph)
|
||||||
: pivoted(dce, dimension, point, leadingWheelSpacing));
|
: pivoted(dce, dimension, point, leadingWheelSpacing, leadingUpsideDown, trailingUpsideDown));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,15 +371,16 @@ public class Carriage {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vec3 pivoted(DimensionalCarriageEntity dce, ResourceKey<Level> dimension, TravellingPoint start,
|
private Vec3 pivoted(DimensionalCarriageEntity dce, ResourceKey<Level> dimension, TravellingPoint start,
|
||||||
double offset) {
|
double offset, boolean leadingUpsideDown, boolean trailingUpsideDown) {
|
||||||
if (train.graph == null)
|
if (train.graph == null)
|
||||||
return dce.pivot == null ? null : dce.pivot.getLocation();
|
return dce.pivot == null ? null : dce.pivot.getLocation();
|
||||||
TrackNodeLocation pivot = dce.findPivot(dimension, start == getLeadingPoint());
|
TrackNodeLocation pivot = dce.findPivot(dimension, start == getLeadingPoint());
|
||||||
if (pivot == null)
|
if (pivot == null)
|
||||||
return null;
|
return null;
|
||||||
Vec3 startVec = start.getPosition(train.graph);
|
boolean flipped = start != getLeadingPoint() && (leadingUpsideDown != trailingUpsideDown);
|
||||||
|
Vec3 startVec = start.getPosition(train.graph, flipped);
|
||||||
Vec3 portalVec = pivot.getLocation()
|
Vec3 portalVec = pivot.getLocation()
|
||||||
.add(0, 1, 0);
|
.add(0, leadingUpsideDown ? -1.0 : 1.0, 0);
|
||||||
return VecHelper.lerp((float) (offset / startVec.distanceTo(portalVec)), startVec, portalVec);
|
return VecHelper.lerp((float) (offset / startVec.distanceTo(portalVec)), startVec, portalVec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,8 +739,8 @@ public class Carriage {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dismountPlayer(ServerLevel sLevel, ServerPlayer sp, Integer seat, boolean portal) {
|
private void dismountPlayer(ServerLevel sLevel, ServerPlayer sp, Integer seat, boolean capture) {
|
||||||
if (!portal) {
|
if (!capture) {
|
||||||
sp.stopRiding();
|
sp.stopRiding();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
package com.simibubi.create.content.logistics.trains.entity;
|
package com.simibubi.create.content.logistics.trains.entity;
|
||||||
|
|
||||||
|
import static com.simibubi.create.content.logistics.trains.track.AbstractBogeyBlockEntity.BOGEY_DATA_KEY;
|
||||||
|
import static com.simibubi.create.content.logistics.trains.track.AbstractBogeyBlockEntity.BOGEY_STYLE_KEY;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.MaterialManager;
|
import com.jozufozu.flywheel.api.MaterialManager;
|
||||||
|
import com.simibubi.create.AllBogeyStyles;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock;
|
||||||
import com.simibubi.create.content.logistics.trains.DimensionPalette;
|
import com.simibubi.create.content.logistics.trains.DimensionPalette;
|
||||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
|
||||||
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
import com.simibubi.create.content.logistics.trains.TrackGraph;
|
||||||
|
import com.simibubi.create.content.logistics.trains.track.AbstractBogeyBlockEntity;
|
||||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
import com.simibubi.create.foundation.utility.RegisteredObjects;
|
import com.simibubi.create.foundation.utility.RegisteredObjects;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||||
|
@ -27,11 +33,15 @@ import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
public class CarriageBogey {
|
public class CarriageBogey {
|
||||||
|
|
||||||
public Carriage carriage;
|
public static final String UPSIDE_DOWN_KEY = "UpsideDown";
|
||||||
|
|
||||||
|
public Carriage carriage;
|
||||||
boolean isLeading;
|
boolean isLeading;
|
||||||
|
|
||||||
IBogeyBlock type;
|
public CompoundTag bogeyData;
|
||||||
|
|
||||||
|
AbstractBogeyBlock<?> type;
|
||||||
|
boolean upsideDown;
|
||||||
Couple<TravellingPoint> points;
|
Couple<TravellingPoint> points;
|
||||||
|
|
||||||
LerpedFloat wheelAngle;
|
LerpedFloat wheelAngle;
|
||||||
|
@ -42,8 +52,15 @@ public class CarriageBogey {
|
||||||
|
|
||||||
int derailAngle;
|
int derailAngle;
|
||||||
|
|
||||||
public CarriageBogey(IBogeyBlock type, TravellingPoint point, TravellingPoint point2) {
|
public CarriageBogey(AbstractBogeyBlock<?> type, boolean upsideDown, CompoundTag bogeyData, TravellingPoint point, TravellingPoint point2) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
this.upsideDown = type.canBeUpsideDown() && upsideDown;
|
||||||
|
point.upsideDown = this.upsideDown;
|
||||||
|
point2.upsideDown = this.upsideDown;
|
||||||
|
if (bogeyData == null || bogeyData.isEmpty())
|
||||||
|
bogeyData = this.createBogeyData(); // Prevent Crash When Updating
|
||||||
|
bogeyData.putBoolean(UPSIDE_DOWN_KEY, upsideDown);
|
||||||
|
this.bogeyData = bogeyData;
|
||||||
points = Couple.create(point, point2);
|
points = Couple.create(point, point2);
|
||||||
wheelAngle = LerpedFloat.angular();
|
wheelAngle = LerpedFloat.angular();
|
||||||
yaw = LerpedFloat.angular();
|
yaw = LerpedFloat.angular();
|
||||||
|
@ -100,11 +117,15 @@ public class CarriageBogey {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TravellingPoint leading() {
|
public TravellingPoint leading() {
|
||||||
return points.getFirst();
|
TravellingPoint point = points.getFirst();
|
||||||
|
point.upsideDown = isUpsideDown();
|
||||||
|
return point;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TravellingPoint trailing() {
|
public TravellingPoint trailing() {
|
||||||
return points.getSecond();
|
TravellingPoint point = points.getSecond();
|
||||||
|
point.upsideDown = isUpsideDown();
|
||||||
|
return point;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getStress() {
|
public double getStress() {
|
||||||
|
@ -118,18 +139,25 @@ public class CarriageBogey {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Vec3 getAnchorPosition() {
|
public Vec3 getAnchorPosition() {
|
||||||
|
return getAnchorPosition(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Vec3 getAnchorPosition(boolean flipUpsideDown) {
|
||||||
if (leading().edge == null)
|
if (leading().edge == null)
|
||||||
return null;
|
return null;
|
||||||
return points.getFirst()
|
return points.getFirst()
|
||||||
.getPosition(carriage.train.graph)
|
.getPosition(carriage.train.graph, flipUpsideDown)
|
||||||
.add(points.getSecond()
|
.add(points.getSecond()
|
||||||
.getPosition(carriage.train.graph))
|
.getPosition(carriage.train.graph, flipUpsideDown))
|
||||||
.scale(.5);
|
.scale(.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateCouplingAnchor(Vec3 entityPos, float entityXRot, float entityYRot, int bogeySpacing,
|
public void updateCouplingAnchor(Vec3 entityPos, float entityXRot, float entityYRot, int bogeySpacing,
|
||||||
float partialTicks, boolean leading) {
|
float partialTicks, boolean leading) {
|
||||||
Vec3 thisOffset = type.getConnectorAnchorOffset();
|
boolean selfUpsideDown = isUpsideDown();
|
||||||
|
boolean leadingUpsideDown = carriage.leadingBogey().isUpsideDown();
|
||||||
|
Vec3 thisOffset = type.getConnectorAnchorOffset(selfUpsideDown);
|
||||||
thisOffset = thisOffset.multiply(1, 1, leading ? -1 : 1);
|
thisOffset = thisOffset.multiply(1, 1, leading ? -1 : 1);
|
||||||
|
|
||||||
thisOffset = VecHelper.rotate(thisOffset, pitch.getValue(partialTicks), Axis.X);
|
thisOffset = VecHelper.rotate(thisOffset, pitch.getValue(partialTicks), Axis.X);
|
||||||
|
@ -141,6 +169,8 @@ public class CarriageBogey {
|
||||||
thisOffset = VecHelper.rotate(thisOffset, 180, Axis.Y);
|
thisOffset = VecHelper.rotate(thisOffset, 180, Axis.Y);
|
||||||
thisOffset = VecHelper.rotate(thisOffset, -entityXRot, Axis.X);
|
thisOffset = VecHelper.rotate(thisOffset, -entityXRot, Axis.X);
|
||||||
thisOffset = VecHelper.rotate(thisOffset, entityYRot + 90, Axis.Y);
|
thisOffset = VecHelper.rotate(thisOffset, entityYRot + 90, Axis.Y);
|
||||||
|
if (selfUpsideDown != leadingUpsideDown)
|
||||||
|
thisOffset = thisOffset.add(0, selfUpsideDown ? -2 : 2, 0);
|
||||||
|
|
||||||
couplingAnchors.set(leading, entityPos.add(thisOffset));
|
couplingAnchors.set(leading, entityPos.add(thisOffset));
|
||||||
}
|
}
|
||||||
|
@ -150,23 +180,46 @@ public class CarriageBogey {
|
||||||
tag.putString("Type", RegisteredObjects.getKeyOrThrow((Block) type)
|
tag.putString("Type", RegisteredObjects.getKeyOrThrow((Block) type)
|
||||||
.toString());
|
.toString());
|
||||||
tag.put("Points", points.serializeEach(tp -> tp.write(dimensions)));
|
tag.put("Points", points.serializeEach(tp -> tp.write(dimensions)));
|
||||||
|
tag.putBoolean("UpsideDown", upsideDown);
|
||||||
|
bogeyData.putBoolean(UPSIDE_DOWN_KEY, upsideDown);
|
||||||
|
NBTHelper.writeResourceLocation(bogeyData, BOGEY_STYLE_KEY, getStyle().name);
|
||||||
|
tag.put(BOGEY_DATA_KEY, bogeyData);
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CarriageBogey read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) {
|
public static CarriageBogey read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) {
|
||||||
ResourceLocation location = new ResourceLocation(tag.getString("Type"));
|
ResourceLocation location = new ResourceLocation(tag.getString("Type"));
|
||||||
IBogeyBlock type = (IBogeyBlock) ForgeRegistries.BLOCKS.getValue(location);
|
AbstractBogeyBlock<?> type = (AbstractBogeyBlock<?>) ForgeRegistries.BLOCKS.getValue(location);
|
||||||
|
boolean upsideDown = tag.getBoolean("UpsideDown");
|
||||||
Couple<TravellingPoint> points = Couple.deserializeEach(tag.getList("Points", Tag.TAG_COMPOUND),
|
Couple<TravellingPoint> points = Couple.deserializeEach(tag.getList("Points", Tag.TAG_COMPOUND),
|
||||||
c -> TravellingPoint.read(c, graph, dimensions));
|
c -> TravellingPoint.read(c, graph, dimensions));
|
||||||
CarriageBogey carriageBogey = new CarriageBogey(type, points.getFirst(), points.getSecond());
|
CompoundTag data = tag.getCompound(AbstractBogeyBlockEntity.BOGEY_DATA_KEY);
|
||||||
return carriageBogey;
|
return new CarriageBogey(type, upsideDown, data, points.getFirst(), points.getSecond());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BogeyInstance createInstance(MaterialManager materialManager) {
|
public BogeyInstance createInstance(MaterialManager materialManager) {
|
||||||
return type.createInstance(materialManager, this);
|
return this.getStyle().createInstance(this, type.getSize(), materialManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BogeyStyle getStyle() {
|
||||||
|
ResourceLocation location = NBTHelper.readResourceLocation(this.bogeyData, BOGEY_STYLE_KEY);
|
||||||
|
BogeyStyle style = AllBogeyStyles.BOGEY_STYLES.get(location);
|
||||||
|
return style != null ? style : AllBogeyStyles.STANDARD; // just for safety
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompoundTag createBogeyData() {
|
||||||
|
BogeyStyle style = type != null ? type.getDefaultStyle() : AllBogeyStyles.STANDARD;
|
||||||
|
CompoundTag nbt = style.defaultData != null ? style.defaultData : new CompoundTag();
|
||||||
|
NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, style.name);
|
||||||
|
nbt.putBoolean(UPSIDE_DOWN_KEY, isUpsideDown());
|
||||||
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLeading() {
|
void setLeading() {
|
||||||
isLeading = true;
|
isLeading = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isUpsideDown() {
|
||||||
|
return type.canBeUpsideDown() && upsideDown;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.ren
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.TrainCargoManager;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.TrainCargoManager;
|
||||||
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
|
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
|
||||||
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel;
|
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel;
|
||||||
import com.simibubi.create.content.logistics.trains.IBogeyBlock;
|
import com.simibubi.create.content.logistics.trains.AbstractBogeyBlock;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
@ -162,11 +162,13 @@ public class CarriageContraption extends Contraption {
|
||||||
.getStep(), toLocalPos(pos));
|
.getStep(), toLocalPos(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockState.getBlock() instanceof IBogeyBlock) {
|
if (blockState.getBlock() instanceof AbstractBogeyBlock<?> bogey) {
|
||||||
|
boolean captureTE = bogey.captureTileEntityForTrain();
|
||||||
bogeys++;
|
bogeys++;
|
||||||
if (bogeys == 2)
|
if (bogeys == 2)
|
||||||
secondBogeyPos = pos;
|
secondBogeyPos = pos;
|
||||||
return Pair.of(new StructureBlockInfo(pos, blockState, null), null);
|
return Pair.of(new StructureBlockInfo(pos, blockState, captureTE ? getBlockEntityNBT(world, pos) : null),
|
||||||
|
captureTE ? world.getBlockEntity(pos) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AllBlocks.BLAZE_BURNER.has(blockState)
|
if (AllBlocks.BLAZE_BURNER.has(blockState)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import net.minecraft.client.renderer.culling.Frustum;
|
||||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.world.level.LightLayer;
|
import net.minecraft.world.level.LightLayer;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer<CarriageContraptionEntity> {
|
public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer<CarriageContraptionEntity> {
|
||||||
|
@ -65,8 +66,9 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer
|
||||||
translateBogey(ms, bogey, bogeySpacing, viewYRot, viewXRot, partialTicks);
|
translateBogey(ms, bogey, bogeySpacing, viewYRot, viewXRot, partialTicks);
|
||||||
|
|
||||||
int light = getBogeyLightCoords(entity, bogey, partialTicks);
|
int light = getBogeyLightCoords(entity, bogey, partialTicks);
|
||||||
|
|
||||||
bogey.type.render(null, bogey.wheelAngle.getValue(partialTicks), ms, partialTicks, buffers, light,
|
bogey.type.render(null, bogey.wheelAngle.getValue(partialTicks), ms, partialTicks, buffers, light,
|
||||||
overlay);
|
overlay, bogey.getStyle(), bogey.bogeyData);
|
||||||
|
|
||||||
ms.popPose();
|
ms.popPose();
|
||||||
}
|
}
|
||||||
|
@ -80,6 +82,8 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer
|
||||||
|
|
||||||
public static void translateBogey(PoseStack ms, CarriageBogey bogey, int bogeySpacing, float viewYRot,
|
public static void translateBogey(PoseStack ms, CarriageBogey bogey, int bogeySpacing, float viewYRot,
|
||||||
float viewXRot, float partialTicks) {
|
float viewXRot, float partialTicks) {
|
||||||
|
boolean selfUpsideDown = bogey.isUpsideDown();
|
||||||
|
boolean leadingUpsideDown = bogey.carriage.leadingBogey().isUpsideDown();
|
||||||
TransformStack.cast(ms)
|
TransformStack.cast(ms)
|
||||||
.rotateY(viewYRot + 90)
|
.rotateY(viewYRot + 90)
|
||||||
.rotateX(-viewXRot)
|
.rotateX(-viewXRot)
|
||||||
|
@ -90,7 +94,9 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer
|
||||||
.rotateY(-viewYRot - 90)
|
.rotateY(-viewYRot - 90)
|
||||||
.rotateY(bogey.yaw.getValue(partialTicks))
|
.rotateY(bogey.yaw.getValue(partialTicks))
|
||||||
.rotateX(bogey.pitch.getValue(partialTicks))
|
.rotateX(bogey.pitch.getValue(partialTicks))
|
||||||
.translate(0, .5f, 0);
|
.translate(0, .5f, 0)
|
||||||
|
.rotateZ(selfUpsideDown ? 180 : 0)
|
||||||
|
.translateY(selfUpsideDown != leadingUpsideDown ? 2 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getBogeyLightCoords(CarriageContraptionEntity entity, CarriageBogey bogey, float partialTicks) {
|
public static int getBogeyLightCoords(CarriageContraptionEntity entity, CarriageBogey bogey, float partialTicks) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.math.Vector3f;
|
import com.mojang.math.Vector3f;
|
||||||
|
import com.simibubi.create.content.logistics.trains.BogeyRenderer;
|
||||||
import com.simibubi.create.foundation.utility.Couple;
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
|
||||||
|
@ -31,7 +32,8 @@ public class CarriageContraptionInstance extends EntityInstance<CarriageContrapt
|
||||||
if (carriage == null)
|
if (carriage == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bogeys = carriage.bogeys.mapNotNullWithParam(CarriageBogey::createInstance, materialManager);
|
bogeys = carriage.bogeys.mapNotNullWithParam((bogey, manager) ->
|
||||||
|
bogey.getStyle().createInstance(bogey, bogey.type.getSize(), manager), materialManager);
|
||||||
updateLight();
|
updateLight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,8 +100,10 @@ public class CarriageContraptionInstance extends EntityInstance<CarriageContrapt
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bogeys.forEach(instance -> {
|
bogeys.forEach(instance -> {
|
||||||
if (instance != null)
|
if (instance != null) {
|
||||||
instance.remove();
|
instance.commonRenderer.ifPresent(BogeyRenderer::remove);
|
||||||
|
instance.renderer.remove();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class CarriageCouplingRenderer {
|
||||||
|
|
||||||
float margin = 3 / 16f;
|
float margin = 3 / 16f;
|
||||||
double couplingDistance = train.carriageSpacing.get(i) - 2 * margin
|
double couplingDistance = train.carriageSpacing.get(i) - 2 * margin
|
||||||
- bogey1.type.getConnectorAnchorOffset().z - bogey2.type.getConnectorAnchorOffset().z;
|
- bogey1.type.getConnectorAnchorOffset(bogey1.isUpsideDown()).z - bogey2.type.getConnectorAnchorOffset(bogey2.isUpsideDown()).z;
|
||||||
int couplingSegments = (int) Math.round(couplingDistance * 4);
|
int couplingSegments = (int) Math.round(couplingDistance * 4);
|
||||||
double stretch = ((anchor2.distanceTo(anchor) - 2 * margin) * 4) / couplingSegments;
|
double stretch = ((anchor2.distanceTo(anchor) - 2 * margin) * 4) / couplingSegments;
|
||||||
for (int j = 0; j < couplingSegments; j++) {
|
for (int j = 0; j < couplingSegments; j++) {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.core.Direction.Axis;
|
import net.minecraft.core.Direction.Axis;
|
||||||
import net.minecraft.core.particles.ParticleTypes;
|
|
||||||
import net.minecraft.util.RandomSource;
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
@ -109,7 +108,7 @@ public class CarriageParticles {
|
||||||
|
|
||||||
m = m.add(contraptionMotion.scale(.75f));
|
m = m.add(contraptionMotion.scale(.75f));
|
||||||
|
|
||||||
level.addParticle(spark ? ParticleTypes.CRIT : ParticleTypes.POOF, v.x, v.y, v.z, m.x, m.y, m.z);
|
level.addParticle(spark ? bogey.getStyle().contactParticle : bogey.getStyle().smokeParticle, v.x, v.y, v.z, m.x, m.y, m.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.simibubi.create.content.logistics.trains.entity;
|
||||||
import com.simibubi.create.AllSoundEvents;
|
import com.simibubi.create.AllSoundEvents;
|
||||||
import com.simibubi.create.AllSoundEvents.SoundEntry;
|
import com.simibubi.create.AllSoundEvents.SoundEntry;
|
||||||
import com.simibubi.create.content.logistics.trains.entity.Carriage.DimensionalCarriageEntity;
|
import com.simibubi.create.content.logistics.trains.entity.Carriage.DimensionalCarriageEntity;
|
||||||
|
import com.simibubi.create.foundation.utility.Couple;
|
||||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
|
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
|
||||||
|
|
||||||
|
@ -30,6 +31,9 @@ public class CarriageSounds {
|
||||||
LoopingSound sharedWheelSoundSeated;
|
LoopingSound sharedWheelSoundSeated;
|
||||||
LoopingSound sharedHonkSound;
|
LoopingSound sharedHonkSound;
|
||||||
|
|
||||||
|
Couple<SoundEvent> bogeySounds;
|
||||||
|
SoundEvent closestBogeySound;
|
||||||
|
|
||||||
boolean arrived;
|
boolean arrived;
|
||||||
|
|
||||||
int tick;
|
int tick;
|
||||||
|
@ -37,6 +41,10 @@ public class CarriageSounds {
|
||||||
|
|
||||||
public CarriageSounds(CarriageContraptionEntity entity) {
|
public CarriageSounds(CarriageContraptionEntity entity) {
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
|
bogeySounds = entity.getCarriage().bogeys.map(bogey ->
|
||||||
|
bogey != null && bogey.getStyle() != null ? bogey.getStyle().getSoundType()
|
||||||
|
: AllSoundEvents.TRAIN2.getMainEvent());
|
||||||
|
closestBogeySound = bogeySounds.getFirst();
|
||||||
distanceFactor = LerpedFloat.linear();
|
distanceFactor = LerpedFloat.linear();
|
||||||
speedFactor = LerpedFloat.linear();
|
speedFactor = LerpedFloat.linear();
|
||||||
approachFactor = LerpedFloat.linear();
|
approachFactor = LerpedFloat.linear();
|
||||||
|
@ -80,6 +88,15 @@ public class CarriageSounds {
|
||||||
double distance1 = toBogey1.length();
|
double distance1 = toBogey1.length();
|
||||||
double distance2 = toBogey2.length();
|
double distance2 = toBogey2.length();
|
||||||
|
|
||||||
|
Couple<CarriageBogey> bogeys = entity.getCarriage().bogeys;
|
||||||
|
CarriageBogey relevantBogey = bogeys.get(distance1 > distance2);
|
||||||
|
if (relevantBogey == null) {
|
||||||
|
relevantBogey = bogeys.getFirst();
|
||||||
|
}
|
||||||
|
if (relevantBogey != null) {
|
||||||
|
closestBogeySound = relevantBogey.getStyle().getSoundType();
|
||||||
|
}
|
||||||
|
|
||||||
Vec3 toCarriage = distance1 > distance2 ? toBogey2 : toBogey1;
|
Vec3 toCarriage = distance1 > distance2 ? toBogey2 : toBogey1;
|
||||||
double distance = Math.min(distance1, distance2);
|
double distance = Math.min(distance1, distance2);
|
||||||
Vec3 soundLocation = cam.add(toCarriage);
|
Vec3 soundLocation = cam.add(toCarriage);
|
||||||
|
@ -98,7 +115,7 @@ public class CarriageSounds {
|
||||||
seatCrossfade.tickChaser();
|
seatCrossfade.tickChaser();
|
||||||
|
|
||||||
minecartEsqueSound = playIfMissing(mc, minecartEsqueSound, AllSoundEvents.TRAIN.getMainEvent());
|
minecartEsqueSound = playIfMissing(mc, minecartEsqueSound, AllSoundEvents.TRAIN.getMainEvent());
|
||||||
sharedWheelSound = playIfMissing(mc, sharedWheelSound, AllSoundEvents.TRAIN2.getMainEvent());
|
sharedWheelSound = playIfMissing(mc, sharedWheelSound, closestBogeySound);
|
||||||
sharedWheelSoundSeated = playIfMissing(mc, sharedWheelSoundSeated, AllSoundEvents.TRAIN3.getMainEvent());
|
sharedWheelSoundSeated = playIfMissing(mc, sharedWheelSoundSeated, AllSoundEvents.TRAIN3.getMainEvent());
|
||||||
|
|
||||||
float volume = Math.min(Math.min(speedFactor.getValue(), distanceFactor.getValue() / 100),
|
float volume = Math.min(Math.min(speedFactor.getValue(), distanceFactor.getValue() / 100),
|
||||||
|
@ -206,7 +223,7 @@ public class CarriageSounds {
|
||||||
public void submitSharedSoundVolume(Vec3 location, float volume) {
|
public void submitSharedSoundVolume(Vec3 location, float volume) {
|
||||||
Minecraft mc = Minecraft.getInstance();
|
Minecraft mc = Minecraft.getInstance();
|
||||||
minecartEsqueSound = playIfMissing(mc, minecartEsqueSound, AllSoundEvents.TRAIN.getMainEvent());
|
minecartEsqueSound = playIfMissing(mc, minecartEsqueSound, AllSoundEvents.TRAIN.getMainEvent());
|
||||||
sharedWheelSound = playIfMissing(mc, sharedWheelSound, AllSoundEvents.TRAIN2.getMainEvent());
|
sharedWheelSound = playIfMissing(mc, sharedWheelSound, closestBogeySound);
|
||||||
sharedWheelSoundSeated = playIfMissing(mc, sharedWheelSoundSeated, AllSoundEvents.TRAIN3.getMainEvent());
|
sharedWheelSoundSeated = playIfMissing(mc, sharedWheelSoundSeated, AllSoundEvents.TRAIN3.getMainEvent());
|
||||||
|
|
||||||
boolean approach = true;
|
boolean approach = true;
|
||||||
|
|
|
@ -14,6 +14,8 @@ import java.util.UUID;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.trains.TrackMaterial;
|
||||||
|
|
||||||
import org.apache.commons.lang3.mutable.MutableDouble;
|
import org.apache.commons.lang3.mutable.MutableDouble;
|
||||||
import org.apache.commons.lang3.mutable.MutableObject;
|
import org.apache.commons.lang3.mutable.MutableObject;
|
||||||
|
|
||||||
|
@ -555,6 +557,21 @@ public class Navigation {
|
||||||
if (graph == null)
|
if (graph == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Cache the list of track types that the train can travel on
|
||||||
|
Set<TrackMaterial.TrackType> validTypes = new HashSet<>();
|
||||||
|
for (int i = 0; i < train.carriages.size(); i++) {
|
||||||
|
Carriage carriage = train.carriages.get(i);
|
||||||
|
if (i == 0) {
|
||||||
|
validTypes.addAll(carriage.leadingBogey().type.getValidPathfindingTypes(carriage.leadingBogey().getStyle()));
|
||||||
|
} else {
|
||||||
|
validTypes.retainAll(carriage.leadingBogey().type.getValidPathfindingTypes(carriage.leadingBogey().getStyle()));
|
||||||
|
}
|
||||||
|
if (carriage.isOnTwoBogeys())
|
||||||
|
validTypes.retainAll(carriage.trailingBogey().type.getValidPathfindingTypes(carriage.trailingBogey().getStyle()));
|
||||||
|
}
|
||||||
|
if (validTypes.isEmpty()) // if there are no valid track types, a route can't be found
|
||||||
|
return;
|
||||||
|
|
||||||
Map<TrackEdge, Integer> penalties = new IdentityHashMap<>();
|
Map<TrackEdge, Integer> penalties = new IdentityHashMap<>();
|
||||||
boolean costRelevant = maxCost >= 0;
|
boolean costRelevant = maxCost >= 0;
|
||||||
if (costRelevant) {
|
if (costRelevant) {
|
||||||
|
@ -674,6 +691,8 @@ public class Navigation {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (Entry<TrackNode, TrackEdge> target : validTargets) {
|
for (Entry<TrackNode, TrackEdge> target : validTargets) {
|
||||||
|
if (!validTypes.contains(target.getValue().getTrackMaterial().trackType))
|
||||||
|
continue;
|
||||||
TrackNode newNode = target.getKey();
|
TrackNode newNode = target.getKey();
|
||||||
TrackEdge newEdge = target.getValue();
|
TrackEdge newEdge = target.getValue();
|
||||||
double newDistance = newEdge.getLength() + distance;
|
double newDistance = newEdge.getLength() + distance;
|
||||||
|
|
|
@ -42,6 +42,7 @@ import com.simibubi.create.content.logistics.trains.management.edgePoint.station
|
||||||
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlockEntity;
|
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlockEntity;
|
||||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime;
|
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime;
|
||||||
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime.State;
|
import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime.State;
|
||||||
|
import com.simibubi.create.content.logistics.trains.track.AbstractBogeyBlockEntity;
|
||||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
import com.simibubi.create.foundation.networking.AllPackets;
|
import com.simibubi.create.foundation.networking.AllPackets;
|
||||||
|
@ -66,6 +67,7 @@ import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.Explosion.BlockInteraction;
|
import net.minecraft.world.level.Explosion.BlockInteraction;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.minecraftforge.common.ForgeHooks;
|
import net.minecraftforge.common.ForgeHooks;
|
||||||
import net.minecraftforge.fluids.FluidStack;
|
import net.minecraftforge.fluids.FluidStack;
|
||||||
|
@ -86,6 +88,7 @@ public class Train {
|
||||||
public boolean honk = false;
|
public boolean honk = false;
|
||||||
|
|
||||||
public UUID id;
|
public UUID id;
|
||||||
|
@Nullable
|
||||||
public UUID owner;
|
public UUID owner;
|
||||||
public TrackGraph graph;
|
public TrackGraph graph;
|
||||||
public Navigation navigation;
|
public Navigation navigation;
|
||||||
|
@ -313,7 +316,13 @@ public class Train {
|
||||||
if (leadingAnchor == null || trailingAnchor == null)
|
if (leadingAnchor == null || trailingAnchor == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
total += leadingAnchor.distanceTo(trailingAnchor);
|
double distanceTo = leadingAnchor.distanceToSqr(trailingAnchor);
|
||||||
|
if (carriage.leadingBogey().isUpsideDown() != previousCarriage.trailingBogey().isUpsideDown()) {
|
||||||
|
distanceTo = Math.sqrt(distanceTo - 4);
|
||||||
|
} else {
|
||||||
|
distanceTo = Math.sqrt(distanceTo);
|
||||||
|
}
|
||||||
|
total += distanceTo;
|
||||||
entries++;
|
entries++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,7 +384,7 @@ public class Train {
|
||||||
int carriageType = first ? last ? Carriage.BOTH : Carriage.FIRST : last ? Carriage.LAST : Carriage.MIDDLE;
|
int carriageType = first ? last ? Carriage.BOTH : Carriage.FIRST : last ? Carriage.LAST : Carriage.MIDDLE;
|
||||||
double actualDistance =
|
double actualDistance =
|
||||||
carriage.travel(level, graph, distance + totalStress, toFollowForward, toFollowBackward, carriageType);
|
carriage.travel(level, graph, distance + totalStress, toFollowForward, toFollowBackward, carriageType);
|
||||||
blocked |= carriage.blocked;
|
blocked |= carriage.blocked || carriage.isOnIncompatibleTrack();
|
||||||
|
|
||||||
boolean onTwoBogeys = carriage.isOnTwoBogeys();
|
boolean onTwoBogeys = carriage.isOnTwoBogeys();
|
||||||
maxStress = Math.max(maxStress, onTwoBogeys ? carriage.bogeySpacing - carriage.getAnchorDiff() : 0);
|
maxStress = Math.max(maxStress, onTwoBogeys ? carriage.bogeySpacing - carriage.getAnchorDiff() : 0);
|
||||||
|
@ -722,9 +731,20 @@ public class Train {
|
||||||
if (entity.getContraption()instanceof CarriageContraption cc)
|
if (entity.getContraption()instanceof CarriageContraption cc)
|
||||||
cc.returnStorageForDisassembly(carriage.storage);
|
cc.returnStorageForDisassembly(carriage.storage);
|
||||||
entity.setPos(Vec3
|
entity.setPos(Vec3
|
||||||
.atLowerCornerOf(pos.relative(assemblyDirection, backwards ? offset + carriage.bogeySpacing : offset)));
|
.atLowerCornerOf(pos.relative(assemblyDirection, backwards ? offset + carriage.bogeySpacing : offset).below(carriage.leadingBogey().isUpsideDown() ? 2 : 0)));
|
||||||
entity.disassemble();
|
entity.disassemble();
|
||||||
|
|
||||||
|
for (CarriageBogey bogey : carriage.bogeys) {
|
||||||
|
if (bogey == null)
|
||||||
|
continue;
|
||||||
|
Vec3 bogeyPosition = bogey.getAnchorPosition();
|
||||||
|
if (bogeyPosition == null) continue;
|
||||||
|
BlockEntity be = level.getBlockEntity(new BlockPos(bogeyPosition));
|
||||||
|
if (!(be instanceof AbstractBogeyBlockEntity sbte))
|
||||||
|
continue;
|
||||||
|
sbte.setBogeyData(bogey.bogeyData);
|
||||||
|
}
|
||||||
|
|
||||||
offset += carriage.bogeySpacing;
|
offset += carriage.bogeySpacing;
|
||||||
|
|
||||||
if (i < carriageSpacing.size())
|
if (i < carriageSpacing.size())
|
||||||
|
@ -944,7 +964,7 @@ public class Train {
|
||||||
occupiedObservers.clear();
|
occupiedObservers.clear();
|
||||||
cachedObserverFiltering.clear();
|
cachedObserverFiltering.clear();
|
||||||
|
|
||||||
TravellingPoint signalScout = new TravellingPoint(node1, node2, edge, position);
|
TravellingPoint signalScout = new TravellingPoint(node1, node2, edge, position, false);
|
||||||
Map<UUID, SignalEdgeGroup> allGroups = Create.RAILWAYS.signalEdgeGroups;
|
Map<UUID, SignalEdgeGroup> allGroups = Create.RAILWAYS.signalEdgeGroups;
|
||||||
MutableObject<UUID> prevGroup = new MutableObject<>(null);
|
MutableObject<UUID> prevGroup = new MutableObject<>(null);
|
||||||
|
|
||||||
|
@ -1087,6 +1107,7 @@ public class Train {
|
||||||
public CompoundTag write(DimensionPalette dimensions) {
|
public CompoundTag write(DimensionPalette dimensions) {
|
||||||
CompoundTag tag = new CompoundTag();
|
CompoundTag tag = new CompoundTag();
|
||||||
tag.putUUID("Id", id);
|
tag.putUUID("Id", id);
|
||||||
|
if (owner != null)
|
||||||
tag.putUUID("Owner", owner);
|
tag.putUUID("Owner", owner);
|
||||||
if (graph != null)
|
if (graph != null)
|
||||||
tag.putUUID("Graph", graph.id);
|
tag.putUUID("Graph", graph.id);
|
||||||
|
@ -1133,7 +1154,7 @@ public class Train {
|
||||||
|
|
||||||
public static Train read(CompoundTag tag, Map<UUID, TrackGraph> trackNetworks, DimensionPalette dimensions) {
|
public static Train read(CompoundTag tag, Map<UUID, TrackGraph> trackNetworks, DimensionPalette dimensions) {
|
||||||
UUID id = tag.getUUID("Id");
|
UUID id = tag.getUUID("Id");
|
||||||
UUID owner = tag.getUUID("Owner");
|
UUID owner = tag.contains("Owner") ? tag.getUUID("Owner") : null;
|
||||||
UUID graphId = tag.contains("Graph") ? tag.getUUID("Graph") : null;
|
UUID graphId = tag.contains("Graph") ? tag.getUUID("Graph") : null;
|
||||||
TrackGraph graph = graphId == null ? null : trackNetworks.get(graphId);
|
TrackGraph graph = graphId == null ? null : trackNetworks.get(graphId);
|
||||||
List<Carriage> carriages = new ArrayList<>();
|
List<Carriage> carriages = new ArrayList<>();
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue