mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-02-05 01:45:00 +01:00
Merge branch 'mc1.19/dev' into mc1.20.1/dev
Conflicts: gradle.properties src/main/java/com/simibubi/create/Create.java src/main/java/com/simibubi/create/content/kinetics/fan/FanProcessing.java src/main/java/com/simibubi/create/content/trains/bogey/BogeyRenderer.java src/main/java/com/simibubi/create/foundation/mixin/client/FixNormalScalingMixin.java src/main/java/com/simibubi/create/infrastructure/gametest/tests/TestItems.java
This commit is contained in:
commit
78cf451f6d
88 changed files with 1094 additions and 1546 deletions
138
## Changes.md
138
## Changes.md
|
@ -1,138 +0,0 @@
|
|||
## Additions
|
||||
|
||||
- Netherite Backtank
|
||||
- Netherite Diving Helmet and Boots
|
||||
- Contraption Controls
|
||||
- Elevator Pulley
|
||||
- Copycat Panels and Copycat Steps
|
||||
- Block of Andesite Alloy
|
||||
- Block of Industrial Iron
|
||||
- Large Water Wheel
|
||||
- Mechanical Roller
|
||||
- Andesite, Brass and Copper Doors
|
||||
- Andesite, Brass and Copper Bars
|
||||
- Andesite, Brass and Copper Scaffolding
|
||||
- Clipboard
|
||||
- Mangrove Windows (1.19)
|
||||
|
||||
## Changes
|
||||
|
||||
- Overhauled models and textures of Andesite & Brass components (Kryppers)
|
||||
- Reworked textures of colored blocks such as seats and sails (dani)
|
||||
- New filter sprites (vectorwing)
|
||||
- Valve handles can now be used to precisely turn mechanical bearings by a set angle
|
||||
- Pulley ropes are now climbable
|
||||
- Lowered hitbox of seats for improved traversability inside contraptions
|
||||
- Improved safety for players standing on vertically moving contraptions
|
||||
- Pulley contraptions will now make an effort to place remote players at y values sensible to the client
|
||||
- Fixed seated entities on rotating contraptions not rendering at the correct location
|
||||
- Deployers no longer fail to activate in chunks claimed or protected by the player that placed them
|
||||
- Fixed couplings, schematics and in-world overlays not rendering correctly at coordinates far from the origin
|
||||
- Fixed Bearings, Pistons, Pulleys and Gantries powered by a Sequenced Gearshift not moving precisely to its instructions at high speeds
|
||||
- Minecart contraptions no longer visually jump to a location when stalled
|
||||
- Mechanical bearings now snap to a rounded angle when stopped
|
||||
- Contraption storage now accepts more chests and barrels from other mods
|
||||
- Players can now open chests and barrels on assembled contraptions
|
||||
- Mechanical Pumps no longer reverse direction based on kinetic input
|
||||
- Fixed pipe connections pulling fluids with half the speed compared to a directly attached pump
|
||||
- Substantially increased speed of visual flow propagation inside pipe networks
|
||||
- Portable storage interfaces now stall for longer after an exchange has happened, and shorter otherwise
|
||||
- Single train track blocks with slopes connected on either side will angle themselves to create a smoother ascend across both
|
||||
- Multiple pulleys can now attach to contraptions in a synchronised group
|
||||
- Display Boards now update text instantaneously at high input rpm
|
||||
- Diving helmets now always grant aqua affinity
|
||||
- Diving helmets can no longer be enchanted with aqua affinity
|
||||
- Water wheel fins are no longer directional
|
||||
- Water wheels now only have one speed level
|
||||
- Water wheels can now take the appearance of any reasonably implemented wood type
|
||||
- Added sided door control options to elevator contact and train station UI
|
||||
- Liquid can no longer spread perpendicularly on top of water wheels
|
||||
- Overhauled UX of scroll values and item filtering
|
||||
- Filtered item extraction can now be configured to pull "up to x items" per operation
|
||||
- Connected textures now use and apply the getAppearance() standard by Forge, allowing them to connect across other mods' facades, etc. (1.19)
|
||||
- Boiler status now highlights information about water flow when insufficient
|
||||
- The majority of in-world options no longer require a wrench
|
||||
- Chutes can now be encased in Industrial Iron Blocks
|
||||
- Chutes are now less prone to resetting shape when moved or rotated
|
||||
- Moved metal block variants to Building Blocks tab
|
||||
- Changed stonecutting ingredient of metal block variants from sheet to ingot
|
||||
- Base stone blocks can now be stonecut back from their cut variants
|
||||
- Fixed track placement allowing an s-bend between two sloped track pieces in specific arrangements
|
||||
- Fixed funnels losing filters when changing between types
|
||||
- New randomised textures for natural palette stone types (Kryppers)
|
||||
- Readjusted palette stone generation to use taller layers
|
||||
- World generation now places fewer stone type veins by default
|
||||
- Fixed lava fans voiding items that have smoking & smelting recipes with different outputs
|
||||
- Filter items now filter for their own item type if left empty
|
||||
- Valve handles no longer create stress config entries for each dyed variant
|
||||
- Place near initial angle mode on bearings now has a smaller interval considered 'near'
|
||||
- Players can now take items from saws via right-click
|
||||
- Item Drains now accept dropped items as input
|
||||
- Train track placement overlay now explicitly mentions the ctrl key
|
||||
- Fixed Mechanical Saws not rendering as animated when using rubidium
|
||||
- Fixed a ui element of the Station Screen rendering behind the background
|
||||
- Belts printed instantly or via cannon now retain the correct type of casing
|
||||
- Scheduled trains no longer slow down for slight ascends/descents on a straight track
|
||||
- Fixed saplings and other non-collidables sticking to chassis or super glue
|
||||
- Encased Fluid Pipes no longer z-fight on open pipe faces
|
||||
- Valve handles now turn twice as quickly
|
||||
- Bearings no longer have the angle-indicating nook on their block
|
||||
- Depot hitbox is now a simple cuboid
|
||||
- Fixed belts encased with andesite briefly showing brass textures
|
||||
- Fixed Filters and Attribute Filters not stacking with unmodified, equivalent stacks
|
||||
- Fixed Attribute Filters saving the name tag preview item in their data
|
||||
- Filters and Schedules can now be reset via crafting
|
||||
- Renamed Sails to Windmill Sails
|
||||
- Crushing gold ore now yields more experience nuggets
|
||||
- Fixed valve pipes sometimes not rotating their indicator fully
|
||||
- Horizontal, encased belts now render a support structure when solid blocks are above them
|
||||
- Added placement assist for mechanical drills, saws and deployers
|
||||
- Mechanical Belts can now be waterlogged
|
||||
- Depots and Ejectors can now be Waterlogged
|
||||
- Chutes and Funnels can now be Waterlogged
|
||||
- Fixed upright mechanical saws only able to be oriented in two directions
|
||||
- Deployers now have their filter slot on the side of the block
|
||||
- Deployers can now be rotated by wrenching them near the edge of the front face
|
||||
- Deployers now set filters on blocks only by targeting any location on a correct side
|
||||
- Fixed Schematics loaded for deployer printing not rotating block entity contents
|
||||
- Added tripwire to #movable_empty_collider
|
||||
- Renamed Stockpile Switch to Threshold Switch
|
||||
- Renamed Content Observer to Smart Observer
|
||||
- Smart observer and threshold switch can now be oriented to face blocks above or below them
|
||||
- Smart observer will now also emit redstone when the block in front of it matches its filter
|
||||
- Fixed non-vanilla signs not accepted as valid display targets
|
||||
- Brass tunnels with no distribution behaviour no longer show the mode switcher
|
||||
- Used more contrasting colours for diode and tunnel value inputs
|
||||
- Fixed crash when hose pulley cannot find reference fluid for infinite draining
|
||||
- Clipboards can now be used to transfer settings between blocks
|
||||
- Clipboards can now be used to manually write to Display Boards and Nixie Tubes
|
||||
- Clipboards can now be used as Material Checklists in the Schematicannon
|
||||
- Fixed and edited existing tooltips and ponder scenes to include behavioural changes in 0.5.1
|
||||
- New ponder scenes for Smart Observer, Threshold Switch, Elevator Pulley, Contraption Controls and Mechanical Rollers
|
||||
- Fixed ponder overlay text rendering with wonky pixels
|
||||
- Added a ponder category for recently added/changed blocks
|
||||
- Renamed Filter to List Filter
|
||||
- Deployers can now apply filters to a Redstone link with less required precision
|
||||
- Bezier track segments now render with a slight angle to reduce z-fighting
|
||||
- Fixed offset shaft rotation on encased large cogwheels
|
||||
- Fixed Smart Fluid Pipe not dropping filter when broken
|
||||
- Placards and Creative Crates will no longer hold on to special nbt content (except potion data, damage, enchants) of the contained item when imported via Schematicannon
|
||||
- Schematicannons can no longer print mobs
|
||||
- Fixed item frames not requiring an exact nbt match for printed contents
|
||||
- Players can now sneak while using exp nuggets to only consume one item at a time
|
||||
- Minecart contraption items can no longer be placed in container items like toolboxes or shulkers (configurable)
|
||||
- Implemented ComputerCraft interaction for Speed Controllers, Display Links, Speedometers, Stressometers, Sequenced Gearshifts and Train Stations (caelwarner)
|
||||
- Hand crank no longer drains hunger when using the extendo grip (Xstoudi)
|
||||
- Fixed Encased Chain Drives not reacting to block rotation and mirroring correctly
|
||||
- Open Ended Pipes now correctly handle Builder's Tea (NerdsOfAFeather)
|
||||
- Added Config entry for brass tunnel distribution cooldown (Walle123)
|
||||
- API for custom bogey & track types (Rabbitminers, techno-sam)
|
||||
- Fixed server crash caused by Gantry Contraptions assembling (Lucasmellof)
|
||||
- Fix "Lighter than air" fluids displayed incorrectly in spouts (cakeGit)
|
||||
- Added rotate and mirror methods to Fluid Pipes (xieve)
|
||||
- Chocolate & Honey fluid fog distance is now configurable (radimous)
|
||||
- Added a TrackGraph merge event (DaComputerNerd717)
|
||||
- Fixed players dismounting when trains get assembled (Equinoxxe)
|
||||
- Added GameTests (TropheusJ)
|
||||
- Added armor tags (NerdsOfAFeather)
|
||||
- Major updates now release as patch A
|
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
@ -49,6 +49,8 @@ body:
|
|||
label: Mod Version
|
||||
description: The version of the mod you were using when the bug occured
|
||||
options:
|
||||
- "0.5.1d"
|
||||
- "0.5.1c"
|
||||
- "0.5.1b"
|
||||
- "0.5.1a"
|
||||
- "0.5.0i"
|
||||
|
@ -114,6 +116,7 @@ body:
|
|||
label: Minecraft Version
|
||||
description: The version of Minecraft you were using when the bug occured
|
||||
options:
|
||||
- "1.20.1"
|
||||
- "1.19.2"
|
||||
- "1.18.2"
|
||||
- "1.18.1"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<p align="center"><img src="https://i.imgur.com/SXaePW6.png" alt="Logo" width="200"></p>
|
||||
<h1 align="center">Create <br>
|
||||
<a href="https://www.patreon.com/simibubi"><img src="https://img.shields.io/badge/Supporters-110-ff5733" alt="Patreon"></a>
|
||||
<a href="https://www.curseforge.com/minecraft/mc-mods/create/files"><img src="https://img.shields.io/badge/Available%20for-MC%201.14%20to%201.18-c70039" alt="Supported Versions"></a>
|
||||
<a href="https://www.patreon.com/simibubi"><img src="https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dsimibubi%26type%3Dpatrons&style=flat&label=Supporters&color=ff5733" alt="Patreon"></a>
|
||||
<a href="https://www.curseforge.com/minecraft/mc-mods/create/files"><img src="https://cf.way2muchnoise.eu/versions/328085(c70039).svg" alt="Supported Versions"></a>
|
||||
<a href="https://github.com/Creators-of-Create/Create/blob/master/LICENSE"><img src="https://img.shields.io/github/license/Creators-of-Create/Create?style=flat&color=900c3f" alt="License"></a>
|
||||
<a href="https://discord.gg/hmaD7Se"><img src="https://img.shields.io/discord/620934202875183104?color=5865f2&label=Discord&style=flat" alt="Discord"></a>
|
||||
<a href="https://www.curseforge.com/minecraft/mc-mods/create"><img src="http://cf.way2muchnoise.eu/328085.svg" alt="CF"></a>
|
||||
|
|
|
@ -169,7 +169,7 @@ dependencies {
|
|||
jarJar.ranged(it, '[MC1.19.3-1.1.10,)')
|
||||
}
|
||||
jarJar("com.jozufozu.flywheel:flywheel-forge-${flywheel_minecraft_version}:${flywheel_version}") {
|
||||
jarJar.ranged(it, '[0.6.9,0.6.10)')
|
||||
jarJar.ranged(it, '[0.6.10,0.6.11)')
|
||||
}
|
||||
|
||||
implementation fg.deobf("com.tterrag.registrate:Registrate:${registrate_version}")
|
||||
|
|
|
@ -4,7 +4,7 @@ org.gradle.jvmargs = -Xmx3G
|
|||
org.gradle.daemon = false
|
||||
|
||||
# mod version info
|
||||
mod_version = 0.5.1.d
|
||||
mod_version = 0.5.1.e
|
||||
artifact_minecraft_version = 1.20.1
|
||||
|
||||
minecraft_version = 1.20.1
|
||||
|
@ -22,8 +22,8 @@ use_parchment = true
|
|||
|
||||
# dependency versions
|
||||
registrate_version = MC1.20-1.3.3
|
||||
flywheel_minecraft_version = 1.20
|
||||
flywheel_version = 0.6.9-4
|
||||
flywheel_minecraft_version = 1.20.1
|
||||
flywheel_version = 0.6.10-6
|
||||
jei_minecraft_version = 1.20.1
|
||||
jei_version = 15.2.0.22
|
||||
curios_minecraft_version = 1.20.1
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
// 1.20.1 2023-08-24T21:57:44.7330415 Create's Recipe Serializer Tags
|
||||
0d8718f7383761bc5d7bc45306ed266ebf25dc1d data/create/tags/recipe_serializer/automation_ignore.json
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"values": [
|
||||
{
|
||||
"id": "occultism:spirit_trade",
|
||||
"required": false
|
||||
},
|
||||
{
|
||||
"id": "occultism:ritual",
|
||||
"required": false
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,12 +1,10 @@
|
|||
package com.simibubi.create;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.simibubi.create.compat.jei.ConversionRecipe;
|
||||
import com.simibubi.create.content.equipment.sandPaper.SandPaperPolishingRecipe;
|
||||
import com.simibubi.create.content.equipment.toolbox.ToolboxDyeingRecipe;
|
||||
|
@ -16,8 +14,8 @@ import com.simibubi.create.content.kinetics.crafter.MechanicalCraftingRecipe;
|
|||
import com.simibubi.create.content.kinetics.crusher.CrushingRecipe;
|
||||
import com.simibubi.create.content.kinetics.deployer.DeployerApplicationRecipe;
|
||||
import com.simibubi.create.content.kinetics.deployer.ManualApplicationRecipe;
|
||||
import com.simibubi.create.content.kinetics.fan.HauntingRecipe;
|
||||
import com.simibubi.create.content.kinetics.fan.SplashingRecipe;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe;
|
||||
import com.simibubi.create.content.kinetics.millstone.MillingRecipe;
|
||||
import com.simibubi.create.content.kinetics.mixer.CompactingRecipe;
|
||||
import com.simibubi.create.content.kinetics.mixer.MixingRecipe;
|
||||
|
@ -29,7 +27,6 @@ import com.simibubi.create.content.processing.recipe.ProcessingRecipeSerializer;
|
|||
import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipeSerializer;
|
||||
import com.simibubi.create.foundation.recipe.IRecipeTypeInfo;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.simibubi.create.foundation.utility.RegisteredObjects;
|
||||
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -127,12 +124,9 @@ public enum AllRecipeTypes implements IRecipeTypeInfo {
|
|||
.getRecipeFor(getType(), inv, world);
|
||||
}
|
||||
|
||||
public static final Set<ResourceLocation> RECIPE_DENY_SET =
|
||||
ImmutableSet.of(new ResourceLocation("occultism", "spirit_trade"), new ResourceLocation("occultism", "ritual"));
|
||||
|
||||
public static boolean shouldIgnoreInAutomation(Recipe<?> recipe) {
|
||||
RecipeSerializer<?> serializer = recipe.getSerializer();
|
||||
if (serializer != null && RECIPE_DENY_SET.contains(RegisteredObjects.getKeyOrThrow(serializer)))
|
||||
if (serializer != null && AllTags.AllRecipeSerializerTags.AUTOMATION_IGNORE.matches(serializer))
|
||||
return true;
|
||||
return recipe.getId()
|
||||
.getPath()
|
||||
|
|
|
@ -20,6 +20,7 @@ import net.minecraft.world.entity.EntityType;
|
|||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
|
@ -316,11 +317,54 @@ public class AllTags {
|
|||
private static void init() {}
|
||||
|
||||
}
|
||||
|
||||
public enum AllRecipeSerializerTags {
|
||||
|
||||
AUTOMATION_IGNORE,
|
||||
|
||||
;
|
||||
|
||||
public final TagKey<RecipeSerializer<?>> tag;
|
||||
public final boolean alwaysDatagen;
|
||||
|
||||
AllRecipeSerializerTags() {
|
||||
this(MOD);
|
||||
}
|
||||
|
||||
AllRecipeSerializerTags(NameSpace namespace) {
|
||||
this(namespace, namespace.optionalDefault, namespace.alwaysDatagenDefault);
|
||||
}
|
||||
|
||||
AllRecipeSerializerTags(NameSpace namespace, String path) {
|
||||
this(namespace, path, namespace.optionalDefault, namespace.alwaysDatagenDefault);
|
||||
}
|
||||
|
||||
AllRecipeSerializerTags(NameSpace namespace, boolean optional, boolean alwaysDatagen) {
|
||||
this(namespace, null, optional, alwaysDatagen);
|
||||
}
|
||||
|
||||
AllRecipeSerializerTags(NameSpace namespace, String path, boolean optional, boolean alwaysDatagen) {
|
||||
ResourceLocation id = new ResourceLocation(namespace.id, path == null ? Lang.asId(name()) : path);
|
||||
if (optional) {
|
||||
tag = optionalTag(ForgeRegistries.RECIPE_SERIALIZERS, id);
|
||||
} else {
|
||||
tag = TagKey.create(Registries.RECIPE_SERIALIZER, id);
|
||||
}
|
||||
this.alwaysDatagen = alwaysDatagen;
|
||||
}
|
||||
|
||||
public boolean matches(RecipeSerializer<?> recipeSerializer) {
|
||||
return ForgeRegistries.RECIPE_SERIALIZERS.getHolder(recipeSerializer).orElseThrow().is(tag);
|
||||
}
|
||||
|
||||
private static void init() {}
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
AllBlockTags.init();
|
||||
AllItemTags.init();
|
||||
AllFluidTags.init();
|
||||
AllEntityTags.init();
|
||||
AllRecipeSerializerTags.init();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,10 @@ import com.simibubi.create.content.decoration.palettes.AllPaletteBlocks;
|
|||
import com.simibubi.create.content.equipment.potatoCannon.BuiltinPotatoProjectileTypes;
|
||||
import com.simibubi.create.content.fluids.tank.BoilerHeaters;
|
||||
import com.simibubi.create.content.kinetics.TorquePropagator;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.AllFanProcessingTypes;
|
||||
import com.simibubi.create.content.kinetics.mechanicalArm.AllArmInteractionPointTypes;
|
||||
import com.simibubi.create.content.redstone.displayLink.AllDisplayBehaviours;
|
||||
import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler;
|
||||
import com.simibubi.create.content.schematics.SchematicInstances;
|
||||
import com.simibubi.create.content.schematics.ServerSchematicLoader;
|
||||
import com.simibubi.create.content.trains.GlobalRailwayManager;
|
||||
import com.simibubi.create.content.trains.bogey.BogeySizes;
|
||||
|
@ -30,6 +30,7 @@ import com.simibubi.create.foundation.damageTypes.DamageTypeDataProvider;
|
|||
import com.simibubi.create.foundation.damageTypes.DamageTypeTagGen;
|
||||
import com.simibubi.create.foundation.data.CreateRegistrate;
|
||||
import com.simibubi.create.foundation.data.LangMerger;
|
||||
import com.simibubi.create.foundation.data.RecipeSerializerTagGen;
|
||||
import com.simibubi.create.foundation.data.TagGen;
|
||||
import com.simibubi.create.foundation.data.recipe.MechanicalCraftingRecipeGen;
|
||||
import com.simibubi.create.foundation.data.recipe.ProcessingRecipeGen;
|
||||
|
@ -68,7 +69,7 @@ public class Create {
|
|||
|
||||
public static final String ID = "create";
|
||||
public static final String NAME = "Create";
|
||||
public static final String VERSION = "0.5.1d";
|
||||
public static final String VERSION = "0.5.1e";
|
||||
|
||||
public static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
|
@ -110,6 +111,7 @@ public class Create {
|
|||
|
||||
AllSoundEvents.prepare();
|
||||
AllTags.init();
|
||||
AllCreativeModeTabs.register(modEventBus);
|
||||
AllBlocks.register();
|
||||
AllItems.register();
|
||||
AllFluids.register();
|
||||
|
@ -122,20 +124,24 @@ public class Create {
|
|||
AllParticleTypes.register(modEventBus);
|
||||
AllStructureProcessorTypes.register(modEventBus);
|
||||
AllEntityDataSerializers.register(modEventBus);
|
||||
AllPackets.registerPackets();
|
||||
AllFeatures.register(modEventBus);
|
||||
AllPlacementModifiers.register(modEventBus);
|
||||
AllCreativeModeTabs.register(modEventBus);
|
||||
BogeySizes.init();
|
||||
AllBogeyStyles.register();
|
||||
|
||||
AllConfigs.register(modLoadingContext);
|
||||
|
||||
// FIXME: some of these registrations are not thread-safe
|
||||
AllMovementBehaviours.registerDefaults();
|
||||
AllInteractionBehaviours.registerDefaults();
|
||||
AllDisplayBehaviours.registerDefaults();
|
||||
ContraptionMovementSetting.registerDefaults();
|
||||
AllArmInteractionPointTypes.register();
|
||||
AllFanProcessingTypes.register();
|
||||
BlockSpoutingBehaviour.registerDefaults();
|
||||
BogeySizes.init();
|
||||
AllBogeyStyles.register();
|
||||
// ----
|
||||
|
||||
ComputerCraftProxy.register();
|
||||
|
||||
ForgeMod.enableMilkFluid();
|
||||
|
@ -147,20 +153,24 @@ public class Create {
|
|||
|
||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus));
|
||||
|
||||
// FIXME: this is not thread-safe
|
||||
Mods.CURIOS.executeIfInstalled(() -> () -> Curios.init(modEventBus, forgeEventBus));
|
||||
}
|
||||
|
||||
public static void init(final FMLCommonSetupEvent event) {
|
||||
AllPackets.registerPackets();
|
||||
SchematicInstances.register();
|
||||
BuiltinPotatoProjectileTypes.register();
|
||||
AllFluids.registerFluidInteractions();
|
||||
|
||||
event.enqueueWork(() -> {
|
||||
// TODO: custom registration should all happen in one place
|
||||
// Most registration happens in the constructor.
|
||||
// These registrations use Create's registered objects directly so they must run after registration has finished.
|
||||
BuiltinPotatoProjectileTypes.register();
|
||||
BoilerHeaters.registerDefaults();
|
||||
// --
|
||||
|
||||
AttachedRegistry.unwrapAll();
|
||||
AllAdvancements.register();
|
||||
AllTriggers.register();
|
||||
BoilerHeaters.registerDefaults();
|
||||
AllFluids.registerFluidInteractions();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -168,13 +178,14 @@ public class Create {
|
|||
TagGen.datagen();
|
||||
DataGenerator gen = event.getGenerator();
|
||||
PackOutput output = gen.getPackOutput();
|
||||
|
||||
|
||||
if (event.includeClient()) {
|
||||
gen.addProvider(true, AllSoundEvents.provider(gen));
|
||||
LangMerger.attachToRegistrateProvider(gen, output);
|
||||
}
|
||||
|
||||
|
||||
if (event.includeServer()) {
|
||||
gen.addProvider(true, new RecipeSerializerTagGen(output, event.getLookupProvider(), event.getExistingFileHelper()));
|
||||
gen.addProvider(true, new AllAdvancements(output));
|
||||
gen.addProvider(true, new StandardRecipeGen(output));
|
||||
gen.addProvider(true, new MechanicalCraftingRecipeGen(output));
|
||||
|
|
|
@ -14,26 +14,42 @@ import net.minecraftforge.registries.ForgeRegistries;
|
|||
* For compatibility with and without another mod present, we have to define load conditions of the specific code
|
||||
*/
|
||||
public enum Mods {
|
||||
DYNAMICTREES,
|
||||
TCONSTRUCT,
|
||||
CURIOS,
|
||||
|
||||
COMPUTERCRAFT,
|
||||
CONNECTIVITY,
|
||||
CURIOS,
|
||||
DYNAMICTREES,
|
||||
OCCULTISM,
|
||||
PACKETFIXER,
|
||||
STORAGEDRAWERS,
|
||||
TCONSTRUCT,
|
||||
XLPACKETS;
|
||||
|
||||
/**
|
||||
* @return a boolean of whether the mod is loaded or not based on mod id
|
||||
*/
|
||||
public boolean isLoaded() {
|
||||
return ModList.get().isLoaded(asId());
|
||||
private final String id;
|
||||
|
||||
Mods() {
|
||||
id = Lang.asId(name());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mod id
|
||||
*/
|
||||
public String asId() {
|
||||
return Lang.asId(name());
|
||||
public String id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public ResourceLocation rl(String path) {
|
||||
return new ResourceLocation(id, path);
|
||||
}
|
||||
|
||||
public Block getBlock(String id) {
|
||||
return ForgeRegistries.BLOCKS.getValue(rl(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a boolean of whether the mod is loaded or not based on mod id
|
||||
*/
|
||||
public boolean isLoaded() {
|
||||
return ModList.get().isLoaded(id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,8 +72,4 @@ public enum Mods {
|
|||
toExecute.get().run();
|
||||
}
|
||||
}
|
||||
|
||||
public Block getBlock(String id) {
|
||||
return ForgeRegistries.BLOCKS.getValue(new ResourceLocation(asId(), id));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
package com.simibubi.create.compat.curios;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.AllTags;
|
||||
import com.simibubi.create.content.equipment.armor.BacktankUtil;
|
||||
import com.simibubi.create.content.equipment.goggles.GogglesItem;
|
||||
import com.simibubi.create.AllTags;
|
||||
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
@ -19,11 +24,6 @@ import top.theillusivec4.curios.api.SlotTypePreset;
|
|||
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
|
||||
import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class Curios {
|
||||
|
||||
/**
|
||||
|
|
|
@ -51,8 +51,8 @@ import com.simibubi.create.content.kinetics.crusher.AbstractCrushingRecipe;
|
|||
import com.simibubi.create.content.kinetics.deployer.DeployerApplicationRecipe;
|
||||
import com.simibubi.create.content.kinetics.deployer.ItemApplicationRecipe;
|
||||
import com.simibubi.create.content.kinetics.deployer.ManualApplicationRecipe;
|
||||
import com.simibubi.create.content.kinetics.fan.HauntingRecipe;
|
||||
import com.simibubi.create.content.kinetics.fan.SplashingRecipe;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe;
|
||||
import com.simibubi.create.content.kinetics.press.MechanicalPressBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.press.PressingRecipe;
|
||||
import com.simibubi.create.content.kinetics.saw.CuttingRecipe;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.simibubi.create.compat.jei.category;
|
||||
|
||||
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
|
||||
import com.simibubi.create.content.kinetics.fan.HauntingRecipe;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe;
|
||||
import com.simibubi.create.foundation.gui.AllGuiTextures;
|
||||
import com.simibubi.create.foundation.gui.element.GuiGameElement;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.simibubi.create.compat.jei.category;
|
||||
|
||||
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
|
||||
import com.simibubi.create.content.kinetics.fan.SplashingRecipe;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe;
|
||||
import com.simibubi.create.foundation.gui.element.GuiGameElement;
|
||||
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
|
|
|
@ -2,17 +2,17 @@ package com.simibubi.create.compat.storageDrawers;
|
|||
|
||||
import com.simibubi.create.compat.Mods;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
|
||||
import com.simibubi.create.foundation.utility.RegisteredObjects;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
public class StorageDrawers {
|
||||
|
||||
public static boolean isDrawer(BlockEntity be) {
|
||||
return be != null && Mods.STORAGEDRAWERS.asId()
|
||||
.equals(BlockEntityType.getKey(be.getType())
|
||||
return be != null && Mods.STORAGEDRAWERS.id()
|
||||
.equals(RegisteredObjects.getKeyOrThrow(be.getType())
|
||||
.getNamespace());
|
||||
}
|
||||
|
||||
|
|
|
@ -336,7 +336,7 @@ public class BlockMovementChecks {
|
|||
return direction == state.getValue(StickerBlock.FACING)
|
||||
&& !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite());
|
||||
}
|
||||
if (block instanceof AbstractBogeyBlock bogey)
|
||||
if (block instanceof AbstractBogeyBlock<?> bogey)
|
||||
return bogey.getStickySurfaces(world, pos, state)
|
||||
.contains(direction);
|
||||
if (block instanceof WhistleBlock)
|
||||
|
|
|
@ -1379,7 +1379,7 @@ public abstract class Contraption {
|
|||
return blocks.values();
|
||||
}
|
||||
|
||||
public Collection<BlockEntity> getSpecialRenderedTEs() {
|
||||
public Collection<BlockEntity> getSpecialRenderedBEs() {
|
||||
return specialRenderedBlockEntities;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import com.simibubi.create.AllDamageTypes;
|
||||
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
import org.apache.commons.lang3.mutable.MutableFloat;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
|
@ -18,6 +16,7 @@ import org.apache.commons.lang3.tuple.MutablePair;
|
|||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllDamageTypes;
|
||||
import com.simibubi.create.AllMovementBehaviours;
|
||||
import com.simibubi.create.AllPackets;
|
||||
import com.simibubi.create.content.contraptions.AbstractContraptionEntity.ContraptionRotationState;
|
||||
|
|
|
@ -14,17 +14,46 @@ public class ContraptionData {
|
|||
/**
|
||||
* A sane, default maximum for contraption data size.
|
||||
*/
|
||||
public static final int DEFAULT_MAX = 2_000_000;
|
||||
public static final int DEFAULT_LIMIT = 2_000_000;
|
||||
/**
|
||||
* Connectivity expands the NBT packet limit to 2 GB.
|
||||
*/
|
||||
public static final int CONNECTIVITY_LIMIT = Integer.MAX_VALUE;
|
||||
/**
|
||||
* Packet Fixer expands the NBT packet limit to 200 MB.
|
||||
*/
|
||||
public static final int PACKET_FIXER_LIMIT = 209_715_200;
|
||||
/**
|
||||
* XL Packets expands the NBT packet limit to 2 GB.
|
||||
*/
|
||||
public static final int EXPANDED_MAX = 2_000_000_000;
|
||||
public static final int XL_PACKETS_LIMIT = 2_000_000_000;
|
||||
/**
|
||||
* Minecart item sizes are limited by the vanilla slot change packet ({@link ClientboundContainerSetSlotPacket}).
|
||||
* {@link ContraptionData#DEFAULT_MAX} is used as the default.
|
||||
* XL Packets expands the size limit to ~2 GB. If the mod is loaded, we take advantage of it and use the higher limit.
|
||||
* {@link #DEFAULT_LIMIT} is used as the default.
|
||||
* Connectivity, PacketFixer, and XL Packets expand the size limit.
|
||||
* If one of these mods is loaded, we take advantage of it and use the higher limit.
|
||||
*/
|
||||
public static final int PICKUP_MAX = Mods.XLPACKETS.isLoaded() ? EXPANDED_MAX : DEFAULT_MAX;
|
||||
public static final int PICKUP_LIMIT;
|
||||
|
||||
static {
|
||||
int limit = DEFAULT_LIMIT;
|
||||
|
||||
// Check from largest to smallest to use the smallest limit if multiple mods are loaded.
|
||||
// It is necessary to use the smallest limit because even if multiple mods are loaded,
|
||||
// not all of their mixins may be applied. Therefore, it is safest to only assume that
|
||||
// the mod with the smallest limit is actually active.
|
||||
if (Mods.CONNECTIVITY.isLoaded()) {
|
||||
limit = CONNECTIVITY_LIMIT;
|
||||
}
|
||||
if (Mods.XLPACKETS.isLoaded()) {
|
||||
limit = XL_PACKETS_LIMIT;
|
||||
}
|
||||
if (Mods.PACKETFIXER.isLoaded()) {
|
||||
limit = PACKET_FIXER_LIMIT;
|
||||
}
|
||||
|
||||
PICKUP_LIMIT = limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the given NBT is too large for a contraption to be synced to clients.
|
||||
|
@ -38,7 +67,7 @@ public class ContraptionData {
|
|||
* @return true if the given NBT is too large for a contraption to be picked up with a wrench.
|
||||
*/
|
||||
public static boolean isTooLargeForPickup(CompoundTag data) {
|
||||
return packetSize(data) > PICKUP_MAX;
|
||||
return packetSize(data) > PICKUP_LIMIT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,7 +14,6 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
|
|
|
@ -10,7 +10,6 @@ import net.minecraft.core.Direction;
|
|||
import net.minecraft.core.particles.BlockParticleOption;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
|
|
|
@ -34,7 +34,6 @@ import net.minecraft.client.renderer.RenderType;
|
|||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
@ -118,9 +117,9 @@ public class ContraptionRenderDispatcher {
|
|||
ContraptionWorld contraptionWorld = c.getContraptionWorld();
|
||||
|
||||
BlockPos origin = c.anchor;
|
||||
int height = contraptionWorld.getHeight();
|
||||
int minBuildHeight = contraptionWorld.getMinBuildHeight();
|
||||
VirtualRenderWorld renderWorld = new VirtualRenderWorld(world, origin, height, minBuildHeight) {
|
||||
int height = contraptionWorld.getHeight();
|
||||
VirtualRenderWorld renderWorld = new VirtualRenderWorld(world, minBuildHeight, height, origin) {
|
||||
@Override
|
||||
public boolean supportsFlywheel() {
|
||||
return canInstance();
|
||||
|
@ -134,13 +133,13 @@ public class ContraptionRenderDispatcher {
|
|||
// FIXME 1.20 this '0' used to be Block.UPDATE_SUPPRESS_LIGHT, yet VirtualRenderWorld didn't actually parse the flags at all
|
||||
renderWorld.setBlock(info.pos(), info.state(), 0);
|
||||
|
||||
renderWorld.runLightingEngine();
|
||||
renderWorld.runLightEngine();
|
||||
return renderWorld;
|
||||
}
|
||||
|
||||
public static void renderBlockEntities(Level world, VirtualRenderWorld renderWorld, Contraption c,
|
||||
ContraptionMatrices matrices, MultiBufferSource buffer) {
|
||||
BlockEntityRenderHelper.renderBlockEntities(world, renderWorld, c.getSpecialRenderedTEs(),
|
||||
BlockEntityRenderHelper.renderBlockEntities(world, renderWorld, c.getSpecialRenderedBEs(),
|
||||
matrices.getModelViewProjection(), matrices.getLight(), buffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import com.simibubi.create.foundation.networking.SimplePacketBase;
|
|||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.network.NetworkEvent.Context;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
|
|
|
@ -31,15 +31,14 @@ public class CopycatBarsModel extends CopycatModel {
|
|||
protected List<BakedQuad> getCroppedQuads(BlockState state, Direction side, RandomSource rand, BlockState material,
|
||||
ModelData wrappedData, RenderType renderType) {
|
||||
BakedModel model = getModelOf(material);
|
||||
List<BakedQuad> templateQuads = model.getQuads(material, null, rand, wrappedData, renderType);
|
||||
List<BakedQuad> superQuads = originalModel.getQuads(state, side, rand, wrappedData, renderType);
|
||||
List<BakedQuad> quads = new ArrayList<>();
|
||||
TextureAtlasSprite targetSprite = model.getParticleIcon(wrappedData);
|
||||
|
||||
boolean vertical = state.getValue(CopycatPanelBlock.FACING)
|
||||
.getAxis() == Axis.Y;
|
||||
|
||||
if (side != null && (vertical || side.getAxis() == Axis.Y))
|
||||
if (side != null && (vertical || side.getAxis() == Axis.Y)) {
|
||||
List<BakedQuad> templateQuads = model.getQuads(material, null, rand, wrappedData, renderType);
|
||||
for (int i = 0; i < templateQuads.size(); i++) {
|
||||
BakedQuad quad = templateQuads.get(i);
|
||||
if (quad.getDirection() != Direction.UP)
|
||||
|
@ -47,10 +46,13 @@ public class CopycatBarsModel extends CopycatModel {
|
|||
targetSprite = quad.getSprite();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetSprite == null)
|
||||
return superQuads;
|
||||
|
||||
List<BakedQuad> quads = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < superQuads.size(); i++) {
|
||||
BakedQuad quad = superQuads.get(i);
|
||||
TextureAtlasSprite original = quad.getSprite();
|
||||
|
|
|
@ -16,7 +16,6 @@ import com.simibubi.create.foundation.utility.Iterate;
|
|||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.simibubi.create.content.decoration.copycat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -110,14 +111,24 @@ public abstract class CopycatModel extends BakedModelWrapperWithData {
|
|||
|
||||
// Rubidium: render side!=null versions of the base material during side==null,
|
||||
// to avoid getting culled away
|
||||
if (side == null && state.getBlock() instanceof CopycatBlock ccb)
|
||||
if (side == null && state.getBlock() instanceof CopycatBlock ccb) {
|
||||
boolean immutable = true;
|
||||
for (Direction nonOcclusionSide : Iterate.directions)
|
||||
if (ccb.shouldFaceAlwaysRender(state, nonOcclusionSide))
|
||||
if (ccb.shouldFaceAlwaysRender(state, nonOcclusionSide)) {
|
||||
if (immutable) {
|
||||
croppedQuads = new ArrayList<>(croppedQuads);
|
||||
immutable = false;
|
||||
}
|
||||
croppedQuads.addAll(getCroppedQuads(state, nonOcclusionSide, rand, material, wrappedData, renderType));
|
||||
}
|
||||
}
|
||||
|
||||
return croppedQuads;
|
||||
}
|
||||
|
||||
/**
|
||||
* The returned list must not be mutated.
|
||||
*/
|
||||
protected abstract List<BakedQuad> getCroppedQuads(BlockState state, Direction side, RandomSource rand,
|
||||
BlockState material, ModelData wrappedData, RenderType renderType);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.simibubi.create.content.equipment.armor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||
|
@ -22,8 +23,6 @@ import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent;
|
|||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@EventBusSubscriber
|
||||
public class DivingHelmetItem extends BaseArmorItem {
|
||||
public static final EquipmentSlot SLOT = EquipmentSlot.HEAD;
|
||||
|
|
|
@ -7,7 +7,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.google.j2objc.annotations.ReflectionSupport.Level;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintCraftingInventory;
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.simibubi.create.content.equipment.goggles;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
|
||||
import com.simibubi.create.foundation.gui.element.GuiGameElement;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.simibubi.create.content.equipment.potatoCannon;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.simibubi.create.AllDamageTypes;
|
||||
import com.simibubi.create.AllEnchantments;
|
||||
import com.simibubi.create.AllSoundEvents;
|
||||
|
@ -37,8 +39,6 @@ import net.minecraftforge.entity.IEntityAdditionalSpawnData;
|
|||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PotatoProjectileEntity extends AbstractHurtingProjectile implements IEntityAdditionalSpawnData {
|
||||
|
||||
protected PotatoCannonProjectileType type;
|
||||
|
|
|
@ -13,7 +13,6 @@ import com.simibubi.create.foundation.item.render.SimpleCustomRenderer;
|
|||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.entity.vehicle.AbstractMinecart;
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.simibubi.create.content.kinetics.belt.transport;
|
|||
import java.util.Random;
|
||||
|
||||
import com.simibubi.create.content.kinetics.belt.BeltHelper;
|
||||
import com.simibubi.create.content.kinetics.fan.FanProcessing;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.FanProcessingType;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
@ -25,7 +25,7 @@ public class TransportedItemStack implements Comparable<TransportedItemStack> {
|
|||
public float prevBeltPosition;
|
||||
public float prevSideOffset;
|
||||
|
||||
public FanProcessing.Type processedBy;
|
||||
public FanProcessingType processedBy;
|
||||
public int processingTime;
|
||||
|
||||
public TransportedItemStack(ItemStack stack) {
|
||||
|
|
|
@ -16,4 +16,9 @@ public abstract class AbstractCrushingRecipe extends ProcessingRecipe<RecipeWrap
|
|||
protected int getMaxInputCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canSpecifyDuration() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import net.minecraft.core.Direction.Axis;
|
|||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
|
|
@ -10,7 +10,9 @@ import com.simibubi.create.AllTags;
|
|||
import com.simibubi.create.content.decoration.copycat.CopycatBlock;
|
||||
import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour;
|
||||
import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult;
|
||||
import com.simibubi.create.content.kinetics.fan.FanProcessing.Type;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.AllFanProcessingTypes;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.FanProcessing;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.FanProcessingType;
|
||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
@ -29,7 +31,6 @@ import net.minecraft.world.entity.item.ItemEntity;
|
|||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
@ -49,7 +50,7 @@ public class AirCurrent {
|
|||
public boolean pushing;
|
||||
public float maxDistance;
|
||||
|
||||
protected List<Pair<TransportedItemStackHandlerBehaviour, FanProcessing.Type>> affectedItemHandlers =
|
||||
protected List<Pair<TransportedItemStackHandlerBehaviour, FanProcessingType>> affectedItemHandlers =
|
||||
new ArrayList<>();
|
||||
protected List<Entity> caughtEntities = new ArrayList<>();
|
||||
|
||||
|
@ -110,14 +111,14 @@ public class AirCurrent {
|
|||
((ServerPlayer) entity).connection.aboveGroundTickCount = 0;
|
||||
|
||||
entityDistance -= .5f;
|
||||
FanProcessing.Type processingType = getSegmentAt((float) entityDistance);
|
||||
FanProcessingType processingType = getSegmentAt((float) entityDistance);
|
||||
|
||||
if (processingType == null || processingType == Type.NONE)
|
||||
if (processingType == AllFanProcessingTypes.NONE)
|
||||
continue;
|
||||
|
||||
if (entity instanceof ItemEntity itemEntity) {
|
||||
if (world.isClientSide) {
|
||||
processingType.spawnParticlesForProcessing(world, entity.position());
|
||||
if (world != null && world.isClientSide) {
|
||||
processingType.spawnProcessingParticles(world, entity.position());
|
||||
continue;
|
||||
}
|
||||
if (FanProcessing.canProcess(itemEntity, processingType))
|
||||
|
@ -127,7 +128,8 @@ public class AirCurrent {
|
|||
continue;
|
||||
}
|
||||
|
||||
processingType.affectEntity(entity, world);
|
||||
if (world != null)
|
||||
processingType.affectEntity(entity, world);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -155,7 +157,7 @@ public class AirCurrent {
|
|||
AirCurrentSegment currentSegment = new AirCurrentSegment();
|
||||
segments.clear();
|
||||
currentSegment.startOffset = 0;
|
||||
FanProcessing.Type type = Type.NONE;
|
||||
FanProcessingType type = AllFanProcessingTypes.NONE;
|
||||
|
||||
int limit = (int) (maxDistance + .5f);
|
||||
int searchStart = pushing ? 0 : limit;
|
||||
|
@ -164,8 +166,8 @@ public class AirCurrent {
|
|||
|
||||
for (int i = searchStart; i * searchStep <= searchEnd * searchStep; i += searchStep) {
|
||||
BlockPos currentPos = start.relative(direction, i);
|
||||
FanProcessing.Type newType = FanProcessing.Type.byBlock(world, currentPos);
|
||||
if (newType != Type.NONE)
|
||||
FanProcessingType newType = FanProcessingType.getAt(world, currentPos);
|
||||
if (newType != AllFanProcessingTypes.NONE)
|
||||
type = newType;
|
||||
if (currentSegment.type != type || currentSegment.startOffset == 0) {
|
||||
currentSegment.endOffset = i;
|
||||
|
@ -258,21 +260,18 @@ public class AirCurrent {
|
|||
BlockPos start = source.getAirCurrentPos();
|
||||
affectedItemHandlers.clear();
|
||||
for (int i = 0; i < maxDistance + 1; i++) {
|
||||
Type type = getSegmentAt(i);
|
||||
if (type == null)
|
||||
continue;
|
||||
|
||||
FanProcessingType segmentType = getSegmentAt(i);
|
||||
for (int offset : Iterate.zeroAndOne) {
|
||||
BlockPos pos = start.relative(direction, i)
|
||||
.below(offset);
|
||||
TransportedItemStackHandlerBehaviour behaviour =
|
||||
BlockEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE);
|
||||
FanProcessing.Type typeAtHandler = type;
|
||||
if (world.getFluidState(pos)
|
||||
.is(Fluids.WATER))
|
||||
typeAtHandler = Type.SPLASHING;
|
||||
if (behaviour != null)
|
||||
affectedItemHandlers.add(Pair.of(behaviour, typeAtHandler));
|
||||
if (behaviour == null)
|
||||
continue;
|
||||
FanProcessingType type = FanProcessingType.getAt(world, pos);
|
||||
if (type == AllFanProcessingTypes.NONE)
|
||||
type = segmentType;
|
||||
affectedItemHandlers.add(Pair.of(behaviour, type));
|
||||
if (direction.getAxis()
|
||||
.isVertical())
|
||||
break;
|
||||
|
@ -281,15 +280,14 @@ public class AirCurrent {
|
|||
}
|
||||
|
||||
public void tickAffectedHandlers() {
|
||||
for (Pair<TransportedItemStackHandlerBehaviour, Type> pair : affectedItemHandlers) {
|
||||
for (Pair<TransportedItemStackHandlerBehaviour, FanProcessingType> pair : affectedItemHandlers) {
|
||||
TransportedItemStackHandlerBehaviour handler = pair.getKey();
|
||||
Level world = handler.getWorld();
|
||||
FanProcessing.Type processingType = pair.getRight();
|
||||
FanProcessingType processingType = pair.getRight();
|
||||
|
||||
handler.handleProcessingOnAllItems((transported) -> {
|
||||
handler.handleProcessingOnAllItems(transported -> {
|
||||
if (world.isClientSide) {
|
||||
if (world != null)
|
||||
processingType.spawnParticlesForProcessing(world, handler.getWorldPositionOf(transported));
|
||||
processingType.spawnProcessingParticles(world, handler.getWorldPositionOf(transported));
|
||||
return TransportedResult.doNothing();
|
||||
}
|
||||
TransportedResult applyProcessing = FanProcessing.applyProcessing(transported, world, processingType);
|
||||
|
@ -304,7 +302,7 @@ public class AirCurrent {
|
|||
return AllTags.AllBlockTags.FAN_TRANSPARENT.matches(state);
|
||||
}
|
||||
|
||||
public FanProcessing.Type getSegmentAt(float offset) {
|
||||
public FanProcessingType getSegmentAt(float offset) {
|
||||
for (AirCurrentSegment airCurrentSegment : segments) {
|
||||
if (offset > airCurrentSegment.endOffset && pushing)
|
||||
continue;
|
||||
|
@ -312,11 +310,11 @@ public class AirCurrent {
|
|||
continue;
|
||||
return airCurrentSegment.type;
|
||||
}
|
||||
return FanProcessing.Type.NONE;
|
||||
return AllFanProcessingTypes.NONE;
|
||||
}
|
||||
|
||||
public static class AirCurrentSegment {
|
||||
FanProcessing.Type type;
|
||||
FanProcessingType type;
|
||||
int startOffset;
|
||||
int endOffset;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@ package com.simibubi.create.content.kinetics.fan;
|
|||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.simibubi.create.foundation.utility.Color;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.AllFanProcessingTypes;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.FanProcessingType;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
|
@ -13,16 +14,15 @@ import net.minecraft.client.particle.SimpleAnimatedParticle;
|
|||
import net.minecraft.client.particle.SpriteSet;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.particles.BlockParticleOption;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class AirFlowParticle extends SimpleAnimatedParticle {
|
||||
|
||||
private final IAirCurrentSource source;
|
||||
private final Access access = new Access();
|
||||
|
||||
protected AirFlowParticle(ClientLevel world, IAirCurrentSource source, double x, double y, double z,
|
||||
SpriteSet sprite) {
|
||||
|
@ -32,11 +32,12 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
|
|||
this.lifetime = 40;
|
||||
hasPhysics = false;
|
||||
selectSprite(7);
|
||||
Vec3 offset = VecHelper.offsetRandomly(Vec3.ZERO, world.random, .25f);
|
||||
Vec3 offset = VecHelper.offsetRandomly(Vec3.ZERO, random, .25f);
|
||||
this.setPos(x + offset.x, y + offset.y, z + offset.z);
|
||||
this.xo = x;
|
||||
this.yo = y;
|
||||
this.zo = z;
|
||||
setColor(0xEEEEEE);
|
||||
setAlpha(.25f);
|
||||
}
|
||||
|
||||
|
@ -48,36 +49,44 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
|
|||
@Override
|
||||
public void tick() {
|
||||
if (source == null || source.isSourceRemoved()) {
|
||||
dissipate();
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
this.xo = this.x;
|
||||
this.yo = this.y;
|
||||
this.zo = this.z;
|
||||
if (this.age++ >= this.lifetime) {
|
||||
this.remove();
|
||||
remove();
|
||||
} else {
|
||||
if (source.getAirCurrent() == null || !source.getAirCurrent().bounds.inflate(.25f).contains(x, y, z)) {
|
||||
dissipate();
|
||||
AirCurrent airCurrent = source.getAirCurrent();
|
||||
if (airCurrent == null || !airCurrent.bounds.inflate(.25f).contains(x, y, z)) {
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3 directionVec = Vec3.atLowerCornerOf(source.getAirCurrent().direction.getNormal());
|
||||
Vec3 directionVec = Vec3.atLowerCornerOf(airCurrent.direction.getNormal());
|
||||
Vec3 motion = directionVec.scale(1 / 8f);
|
||||
if (!source.getAirCurrent().pushing)
|
||||
motion = motion.scale(-1);
|
||||
|
||||
double distance = new Vec3(x, y, z).subtract(VecHelper.getCenterOf(source.getAirCurrentPos()))
|
||||
.multiply(directionVec).length() - .5f;
|
||||
if (distance > source.getAirCurrent().maxDistance + 1 || distance < -.25f) {
|
||||
dissipate();
|
||||
if (distance > airCurrent.maxDistance + 1 || distance < -.25f) {
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
motion = motion.scale(source.getAirCurrent().maxDistance - (distance - 1f)).scale(.5f);
|
||||
selectSprite((int) Mth.clamp((distance / source.getAirCurrent().maxDistance) * 8 + level.random.nextInt(4),
|
||||
0, 7));
|
||||
motion = motion.scale(airCurrent.maxDistance - (distance - 1f)).scale(.5f);
|
||||
|
||||
morphType(distance);
|
||||
FanProcessingType type = getType(distance);
|
||||
if (type == AllFanProcessingTypes.NONE) {
|
||||
setColor(0xEEEEEE);
|
||||
setAlpha(.25f);
|
||||
selectSprite((int) Mth.clamp((distance / airCurrent.maxDistance) * 8 + random.nextInt(4),
|
||||
0, 7));
|
||||
} else {
|
||||
type.morphAirFlow(access, random);
|
||||
selectSprite(random.nextInt(3));
|
||||
}
|
||||
|
||||
xd = motion.x;
|
||||
yd = motion.y;
|
||||
|
@ -93,68 +102,10 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
|
|||
|
||||
}
|
||||
|
||||
public void morphType(double distance) {
|
||||
private FanProcessingType getType(double distance) {
|
||||
if (source.getAirCurrent() == null)
|
||||
return;
|
||||
FanProcessing.Type type = source.getAirCurrent().getSegmentAt((float) distance);
|
||||
|
||||
if (type == FanProcessing.Type.SPLASHING) {
|
||||
setColor(Color.mixColors(0x4499FF, 0x2277FF, level.random.nextFloat()));
|
||||
setAlpha(1f);
|
||||
selectSprite(level.random.nextInt(3));
|
||||
if (level.random.nextFloat() < 1 / 32f)
|
||||
level.addParticle(ParticleTypes.BUBBLE, x, y, z, xd * .125f, yd * .125f,
|
||||
zd * .125f);
|
||||
if (level.random.nextFloat() < 1 / 32f)
|
||||
level.addParticle(ParticleTypes.BUBBLE_POP, x, y, z, xd * .125f, yd * .125f,
|
||||
zd * .125f);
|
||||
}
|
||||
|
||||
if (type == FanProcessing.Type.SMOKING) {
|
||||
setColor(Color.mixColors(0x0, 0x555555, level.random.nextFloat()));
|
||||
setAlpha(1f);
|
||||
selectSprite(level.random.nextInt(3));
|
||||
if (level.random.nextFloat() < 1 / 32f)
|
||||
level.addParticle(ParticleTypes.SMOKE, x, y, z, xd * .125f, yd * .125f,
|
||||
zd * .125f);
|
||||
if (level.random.nextFloat() < 1 / 32f)
|
||||
level.addParticle(ParticleTypes.LARGE_SMOKE, x, y, z, xd * .125f, yd * .125f,
|
||||
zd * .125f);
|
||||
}
|
||||
|
||||
if (type == FanProcessing.Type.HAUNTING) {
|
||||
setColor(Color.mixColors(0x0, 0x126568, level.random.nextFloat()));
|
||||
setAlpha(1f);
|
||||
selectSprite(level.random.nextInt(3));
|
||||
if (level.random.nextFloat() < 1 / 128f)
|
||||
level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, x, y, z, xd * .125f, yd * .125f,
|
||||
zd * .125f);
|
||||
if (level.random.nextFloat() < 1 / 32f)
|
||||
level.addParticle(ParticleTypes.SMOKE, x, y, z, xd * .125f, yd * .125f,
|
||||
zd * .125f);
|
||||
}
|
||||
|
||||
if (type == FanProcessing.Type.BLASTING) {
|
||||
setColor(Color.mixColors(0xFF4400, 0xFF8855, level.random.nextFloat()));
|
||||
setAlpha(.5f);
|
||||
selectSprite(level.random.nextInt(3));
|
||||
if (level.random.nextFloat() < 1 / 32f)
|
||||
level.addParticle(ParticleTypes.FLAME, x, y, z, xd * .25f, yd * .25f,
|
||||
zd * .25f);
|
||||
if (level.random.nextFloat() < 1 / 16f)
|
||||
level.addParticle(new BlockParticleOption(ParticleTypes.BLOCK, Blocks.LAVA.defaultBlockState()), x, y,
|
||||
z, xd * .25f, yd * .25f, zd * .25f);
|
||||
}
|
||||
|
||||
if (type == null) {
|
||||
setColor(0xEEEEEE);
|
||||
setAlpha(.25f);
|
||||
setSize(.2f, .2f);
|
||||
}
|
||||
}
|
||||
|
||||
private void dissipate() {
|
||||
remove();
|
||||
return AllFanProcessingTypes.NONE;
|
||||
return source.getAirCurrent().getSegmentAt((float) distance);
|
||||
}
|
||||
|
||||
public int getLightColor(float partialTick) {
|
||||
|
@ -182,4 +133,21 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
|
|||
}
|
||||
}
|
||||
|
||||
private class Access implements FanProcessingType.AirFlowParticleAccess {
|
||||
@Override
|
||||
public void setColor(int color) {
|
||||
AirFlowParticle.this.setColor(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(float alpha) {
|
||||
AirFlowParticle.this.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnExtraParticle(ParticleOptions options, float speedMultiplier) {
|
||||
level.addParticle(options, x, y, z, xd * speedMultiplier, yd * speedMultiplier, zd * speedMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,451 +0,0 @@
|
|||
package com.simibubi.create.content.kinetics.fan;
|
||||
|
||||
import static com.simibubi.create.content.processing.burner.BlazeBurnerBlock.getHeatLevelOf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.simibubi.create.AllDamageTypes;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult;
|
||||
import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack;
|
||||
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
|
||||
import com.simibubi.create.content.processing.burner.LitBlazeBurnerBlock;
|
||||
import com.simibubi.create.foundation.recipe.RecipeApplier;
|
||||
import com.simibubi.create.foundation.utility.Color;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.infrastructure.config.AllConfigs;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.particles.DustParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.animal.horse.Horse;
|
||||
import net.minecraft.world.entity.animal.horse.SkeletonHorse;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.monster.EnderMan;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.AbstractCookingRecipe;
|
||||
import net.minecraft.world.item.crafting.BlastingRecipe;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.item.crafting.SmeltingRecipe;
|
||||
import net.minecraft.world.item.crafting.SmokingRecipe;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.CampfireBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||
|
||||
public class FanProcessing {
|
||||
private static final RecipeWrapper RECIPE_WRAPPER = new RecipeWrapper(new ItemStackHandler(1));
|
||||
private static final SplashingWrapper SPLASHING_WRAPPER = new SplashingWrapper();
|
||||
private static final HauntingWrapper HAUNTING_WRAPPER = new HauntingWrapper();
|
||||
|
||||
public static boolean canProcess(ItemEntity entity, Type type) {
|
||||
if (entity.getPersistentData()
|
||||
.contains("CreateData")) {
|
||||
CompoundTag compound = entity.getPersistentData()
|
||||
.getCompound("CreateData");
|
||||
if (compound.contains("Processing")) {
|
||||
CompoundTag processing = compound.getCompound("Processing");
|
||||
|
||||
if (Type.valueOf(processing.getString("Type")) != type)
|
||||
return type.canProcess(entity.getItem(), entity.level());
|
||||
else if (processing.getInt("Time") >= 0)
|
||||
return true;
|
||||
else if (processing.getInt("Time") == -1)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return type.canProcess(entity.getItem(), entity.level());
|
||||
}
|
||||
|
||||
public static boolean isWashable(ItemStack stack, Level world) {
|
||||
SPLASHING_WRAPPER.setItem(0, stack);
|
||||
Optional<SplashingRecipe> recipe = AllRecipeTypes.SPLASHING.find(SPLASHING_WRAPPER, world);
|
||||
return recipe.isPresent();
|
||||
}
|
||||
|
||||
public static boolean isHauntable(ItemStack stack, Level world) {
|
||||
HAUNTING_WRAPPER.setItem(0, stack);
|
||||
Optional<HauntingRecipe> recipe = AllRecipeTypes.HAUNTING.find(HAUNTING_WRAPPER, world);
|
||||
return recipe.isPresent();
|
||||
}
|
||||
|
||||
public static boolean applyProcessing(ItemEntity entity, Type type) {
|
||||
if (decrementProcessingTime(entity, type) != 0)
|
||||
return false;
|
||||
List<ItemStack> stacks = process(entity.getItem(), type, entity.level());
|
||||
if (stacks == null)
|
||||
return false;
|
||||
if (stacks.isEmpty()) {
|
||||
entity.discard();
|
||||
return false;
|
||||
}
|
||||
entity.setItem(stacks.remove(0));
|
||||
for (ItemStack additional : stacks) {
|
||||
ItemEntity entityIn = new ItemEntity(entity.level(), entity.getX(), entity.getY(), entity.getZ(), additional);
|
||||
entityIn.setDeltaMovement(entity.getDeltaMovement());
|
||||
entity.level().addFreshEntity(entityIn);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static TransportedResult applyProcessing(TransportedItemStack transported, Level world, Type type) {
|
||||
TransportedResult ignore = TransportedResult.doNothing();
|
||||
if (transported.processedBy != type) {
|
||||
transported.processedBy = type;
|
||||
int timeModifierForStackSize = ((transported.stack.getCount() - 1) / 16) + 1;
|
||||
int processingTime =
|
||||
(int) (AllConfigs.server().kinetics.fanProcessingTime.get() * timeModifierForStackSize) + 1;
|
||||
transported.processingTime = processingTime;
|
||||
if (!type.canProcess(transported.stack, world))
|
||||
transported.processingTime = -1;
|
||||
return ignore;
|
||||
}
|
||||
if (transported.processingTime == -1)
|
||||
return ignore;
|
||||
if (transported.processingTime-- > 0)
|
||||
return ignore;
|
||||
|
||||
List<ItemStack> stacks = process(transported.stack, type, world);
|
||||
if (stacks == null)
|
||||
return ignore;
|
||||
|
||||
List<TransportedItemStack> transportedStacks = new ArrayList<>();
|
||||
for (ItemStack additional : stacks) {
|
||||
TransportedItemStack newTransported = transported.getSimilar();
|
||||
newTransported.stack = additional.copy();
|
||||
transportedStacks.add(newTransported);
|
||||
}
|
||||
return TransportedResult.convertTo(transportedStacks);
|
||||
}
|
||||
|
||||
private static List<ItemStack> process(ItemStack stack, Type type, Level world) {
|
||||
if (type == Type.SPLASHING) {
|
||||
SPLASHING_WRAPPER.setItem(0, stack);
|
||||
Optional<SplashingRecipe> recipe = AllRecipeTypes.SPLASHING.find(SPLASHING_WRAPPER, world);
|
||||
if (recipe.isPresent())
|
||||
return RecipeApplier.applyRecipeOn(world, stack, recipe.get());
|
||||
return null;
|
||||
}
|
||||
if (type == Type.HAUNTING) {
|
||||
HAUNTING_WRAPPER.setItem(0, stack);
|
||||
Optional<HauntingRecipe> recipe = AllRecipeTypes.HAUNTING.find(HAUNTING_WRAPPER, world);
|
||||
if (recipe.isPresent())
|
||||
return RecipeApplier.applyRecipeOn(world, stack, recipe.get());
|
||||
return null;
|
||||
}
|
||||
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<SmokingRecipe> smokingRecipe = world.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMOKING, RECIPE_WRAPPER, world);
|
||||
|
||||
if (type == Type.BLASTING) {
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<? extends AbstractCookingRecipe> smeltingRecipe = world.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMELTING, RECIPE_WRAPPER, world);
|
||||
if (!smeltingRecipe.isPresent()) {
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
smeltingRecipe = world.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.BLASTING, RECIPE_WRAPPER, world);
|
||||
}
|
||||
|
||||
if (smeltingRecipe.isPresent()) {
|
||||
RegistryAccess registryAccess = world.registryAccess();
|
||||
if (smokingRecipe.isEmpty() || !ItemStack.isSameItem(smokingRecipe.get()
|
||||
.getResultItem(registryAccess),
|
||||
smeltingRecipe.get()
|
||||
.getResultItem(registryAccess))) {
|
||||
return RecipeApplier.applyRecipeOn(world, stack, smeltingRecipe.get());
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (type == Type.SMOKING && smokingRecipe.isPresent())
|
||||
return RecipeApplier.applyRecipeOn(world, stack, smokingRecipe.get());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int decrementProcessingTime(ItemEntity entity, Type type) {
|
||||
CompoundTag nbt = entity.getPersistentData();
|
||||
|
||||
if (!nbt.contains("CreateData"))
|
||||
nbt.put("CreateData", new CompoundTag());
|
||||
CompoundTag createData = nbt.getCompound("CreateData");
|
||||
|
||||
if (!createData.contains("Processing"))
|
||||
createData.put("Processing", new CompoundTag());
|
||||
CompoundTag processing = createData.getCompound("Processing");
|
||||
|
||||
if (!processing.contains("Type") || Type.valueOf(processing.getString("Type")) != type) {
|
||||
processing.putString("Type", type.name());
|
||||
int timeModifierForStackSize = ((entity.getItem()
|
||||
.getCount() - 1) / 16) + 1;
|
||||
int processingTime =
|
||||
(int) (AllConfigs.server().kinetics.fanProcessingTime.get() * timeModifierForStackSize) + 1;
|
||||
processing.putInt("Time", processingTime);
|
||||
}
|
||||
|
||||
int value = processing.getInt("Time") - 1;
|
||||
processing.putInt("Time", value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
SPLASHING {
|
||||
@Override
|
||||
public void spawnParticlesForProcessing(Level level, Vec3 pos) {
|
||||
if (level.random.nextInt(8) != 0)
|
||||
return;
|
||||
Vector3f color = new Color(0x0055FF).asVectorF();
|
||||
level.addParticle(new DustParticleOptions(color, 1), pos.x + (level.random.nextFloat() - .5f) * .5f,
|
||||
pos.y + .5f, pos.z + (level.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0);
|
||||
level.addParticle(ParticleTypes.SPIT, pos.x + (level.random.nextFloat() - .5f) * .5f, pos.y + .5f,
|
||||
pos.z + (level.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void affectEntity(Entity entity, Level level) {
|
||||
if (level.isClientSide)
|
||||
return;
|
||||
|
||||
if (entity instanceof EnderMan || entity.getType() == EntityType.SNOW_GOLEM
|
||||
|| entity.getType() == EntityType.BLAZE) {
|
||||
entity.hurt(entity.damageSources().drown(), 2);
|
||||
}
|
||||
if (entity.isOnFire()) {
|
||||
entity.clearFire();
|
||||
level.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE,
|
||||
SoundSource.NEUTRAL, 0.7F, 1.6F + (level.random.nextFloat() - level.random.nextFloat()) * 0.4F);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
return isWashable(stack, level);
|
||||
}
|
||||
},
|
||||
SMOKING {
|
||||
@Override
|
||||
public void spawnParticlesForProcessing(Level level, Vec3 pos) {
|
||||
if (level.random.nextInt(8) != 0)
|
||||
return;
|
||||
level.addParticle(ParticleTypes.POOF, pos.x, pos.y + .25f, pos.z, 0, 1 / 16f, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void affectEntity(Entity entity, Level level) {
|
||||
if (level.isClientSide)
|
||||
return;
|
||||
|
||||
if (!entity.fireImmune()) {
|
||||
entity.setSecondsOnFire(2);
|
||||
entity.hurt(AllDamageTypes.FAN_FIRE.source(level), 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<SmokingRecipe> recipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMOKING, RECIPE_WRAPPER, level);
|
||||
return recipe.isPresent();
|
||||
}
|
||||
},
|
||||
HAUNTING {
|
||||
@Override
|
||||
public void spawnParticlesForProcessing(Level level, Vec3 pos) {
|
||||
if (level.random.nextInt(8) != 0)
|
||||
return;
|
||||
pos = pos.add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1)
|
||||
.multiply(1, 0.05f, 1)
|
||||
.normalize()
|
||||
.scale(0.15f));
|
||||
level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, pos.x, pos.y + .45f, pos.z, 0, 0, 0);
|
||||
if (level.random.nextInt(2) == 0)
|
||||
level.addParticle(ParticleTypes.SMOKE, pos.x, pos.y + .25f, pos.z, 0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void affectEntity(Entity entity, Level level) {
|
||||
if (level.isClientSide) {
|
||||
if (entity instanceof Horse) {
|
||||
Vec3 p = entity.getPosition(0);
|
||||
Vec3 v = p.add(0, 0.5f, 0)
|
||||
.add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1)
|
||||
.multiply(1, 0.2f, 1)
|
||||
.normalize()
|
||||
.scale(1f));
|
||||
level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, v.x, v.y, v.z, 0, 0.1f, 0);
|
||||
if (level.random.nextInt(3) == 0)
|
||||
level.addParticle(ParticleTypes.LARGE_SMOKE, p.x, p.y + .5f, p.z,
|
||||
(level.random.nextFloat() - .5f) * .5f, 0.1f, (level.random.nextFloat() - .5f) * .5f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity instanceof LivingEntity livingEntity) {
|
||||
livingEntity.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 30, 0, false, false));
|
||||
livingEntity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 20, 1, false, false));
|
||||
}
|
||||
if (entity instanceof Horse horse) {
|
||||
int progress = horse.getPersistentData()
|
||||
.getInt("CreateHaunting");
|
||||
if (progress < 100) {
|
||||
if (progress % 10 == 0) {
|
||||
level.playSound(null, entity.blockPosition(), SoundEvents.SOUL_ESCAPE, SoundSource.NEUTRAL,
|
||||
1f, 1.5f * progress / 100f);
|
||||
}
|
||||
horse.getPersistentData()
|
||||
.putInt("CreateHaunting", progress + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
level.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE,
|
||||
SoundSource.NEUTRAL, 1.25f, 0.65f);
|
||||
|
||||
SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(level);
|
||||
CompoundTag serializeNBT = horse.saveWithoutId(new CompoundTag());
|
||||
serializeNBT.remove("UUID");
|
||||
if (!horse.getArmor()
|
||||
.isEmpty())
|
||||
horse.spawnAtLocation(horse.getArmor());
|
||||
|
||||
skeletonHorse.deserializeNBT(serializeNBT);
|
||||
skeletonHorse.setPos(horse.getPosition(0));
|
||||
level.addFreshEntity(skeletonHorse);
|
||||
horse.discard();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
return isHauntable(stack, level);
|
||||
}
|
||||
},
|
||||
BLASTING {
|
||||
@Override
|
||||
public void spawnParticlesForProcessing(Level level, Vec3 pos) {
|
||||
if (level.random.nextInt(8) != 0)
|
||||
return;
|
||||
level.addParticle(ParticleTypes.LARGE_SMOKE, pos.x, pos.y + .25f, pos.z, 0, 1 / 16f, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void affectEntity(Entity entity, Level level) {
|
||||
if (level.isClientSide)
|
||||
return;
|
||||
|
||||
if (!entity.fireImmune()) {
|
||||
entity.setSecondsOnFire(10);
|
||||
entity.hurt(AllDamageTypes.FAN_LAVA.source(level), 4);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<SmeltingRecipe> smeltingRecipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMELTING, RECIPE_WRAPPER, level);
|
||||
|
||||
if (smeltingRecipe.isPresent())
|
||||
return true;
|
||||
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<BlastingRecipe> blastingRecipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.BLASTING, RECIPE_WRAPPER, level);
|
||||
|
||||
if (blastingRecipe.isPresent())
|
||||
return true;
|
||||
|
||||
return !stack.getItem()
|
||||
.isFireResistant();
|
||||
}
|
||||
},
|
||||
NONE {
|
||||
@Override
|
||||
public void spawnParticlesForProcessing(Level level, Vec3 pos) {}
|
||||
|
||||
@Override
|
||||
public void affectEntity(Entity entity, Level level) {}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
public abstract boolean canProcess(ItemStack stack, Level level);
|
||||
|
||||
public abstract void spawnParticlesForProcessing(Level level, Vec3 pos);
|
||||
|
||||
public abstract void affectEntity(Entity entity, Level level);
|
||||
|
||||
public static Type byBlock(BlockGetter reader, BlockPos pos) {
|
||||
FluidState fluidState = reader.getFluidState(pos);
|
||||
if (fluidState.getType() == Fluids.WATER || fluidState.getType() == Fluids.FLOWING_WATER)
|
||||
return Type.SPLASHING;
|
||||
BlockState blockState = reader.getBlockState(pos);
|
||||
Block block = blockState.getBlock();
|
||||
if (block == Blocks.SOUL_FIRE
|
||||
|| block == Blocks.SOUL_CAMPFIRE && blockState.getOptionalValue(CampfireBlock.LIT)
|
||||
.orElse(false)
|
||||
|| AllBlocks.LIT_BLAZE_BURNER.has(blockState)
|
||||
&& blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE)
|
||||
.map(flame -> flame == LitBlazeBurnerBlock.FlameType.SOUL)
|
||||
.orElse(false))
|
||||
return Type.HAUNTING;
|
||||
if (block == Blocks.FIRE
|
||||
|| blockState.is(BlockTags.CAMPFIRES) && blockState.getOptionalValue(CampfireBlock.LIT)
|
||||
.orElse(false)
|
||||
|| AllBlocks.LIT_BLAZE_BURNER.has(blockState)
|
||||
&& blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE)
|
||||
.map(flame -> flame == LitBlazeBurnerBlock.FlameType.REGULAR)
|
||||
.orElse(false)
|
||||
|| getHeatLevelOf(blockState) == BlazeBurnerBlock.HeatLevel.SMOULDERING)
|
||||
return Type.SMOKING;
|
||||
if (block == Blocks.LAVA || getHeatLevelOf(blockState).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING))
|
||||
return Type.BLASTING;
|
||||
return Type.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SplashingWrapper extends RecipeWrapper {
|
||||
public SplashingWrapper() {
|
||||
super(new ItemStackHandler(1));
|
||||
}
|
||||
}
|
||||
|
||||
public static class HauntingWrapper extends RecipeWrapper {
|
||||
public HauntingWrapper() {
|
||||
super(new ItemStackHandler(1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,486 @@
|
|||
package com.simibubi.create.content.kinetics.fan.processing;
|
||||
|
||||
import static com.simibubi.create.content.processing.burner.BlazeBurnerBlock.getHeatLevelOf;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllDamageTypes;
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe.HauntingWrapper;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe.SplashingWrapper;
|
||||
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
|
||||
import com.simibubi.create.content.processing.burner.LitBlazeBurnerBlock;
|
||||
import com.simibubi.create.foundation.recipe.RecipeApplier;
|
||||
import com.simibubi.create.foundation.utility.Color;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.particles.BlockParticleOption;
|
||||
import net.minecraft.core.particles.DustParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.animal.horse.Horse;
|
||||
import net.minecraft.world.entity.animal.horse.SkeletonHorse;
|
||||
import net.minecraft.world.entity.monster.EnderMan;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.AbstractCookingRecipe;
|
||||
import net.minecraft.world.item.crafting.BlastingRecipe;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.item.crafting.SmeltingRecipe;
|
||||
import net.minecraft.world.item.crafting.SmokingRecipe;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.CampfireBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||
|
||||
public class AllFanProcessingTypes {
|
||||
public static final NoneType NONE = register("none", new NoneType());
|
||||
public static final BlastingType BLASTING = register("blasting", new BlastingType());
|
||||
public static final HauntingType HAUNTING = register("haunting", new HauntingType());
|
||||
public static final SmokingType SMOKING = register("smoking", new SmokingType());
|
||||
public static final SplashingType SPLASHING = register("splashing", new SplashingType());
|
||||
|
||||
private static final Map<String, FanProcessingType> LEGACY_NAME_MAP;
|
||||
|
||||
static {
|
||||
Object2ReferenceOpenHashMap<String, FanProcessingType> map = new Object2ReferenceOpenHashMap<>();
|
||||
map.put("NONE", NONE);
|
||||
map.put("BLASTING", BLASTING);
|
||||
map.put("HAUNTING", HAUNTING);
|
||||
map.put("SMOKING", SMOKING);
|
||||
map.put("SPLASHING", SPLASHING);
|
||||
map.trim();
|
||||
LEGACY_NAME_MAP = map;
|
||||
}
|
||||
|
||||
private static <T extends FanProcessingType> T register(String id, T type) {
|
||||
FanProcessingTypeRegistry.register(Create.asResource(id), type);
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static FanProcessingType ofLegacyName(String name) {
|
||||
return LEGACY_NAME_MAP.get(name);
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
}
|
||||
|
||||
public static FanProcessingType parseLegacy(String str) {
|
||||
FanProcessingType type = ofLegacyName(str);
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
return FanProcessingType.parse(str);
|
||||
}
|
||||
|
||||
public static class NoneType implements FanProcessingType {
|
||||
@Override
|
||||
public boolean isValidAt(Level level, BlockPos pos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return -1000000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<ItemStack> process(ItemStack stack, Level level) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnProcessingParticles(Level level, Vec3 pos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void morphAirFlow(AirFlowParticleAccess particleAccess, RandomSource random) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void affectEntity(Entity entity, Level level) {
|
||||
}
|
||||
}
|
||||
|
||||
public static class BlastingType implements FanProcessingType {
|
||||
private static final RecipeWrapper RECIPE_WRAPPER = new RecipeWrapper(new ItemStackHandler(1));
|
||||
|
||||
@Override
|
||||
public boolean isValidAt(Level level, BlockPos pos) {
|
||||
BlockState blockState = level.getBlockState(pos);
|
||||
Block block = blockState.getBlock();
|
||||
return block == Blocks.LAVA || getHeatLevelOf(blockState).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<SmeltingRecipe> smeltingRecipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMELTING, RECIPE_WRAPPER, level);
|
||||
|
||||
if (smeltingRecipe.isPresent())
|
||||
return true;
|
||||
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<BlastingRecipe> blastingRecipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.BLASTING, RECIPE_WRAPPER, level);
|
||||
|
||||
if (blastingRecipe.isPresent())
|
||||
return true;
|
||||
|
||||
return !stack.getItem()
|
||||
.isFireResistant();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<ItemStack> process(ItemStack stack, Level level) {
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<SmokingRecipe> smokingRecipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMOKING, RECIPE_WRAPPER, level);
|
||||
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<? extends AbstractCookingRecipe> smeltingRecipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMELTING, RECIPE_WRAPPER, level);
|
||||
if (!smeltingRecipe.isPresent()) {
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
smeltingRecipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.BLASTING, RECIPE_WRAPPER, level);
|
||||
}
|
||||
|
||||
if (smeltingRecipe.isPresent()) {
|
||||
RegistryAccess registryAccess = level.registryAccess();
|
||||
if (!smokingRecipe.isPresent() || !ItemStack.isSameItem(smokingRecipe.get()
|
||||
.getResultItem(registryAccess),
|
||||
smeltingRecipe.get()
|
||||
.getResultItem(registryAccess))) {
|
||||
return RecipeApplier.applyRecipeOn(level, stack, smeltingRecipe.get());
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnProcessingParticles(Level level, Vec3 pos) {
|
||||
if (level.random.nextInt(8) != 0)
|
||||
return;
|
||||
level.addParticle(ParticleTypes.LARGE_SMOKE, pos.x, pos.y + .25f, pos.z, 0, 1 / 16f, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void morphAirFlow(AirFlowParticleAccess particleAccess, RandomSource random) {
|
||||
particleAccess.setColor(Color.mixColors(0xFF4400, 0xFF8855, random.nextFloat()));
|
||||
particleAccess.setAlpha(.5f);
|
||||
if (random.nextFloat() < 1 / 32f)
|
||||
particleAccess.spawnExtraParticle(ParticleTypes.FLAME, .25f);
|
||||
if (random.nextFloat() < 1 / 16f)
|
||||
particleAccess.spawnExtraParticle(new BlockParticleOption(ParticleTypes.BLOCK, Blocks.LAVA.defaultBlockState()), .25f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void affectEntity(Entity entity, Level level) {
|
||||
if (level.isClientSide)
|
||||
return;
|
||||
|
||||
if (!entity.fireImmune()) {
|
||||
entity.setSecondsOnFire(10);
|
||||
entity.hurt(AllDamageTypes.FAN_LAVA.source(level), 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class HauntingType implements FanProcessingType {
|
||||
private static final HauntingWrapper HAUNTING_WRAPPER = new HauntingWrapper();
|
||||
|
||||
@Override
|
||||
public boolean isValidAt(Level level, BlockPos pos) {
|
||||
BlockState blockState = level.getBlockState(pos);
|
||||
Block block = blockState.getBlock();
|
||||
return block == Blocks.SOUL_FIRE
|
||||
|| block == Blocks.SOUL_CAMPFIRE && blockState.getOptionalValue(CampfireBlock.LIT)
|
||||
.orElse(false)
|
||||
|| AllBlocks.LIT_BLAZE_BURNER.has(blockState)
|
||||
&& blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE)
|
||||
.map(flame -> flame == LitBlazeBurnerBlock.FlameType.SOUL)
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 300;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
HAUNTING_WRAPPER.setItem(0, stack);
|
||||
Optional<HauntingRecipe> recipe = AllRecipeTypes.HAUNTING.find(HAUNTING_WRAPPER, level);
|
||||
return recipe.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<ItemStack> process(ItemStack stack, Level level) {
|
||||
HAUNTING_WRAPPER.setItem(0, stack);
|
||||
Optional<HauntingRecipe> recipe = AllRecipeTypes.HAUNTING.find(HAUNTING_WRAPPER, level);
|
||||
if (recipe.isPresent())
|
||||
return RecipeApplier.applyRecipeOn(level, stack, recipe.get());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnProcessingParticles(Level level, Vec3 pos) {
|
||||
if (level.random.nextInt(8) != 0)
|
||||
return;
|
||||
pos = pos.add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1)
|
||||
.multiply(1, 0.05f, 1)
|
||||
.normalize()
|
||||
.scale(0.15f));
|
||||
level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, pos.x, pos.y + .45f, pos.z, 0, 0, 0);
|
||||
if (level.random.nextInt(2) == 0)
|
||||
level.addParticle(ParticleTypes.SMOKE, pos.x, pos.y + .25f, pos.z, 0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void morphAirFlow(AirFlowParticleAccess particleAccess, RandomSource random) {
|
||||
particleAccess.setColor(Color.mixColors(0x0, 0x126568, random.nextFloat()));
|
||||
particleAccess.setAlpha(1f);
|
||||
if (random.nextFloat() < 1 / 128f)
|
||||
particleAccess.spawnExtraParticle(ParticleTypes.SOUL_FIRE_FLAME, .125f);
|
||||
if (random.nextFloat() < 1 / 32f)
|
||||
particleAccess.spawnExtraParticle(ParticleTypes.SMOKE, .125f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void affectEntity(Entity entity, Level level) {
|
||||
if (level.isClientSide) {
|
||||
if (entity instanceof Horse) {
|
||||
Vec3 p = entity.getPosition(0);
|
||||
Vec3 v = p.add(0, 0.5f, 0)
|
||||
.add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1)
|
||||
.multiply(1, 0.2f, 1)
|
||||
.normalize()
|
||||
.scale(1f));
|
||||
level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, v.x, v.y, v.z, 0, 0.1f, 0);
|
||||
if (level.random.nextInt(3) == 0)
|
||||
level.addParticle(ParticleTypes.LARGE_SMOKE, p.x, p.y + .5f, p.z,
|
||||
(level.random.nextFloat() - .5f) * .5f, 0.1f, (level.random.nextFloat() - .5f) * .5f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity instanceof LivingEntity livingEntity) {
|
||||
livingEntity.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 30, 0, false, false));
|
||||
livingEntity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 20, 1, false, false));
|
||||
}
|
||||
if (entity instanceof Horse horse) {
|
||||
int progress = horse.getPersistentData()
|
||||
.getInt("CreateHaunting");
|
||||
if (progress < 100) {
|
||||
if (progress % 10 == 0) {
|
||||
level.playSound(null, entity.blockPosition(), SoundEvents.SOUL_ESCAPE, SoundSource.NEUTRAL,
|
||||
1f, 1.5f * progress / 100f);
|
||||
}
|
||||
horse.getPersistentData()
|
||||
.putInt("CreateHaunting", progress + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
level.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE,
|
||||
SoundSource.NEUTRAL, 1.25f, 0.65f);
|
||||
|
||||
SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(level);
|
||||
CompoundTag serializeNBT = horse.saveWithoutId(new CompoundTag());
|
||||
serializeNBT.remove("UUID");
|
||||
if (!horse.getArmor()
|
||||
.isEmpty())
|
||||
horse.spawnAtLocation(horse.getArmor());
|
||||
|
||||
skeletonHorse.deserializeNBT(serializeNBT);
|
||||
skeletonHorse.setPos(horse.getPosition(0));
|
||||
level.addFreshEntity(skeletonHorse);
|
||||
horse.discard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SmokingType implements FanProcessingType {
|
||||
private static final RecipeWrapper RECIPE_WRAPPER = new RecipeWrapper(new ItemStackHandler(1));
|
||||
|
||||
@Override
|
||||
public boolean isValidAt(Level level, BlockPos pos) {
|
||||
BlockState blockState = level.getBlockState(pos);
|
||||
Block block = blockState.getBlock();
|
||||
return block == Blocks.FIRE
|
||||
|| blockState.is(BlockTags.CAMPFIRES) && blockState.getOptionalValue(CampfireBlock.LIT)
|
||||
.orElse(false)
|
||||
|| AllBlocks.LIT_BLAZE_BURNER.has(blockState)
|
||||
&& blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE)
|
||||
.map(flame -> flame == LitBlazeBurnerBlock.FlameType.REGULAR)
|
||||
.orElse(false)
|
||||
|| getHeatLevelOf(blockState) == BlazeBurnerBlock.HeatLevel.SMOULDERING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<SmokingRecipe> recipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMOKING, RECIPE_WRAPPER, level);
|
||||
return recipe.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<ItemStack> process(ItemStack stack, Level level) {
|
||||
RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<SmokingRecipe> smokingRecipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMOKING, RECIPE_WRAPPER, level);
|
||||
|
||||
if (smokingRecipe.isPresent())
|
||||
return RecipeApplier.applyRecipeOn(level, stack, smokingRecipe.get());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnProcessingParticles(Level level, Vec3 pos) {
|
||||
if (level.random.nextInt(8) != 0)
|
||||
return;
|
||||
level.addParticle(ParticleTypes.POOF, pos.x, pos.y + .25f, pos.z, 0, 1 / 16f, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void morphAirFlow(AirFlowParticleAccess particleAccess, RandomSource random) {
|
||||
particleAccess.setColor(Color.mixColors(0x0, 0x555555, random.nextFloat()));
|
||||
particleAccess.setAlpha(1f);
|
||||
if (random.nextFloat() < 1 / 32f)
|
||||
particleAccess.spawnExtraParticle(ParticleTypes.SMOKE, .125f);
|
||||
if (random.nextFloat() < 1 / 32f)
|
||||
particleAccess.spawnExtraParticle(ParticleTypes.LARGE_SMOKE, .125f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void affectEntity(Entity entity, Level level) {
|
||||
if (level.isClientSide)
|
||||
return;
|
||||
|
||||
if (!entity.fireImmune()) {
|
||||
entity.setSecondsOnFire(2);
|
||||
entity.hurt(AllDamageTypes.FAN_FIRE.source(level), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SplashingType implements FanProcessingType {
|
||||
private static final SplashingWrapper SPLASHING_WRAPPER = new SplashingWrapper();
|
||||
|
||||
@Override
|
||||
public boolean isValidAt(Level level, BlockPos pos) {
|
||||
FluidState fluidState = level.getFluidState(pos);
|
||||
Fluid fluid = fluidState.getType();
|
||||
return fluid == Fluids.WATER || fluid == Fluids.FLOWING_WATER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 400;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
SPLASHING_WRAPPER.setItem(0, stack);
|
||||
Optional<SplashingRecipe> recipe = AllRecipeTypes.SPLASHING.find(SPLASHING_WRAPPER, level);
|
||||
return recipe.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<ItemStack> process(ItemStack stack, Level level) {
|
||||
SPLASHING_WRAPPER.setItem(0, stack);
|
||||
Optional<SplashingRecipe> recipe = AllRecipeTypes.SPLASHING.find(SPLASHING_WRAPPER, level);
|
||||
if (recipe.isPresent())
|
||||
return RecipeApplier.applyRecipeOn(level, stack, recipe.get());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnProcessingParticles(Level level, Vec3 pos) {
|
||||
if (level.random.nextInt(8) != 0)
|
||||
return;
|
||||
Vector3f color = new Color(0x0055FF).asVectorF();
|
||||
level.addParticle(new DustParticleOptions(color, 1), pos.x + (level.random.nextFloat() - .5f) * .5f,
|
||||
pos.y + .5f, pos.z + (level.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0);
|
||||
level.addParticle(ParticleTypes.SPIT, pos.x + (level.random.nextFloat() - .5f) * .5f, pos.y + .5f,
|
||||
pos.z + (level.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void morphAirFlow(AirFlowParticleAccess particleAccess, RandomSource random) {
|
||||
particleAccess.setColor(Color.mixColors(0x4499FF, 0x2277FF, random.nextFloat()));
|
||||
particleAccess.setAlpha(1f);
|
||||
if (random.nextFloat() < 1 / 32f)
|
||||
particleAccess.spawnExtraParticle(ParticleTypes.BUBBLE, .125f);
|
||||
if (random.nextFloat() < 1 / 32f)
|
||||
particleAccess.spawnExtraParticle(ParticleTypes.BUBBLE_POP, .125f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void affectEntity(Entity entity, Level level) {
|
||||
if (level.isClientSide)
|
||||
return;
|
||||
|
||||
if (entity instanceof EnderMan || entity.getType() == EntityType.SNOW_GOLEM
|
||||
|| entity.getType() == EntityType.BLAZE) {
|
||||
entity.hurt(entity.damageSources().drown(), 2);
|
||||
}
|
||||
if (entity.isOnFire()) {
|
||||
entity.clearFire();
|
||||
level.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE,
|
||||
SoundSource.NEUTRAL, 0.7F, 1.6F + (level.random.nextFloat() - level.random.nextFloat()) * 0.4F);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package com.simibubi.create.content.kinetics.fan.processing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult;
|
||||
import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack;
|
||||
import com.simibubi.create.infrastructure.config.AllConfigs;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
public class FanProcessing {
|
||||
public static boolean canProcess(ItemEntity entity, FanProcessingType type) {
|
||||
if (entity.getPersistentData()
|
||||
.contains("CreateData")) {
|
||||
CompoundTag compound = entity.getPersistentData()
|
||||
.getCompound("CreateData");
|
||||
if (compound.contains("Processing")) {
|
||||
CompoundTag processing = compound.getCompound("Processing");
|
||||
|
||||
if (AllFanProcessingTypes.parseLegacy(processing.getString("Type")) != type)
|
||||
return type.canProcess(entity.getItem(), entity.level());
|
||||
else if (processing.getInt("Time") >= 0)
|
||||
return true;
|
||||
else if (processing.getInt("Time") == -1)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return type.canProcess(entity.getItem(), entity.level());
|
||||
}
|
||||
|
||||
public static boolean applyProcessing(ItemEntity entity, FanProcessingType type) {
|
||||
if (decrementProcessingTime(entity, type) != 0)
|
||||
return false;
|
||||
List<ItemStack> stacks = type.process(entity.getItem(), entity.level());
|
||||
if (stacks == null)
|
||||
return false;
|
||||
if (stacks.isEmpty()) {
|
||||
entity.discard();
|
||||
return false;
|
||||
}
|
||||
entity.setItem(stacks.remove(0));
|
||||
for (ItemStack additional : stacks) {
|
||||
ItemEntity entityIn = new ItemEntity(entity.level(), entity.getX(), entity.getY(), entity.getZ(), additional);
|
||||
entityIn.setDeltaMovement(entity.getDeltaMovement());
|
||||
entity.level().addFreshEntity(entityIn);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static TransportedResult applyProcessing(TransportedItemStack transported, Level world, FanProcessingType type) {
|
||||
TransportedResult ignore = TransportedResult.doNothing();
|
||||
if (transported.processedBy != type) {
|
||||
transported.processedBy = type;
|
||||
int timeModifierForStackSize = ((transported.stack.getCount() - 1) / 16) + 1;
|
||||
int processingTime =
|
||||
(int) (AllConfigs.server().kinetics.fanProcessingTime.get() * timeModifierForStackSize) + 1;
|
||||
transported.processingTime = processingTime;
|
||||
if (!type.canProcess(transported.stack, world))
|
||||
transported.processingTime = -1;
|
||||
return ignore;
|
||||
}
|
||||
if (transported.processingTime == -1)
|
||||
return ignore;
|
||||
if (transported.processingTime-- > 0)
|
||||
return ignore;
|
||||
|
||||
List<ItemStack> stacks = type.process(transported.stack, world);
|
||||
if (stacks == null)
|
||||
return ignore;
|
||||
|
||||
List<TransportedItemStack> transportedStacks = new ArrayList<>();
|
||||
for (ItemStack additional : stacks) {
|
||||
TransportedItemStack newTransported = transported.getSimilar();
|
||||
newTransported.stack = additional.copy();
|
||||
transportedStacks.add(newTransported);
|
||||
}
|
||||
return TransportedResult.convertTo(transportedStacks);
|
||||
}
|
||||
|
||||
private static int decrementProcessingTime(ItemEntity entity, FanProcessingType type) {
|
||||
CompoundTag nbt = entity.getPersistentData();
|
||||
|
||||
if (!nbt.contains("CreateData"))
|
||||
nbt.put("CreateData", new CompoundTag());
|
||||
CompoundTag createData = nbt.getCompound("CreateData");
|
||||
|
||||
if (!createData.contains("Processing"))
|
||||
createData.put("Processing", new CompoundTag());
|
||||
CompoundTag processing = createData.getCompound("Processing");
|
||||
|
||||
if (!processing.contains("Type") || AllFanProcessingTypes.parseLegacy(processing.getString("Type")) != type) {
|
||||
processing.putString("Type", FanProcessingTypeRegistry.getIdOrThrow(type).toString());
|
||||
int timeModifierForStackSize = ((entity.getItem()
|
||||
.getCount() - 1) / 16) + 1;
|
||||
int processingTime =
|
||||
(int) (AllConfigs.server().kinetics.fanProcessingTime.get() * timeModifierForStackSize) + 1;
|
||||
processing.putInt("Time", processingTime);
|
||||
}
|
||||
|
||||
int value = processing.getInt("Time") - 1;
|
||||
processing.putInt("Time", value);
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package com.simibubi.create.content.kinetics.fan.processing;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public interface FanProcessingType {
|
||||
boolean isValidAt(Level level, BlockPos pos);
|
||||
|
||||
int getPriority();
|
||||
|
||||
boolean canProcess(ItemStack stack, Level level);
|
||||
|
||||
@Nullable
|
||||
List<ItemStack> process(ItemStack stack, Level level);
|
||||
|
||||
void spawnProcessingParticles(Level level, Vec3 pos);
|
||||
|
||||
void morphAirFlow(AirFlowParticleAccess particleAccess, RandomSource random);
|
||||
|
||||
void affectEntity(Entity entity, Level level);
|
||||
|
||||
static FanProcessingType parse(String str) {
|
||||
ResourceLocation id = ResourceLocation.tryParse(str);
|
||||
if (id == null) {
|
||||
return AllFanProcessingTypes.NONE;
|
||||
}
|
||||
FanProcessingType type = FanProcessingTypeRegistry.getType(id);
|
||||
if (type == null) {
|
||||
return AllFanProcessingTypes.NONE;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static FanProcessingType getAt(Level level, BlockPos pos) {
|
||||
for (FanProcessingType type : FanProcessingTypeRegistry.getSortedTypesView()) {
|
||||
if (type.isValidAt(level, pos)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return AllFanProcessingTypes.NONE;
|
||||
}
|
||||
|
||||
interface AirFlowParticleAccess {
|
||||
void setColor(int color);
|
||||
|
||||
void setAlpha(float alpha);
|
||||
|
||||
void spawnExtraParticle(ParticleOptions options, float speedMultiplier);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package com.simibubi.create.content.kinetics.fan.processing;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class FanProcessingTypeRegistry {
|
||||
private static final Map<ResourceLocation, FanProcessingType> TYPES = new Object2ReferenceOpenHashMap<>();
|
||||
private static final Map<FanProcessingType, ResourceLocation> IDS = new Reference2ObjectOpenHashMap<>();
|
||||
private static final List<FanProcessingType> SORTED_TYPES = new ReferenceArrayList<>();
|
||||
private static final List<FanProcessingType> SORTED_TYPES_VIEW = Collections.unmodifiableList(SORTED_TYPES);
|
||||
|
||||
public static void register(ResourceLocation id, FanProcessingType type) {
|
||||
if (TYPES.put(id, type) != null) {
|
||||
throw new IllegalArgumentException("Tried to override FanProcessingType registration for id '" + id + "'. This is not supported!");
|
||||
}
|
||||
ResourceLocation prevId = IDS.put(type, id);
|
||||
if (prevId != null) {
|
||||
throw new IllegalArgumentException("Tried to register same FanProcessingType instance for multiple ids '" + prevId + "' and '" + id + "'. This is not supported!");
|
||||
}
|
||||
insertSortedType(type, id);
|
||||
}
|
||||
|
||||
private static void insertSortedType(FanProcessingType type, ResourceLocation id) {
|
||||
int index = Collections.binarySearch(SORTED_TYPES, type, (type1, type2) -> type2.getPriority() - type1.getPriority());
|
||||
if (index >= 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
SORTED_TYPES.add(-index - 1, type);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static FanProcessingType getType(ResourceLocation id) {
|
||||
return TYPES.get(id);
|
||||
}
|
||||
|
||||
public static FanProcessingType getTypeOrThrow(ResourceLocation id) {
|
||||
FanProcessingType type = getType(id);
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("Could not get FanProcessingType for id '" + id + "'!");
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ResourceLocation getId(FanProcessingType type) {
|
||||
return IDS.get(type);
|
||||
}
|
||||
|
||||
public static ResourceLocation getIdOrThrow(FanProcessingType type) {
|
||||
ResourceLocation id = getId(type);
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException("Could not get id for FanProcessingType " + type + "!");
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public static List<FanProcessingType> getSortedTypesView() {
|
||||
return SORTED_TYPES_VIEW;
|
||||
}
|
||||
}
|
|
@ -1,22 +1,25 @@
|
|||
package com.simibubi.create.content.kinetics.fan;
|
||||
package com.simibubi.create.content.kinetics.fan.processing;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe.HauntingWrapper;
|
||||
import com.simibubi.create.content.processing.recipe.ProcessingRecipe;
|
||||
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams;
|
||||
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public class HauntingRecipe extends ProcessingRecipe<FanProcessing.HauntingWrapper> {
|
||||
public class HauntingRecipe extends ProcessingRecipe<HauntingWrapper> {
|
||||
|
||||
public HauntingRecipe(ProcessingRecipeParams params) {
|
||||
super(AllRecipeTypes.HAUNTING, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(FanProcessing.HauntingWrapper inv, Level worldIn) {
|
||||
public boolean matches(HauntingWrapper inv, Level worldIn) {
|
||||
if (inv.isEmpty())
|
||||
return false;
|
||||
return ingredients.get(0)
|
||||
|
@ -33,4 +36,10 @@ public class HauntingRecipe extends ProcessingRecipe<FanProcessing.HauntingWrapp
|
|||
return 12;
|
||||
}
|
||||
|
||||
public static class HauntingWrapper extends RecipeWrapper {
|
||||
public HauntingWrapper() {
|
||||
super(new ItemStackHandler(1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +1,18 @@
|
|||
package com.simibubi.create.content.kinetics.fan;
|
||||
package com.simibubi.create.content.kinetics.fan.processing;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.content.kinetics.fan.FanProcessing.SplashingWrapper;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe.SplashingWrapper;
|
||||
import com.simibubi.create.content.processing.recipe.ProcessingRecipe;
|
||||
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams;
|
||||
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public class SplashingRecipe extends ProcessingRecipe<FanProcessing.SplashingWrapper> {
|
||||
public class SplashingRecipe extends ProcessingRecipe<SplashingWrapper> {
|
||||
|
||||
public SplashingRecipe(ProcessingRecipeParams params) {
|
||||
super(AllRecipeTypes.SPLASHING, params);
|
||||
|
@ -34,4 +36,10 @@ public class SplashingRecipe extends ProcessingRecipe<FanProcessing.SplashingWra
|
|||
return 12;
|
||||
}
|
||||
|
||||
public static class SplashingWrapper extends RecipeWrapper {
|
||||
public SplashingWrapper() {
|
||||
super(new ItemStackHandler(1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -47,6 +47,11 @@ public class CuttingRecipe extends ProcessingRecipe<RecipeWrapper> implements IA
|
|||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canSpecifyDuration() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAssemblyIngredients(List<Ingredient> list) {}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ import net.minecraft.core.Direction.Axis;
|
|||
import net.minecraft.core.Direction.AxisDirection;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.simibubi.create.content.kinetics.transmission.sequencer;
|
|||
|
||||
import java.util.Vector;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllPackets;
|
||||
import com.simibubi.create.compat.computercraft.ComputerScreen;
|
||||
|
|
|
@ -18,7 +18,6 @@ import net.minecraft.core.Direction;
|
|||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.content.kinetics.fan.FanProcessing;
|
||||
import com.simibubi.create.content.kinetics.fan.processing.AllFanProcessingTypes;
|
||||
import com.simibubi.create.content.logistics.filter.attribute.BookAuthorAttribute;
|
||||
import com.simibubi.create.content.logistics.filter.attribute.BookCopyAttribute;
|
||||
import com.simibubi.create.content.logistics.filter.attribute.ColorAttribute;
|
||||
|
@ -143,8 +143,8 @@ public interface ItemAttribute {
|
|||
EQUIPABLE(s -> LivingEntity.getEquipmentSlotForItem(s)
|
||||
.getType() != EquipmentSlot.Type.HAND),
|
||||
FURNACE_FUEL(AbstractFurnaceBlockEntity::isFuel),
|
||||
WASHABLE(FanProcessing::isWashable),
|
||||
HAUNTABLE(FanProcessing::isHauntable),
|
||||
WASHABLE(AllFanProcessingTypes.SPLASHING::canProcess),
|
||||
HAUNTABLE(AllFanProcessingTypes.HAUNTING::canProcess),
|
||||
CRUSHABLE((s, w) -> testRecipe(s, w, AllRecipeTypes.CRUSHING.getType())
|
||||
|| testRecipe(s, w, AllRecipeTypes.MILLING.getType())),
|
||||
SMELTABLE((s, w) -> testRecipe(s, w, RecipeType.SMELTING)),
|
||||
|
|
|
@ -210,6 +210,11 @@ public class BasinRecipe extends ProcessingRecipe<SmartInventory> {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canSpecifyDuration() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(SmartInventory inv, @Nonnull Level worldIn) {
|
||||
return false;
|
||||
|
|
|
@ -72,7 +72,7 @@ public abstract class ProcessingRecipe<T extends Container> implements Recipe<T>
|
|||
}
|
||||
|
||||
protected boolean canSpecifyDuration() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected int getMaxFluidInputCount() {
|
||||
|
|
|
@ -237,10 +237,10 @@ public class AllDisplayBehaviours {
|
|||
Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> {
|
||||
DisplayBehaviour computerDisplaySource = register(Create.asResource("computer_display_source"), new ComputerDisplaySource());
|
||||
|
||||
assignBlockEntity(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "wired_modem_full"));
|
||||
assignBlockEntity(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_normal"));
|
||||
assignBlockEntity(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_advanced"));
|
||||
assignBlockEntity(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_command"));
|
||||
assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("wired_modem_full"));
|
||||
assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_normal"));
|
||||
assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_advanced"));
|
||||
assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_command"));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,19 +24,13 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
|
|||
|
||||
public class SchematicInstances {
|
||||
|
||||
public static final WorldAttached<Cache<Integer, SchematicWorld>> loadedSchematics;
|
||||
|
||||
static {
|
||||
loadedSchematics = new WorldAttached<>($ -> CacheBuilder.newBuilder()
|
||||
private static final WorldAttached<Cache<Integer, SchematicWorld>> LOADED_SCHEMATICS = new WorldAttached<>($ -> CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(5, TimeUnit.MINUTES)
|
||||
.build());
|
||||
}
|
||||
|
||||
public static void register() {}
|
||||
|
||||
@Nullable
|
||||
public static SchematicWorld get(Level world, ItemStack schematic) {
|
||||
Cache<Integer, SchematicWorld> map = loadedSchematics.get(world);
|
||||
Cache<Integer, SchematicWorld> map = LOADED_SCHEMATICS.get(world);
|
||||
int hash = getHash(schematic);
|
||||
SchematicWorld ifPresent = map.getIfPresent(hash);
|
||||
if (ifPresent != null)
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.simibubi.create.content.schematics.client;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.CreateClient;
|
||||
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.simibubi.create.content.trains.bogey;
|
|||
import com.jozufozu.flywheel.api.MaterialManager;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
|
||||
import com.simibubi.create.content.trains.entity.CarriageBogey;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
|
|
@ -8,7 +8,6 @@ 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;
|
||||
|
|
|
@ -289,9 +289,9 @@ public class CarriageContraption extends Contraption {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<BlockEntity> getSpecialRenderedTEs() {
|
||||
public Collection<BlockEntity> getSpecialRenderedBEs() {
|
||||
if (notInPortal())
|
||||
return super.getSpecialRenderedTEs();
|
||||
return super.getSpecialRenderedBEs();
|
||||
return specialRenderedBEsOutsidePortal;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ import net.minecraft.world.entity.player.Player;
|
|||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.SignalGetter;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.simibubi.create.CreateClient;
|
|||
import com.simibubi.create.content.equipment.blueprint.BlueprintOverlayRenderer;
|
||||
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||
import com.simibubi.create.foundation.utility.Couple;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
|
@ -44,7 +45,6 @@ import net.minecraft.world.level.block.Block;
|
|||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.HitResult.Type;
|
||||
|
@ -478,18 +478,6 @@ public class TrackPlacement {
|
|||
info.requiredPavement += TrackPaver.paveCurve(level, info.curve, block, simulate, visited);
|
||||
}
|
||||
|
||||
private static BlockState copyProperties(BlockState from, BlockState onto) {
|
||||
for (Property property : onto.getProperties()) {
|
||||
if (from.hasProperty(property))
|
||||
onto = onto.setValue(property, from.getValue(property));
|
||||
}
|
||||
return onto;
|
||||
}
|
||||
|
||||
private static BlockState copyProperties(BlockState from, BlockState onto, boolean keepFrom) {
|
||||
return keepFrom ? from : copyProperties(from, onto);
|
||||
}
|
||||
|
||||
private static PlacementInfo placeTracks(Level level, PlacementInfo info, BlockState state1, BlockState state2,
|
||||
BlockPos targetPos1, BlockPos targetPos2, boolean simulate) {
|
||||
info.requiredTracks = 0;
|
||||
|
@ -518,7 +506,7 @@ public class TrackPlacement {
|
|||
BlockPos offsetPos = pos.offset(BlockPos.containing(offset));
|
||||
BlockState stateAtPos = level.getBlockState(offsetPos);
|
||||
// copy over all shared properties from the shaped state to the correct track material block
|
||||
BlockState toPlace = copyProperties(state, info.trackMaterial.getBlock().defaultBlockState());
|
||||
BlockState toPlace = BlockHelper.copyProperties(state, info.trackMaterial.getBlock().defaultBlockState());
|
||||
|
||||
boolean canPlace = stateAtPos.canBeReplaced();
|
||||
if (canPlace)
|
||||
|
@ -543,12 +531,12 @@ public class TrackPlacement {
|
|||
BlockState onto = info.trackMaterial.getBlock().defaultBlockState();
|
||||
BlockState stateAtPos = level.getBlockState(targetPos1);
|
||||
level.setBlock(targetPos1, ProperWaterloggedBlock.withWater(level,
|
||||
(AllTags.AllBlockTags.TRACKS.matches(stateAtPos) ? stateAtPos : copyProperties(state1, onto))
|
||||
(AllTags.AllBlockTags.TRACKS.matches(stateAtPos) ? stateAtPos : BlockHelper.copyProperties(state1, onto))
|
||||
.setValue(TrackBlock.HAS_BE, true), targetPos1), 3);
|
||||
|
||||
stateAtPos = level.getBlockState(targetPos2);
|
||||
level.setBlock(targetPos2, ProperWaterloggedBlock.withWater(level,
|
||||
(AllTags.AllBlockTags.TRACKS.matches(stateAtPos) ? stateAtPos : copyProperties(state2, onto))
|
||||
(AllTags.AllBlockTags.TRACKS.matches(stateAtPos) ? stateAtPos : BlockHelper.copyProperties(state2, onto))
|
||||
.setValue(TrackBlock.HAS_BE, true), targetPos2), 3);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ import net.minecraft.MethodsReturnNonnullByDefault;
|
|||
import net.minecraft.advancements.CriterionTrigger;
|
||||
import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance;
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate;
|
||||
import net.minecraft.advancements.critereon.EntityPredicate;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.PlayerAdvancements;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
|
|
@ -11,7 +11,6 @@ import com.google.gson.JsonObject;
|
|||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate;
|
||||
import net.minecraft.advancements.critereon.DeserializationContext;
|
||||
import net.minecraft.advancements.critereon.EntityPredicate;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.Optional;
|
|||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.platform.Window;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.config.ui.entries.NumberEntry;
|
||||
import com.simibubi.create.foundation.gui.RemovedGuiUtils;
|
||||
import com.simibubi.create.foundation.gui.Theme;
|
||||
|
|
|
@ -3,19 +3,17 @@ package com.simibubi.create.foundation.damageTypes;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import com.simibubi.create.AllDamageTypes;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
|
||||
import net.minecraftforge.common.data.DatapackBuiltinEntriesProvider;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.simibubi.create.AllDamageTypes;
|
||||
import com.simibubi.create.Create;
|
||||
|
||||
import net.minecraft.core.HolderLookup.Provider;
|
||||
import net.minecraft.core.RegistrySetBuilder;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraftforge.common.data.DatapackBuiltinEntriesProvider;
|
||||
|
||||
public class DamageTypeDataProvider extends DatapackBuiltinEntriesProvider {
|
||||
private static final RegistrySetBuilder BUILDER = new RegistrySetBuilder()
|
||||
|
|
|
@ -10,7 +10,6 @@ import javax.annotation.Nullable;
|
|||
import com.jozufozu.flywheel.api.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
|
||||
import com.simibubi.create.AllBlockEntityTypes;
|
||||
import com.simibubi.create.Create;
|
||||
import com.tterrag.registrate.AbstractRegistrate;
|
||||
import com.tterrag.registrate.builders.BlockEntityBuilder;
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package com.simibubi.create.foundation.data;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.simibubi.create.AllTags.AllRecipeSerializerTags;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.compat.Mods;
|
||||
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.tags.TagsProvider;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
|
||||
public class RecipeSerializerTagGen extends TagsProvider<RecipeSerializer<?>> {
|
||||
public RecipeSerializerTagGen(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, @Nullable ExistingFileHelper existingFileHelper) {
|
||||
super(output, Registries.RECIPE_SERIALIZER, lookupProvider, Create.ID, existingFileHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Create's Recipe Serializer Tags";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addTags(HolderLookup.Provider provider) {
|
||||
this.tag(AllRecipeSerializerTags.AUTOMATION_IGNORE.tag)
|
||||
.addOptional(Mods.OCCULTISM.rl("spirit_trade"))
|
||||
.addOptional(Mods.OCCULTISM.rl("ritual"));
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package com.simibubi.create.foundation.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.gui.element.ScreenElement;
|
||||
import com.simibubi.create.foundation.utility.Color;
|
||||
|
|
|
@ -3,8 +3,6 @@ package com.simibubi.create.foundation.gui.widget;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.gui.element.RenderElement;
|
||||
import com.simibubi.create.foundation.gui.element.ScreenElement;
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.simibubi.create.foundation.gui.widget;
|
|||
import javax.annotation.Nonnull;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.foundation.utility.Components;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
package com.simibubi.create.foundation.mixin.client;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.At.Shift;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
@Mixin(PoseStack.class)
|
||||
public class FixNormalScalingMixin {
|
||||
/**
|
||||
* Minecraft negates the normal matrix if all scales are equal and negative, but
|
||||
* does not return afterward. This allows the rest of the method's logic to be
|
||||
* applied, which negates the matrix again, resulting in the matrix being the
|
||||
* same as in the beginning.
|
||||
*/
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lorg/joml/Matrix3f;scale(F)Lorg/joml/Matrix3f;", shift = Shift.AFTER, remap = false), method = "scale(FFF)V", cancellable = true)
|
||||
private void create$returnAfterNegate(float x, float y, float z, CallbackInfo ci) {
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Minecraft takes the inverse cube root of the product of all scales to provide a
|
||||
* rough estimate for normalization so that it does not need to be done later. It
|
||||
* does not make sense for this "normalization factor" to be negative though, as
|
||||
* that would invert all normals. Additionally, Minecraft's fastInverseCbrt method
|
||||
* does not work for negative numbers.
|
||||
*/
|
||||
@ModifyArg(at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;fastInvCubeRoot(F)F"), method = "scale(FFF)V")
|
||||
private float create$absInvCbrtInput(float input) {
|
||||
return Math.abs(input);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package com.simibubi.create.foundation.ponder;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.foundation.gui.element.GuiGameElement;
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
package com.simibubi.create.foundation.utility;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.simibubi.create.Create;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
|
||||
public class CreateRegistry<K, V> {
|
||||
private static final List<CreateRegistry<?, ?>> ALL = new ArrayList<>();
|
||||
|
||||
protected final IForgeRegistry<K> objectRegistry;
|
||||
protected final Map<ResourceLocation, V> locationMap = new HashMap<>();
|
||||
protected final Map<K, V> objectMap = new IdentityHashMap<>();
|
||||
protected boolean unwrapped = false;
|
||||
|
||||
public CreateRegistry(IForgeRegistry<K> objectRegistry) {
|
||||
this.objectRegistry = objectRegistry;
|
||||
ALL.add(this);
|
||||
}
|
||||
|
||||
public void register(ResourceLocation location, V value) {
|
||||
if (!unwrapped) {
|
||||
locationMap.put(location, value);
|
||||
} else {
|
||||
K object = objectRegistry.getValue(location);
|
||||
if (object != null) {
|
||||
objectMap.put(object, value);
|
||||
} else {
|
||||
Create.LOGGER.warn("Could not get object for location '" + location + "' in CreateRegistry after unwrapping!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void register(K object, V value) {
|
||||
if (unwrapped) {
|
||||
objectMap.put(object, value);
|
||||
} else {
|
||||
ResourceLocation location = objectRegistry.getKey(object);
|
||||
if (location != null) {
|
||||
locationMap.put(location, value);
|
||||
} else {
|
||||
Create.LOGGER.warn("Could not get location of object '" + object + "' in CreateRegistry before unwrapping!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public V get(ResourceLocation location) {
|
||||
if (!unwrapped) {
|
||||
return locationMap.get(location);
|
||||
} else {
|
||||
K object = objectRegistry.getValue(location);
|
||||
if (object != null) {
|
||||
return objectMap.get(object);
|
||||
} else {
|
||||
Create.LOGGER.warn("Could not get object for location '" + location + "' in CreateRegistry after unwrapping!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public V get(K object) {
|
||||
if (unwrapped) {
|
||||
return objectMap.get(object);
|
||||
} else {
|
||||
ResourceLocation location = objectRegistry.getKey(object);
|
||||
if (location != null) {
|
||||
return locationMap.get(location);
|
||||
} else {
|
||||
Create.LOGGER.warn("Could not get location of object '" + object + "' in CreateRegistry before unwrapping!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUnwrapped() {
|
||||
return unwrapped;
|
||||
}
|
||||
|
||||
protected void unwrap() {
|
||||
for (Map.Entry<ResourceLocation, V> entry : locationMap.entrySet()) {
|
||||
ResourceLocation location = entry.getKey();
|
||||
K object = objectRegistry.getValue(location);
|
||||
if (object != null) {
|
||||
objectMap.put(object, entry.getValue());
|
||||
} else {
|
||||
Create.LOGGER.warn("Could not get object for location '" + location + "' in CreateRegistry during unwrapping!");
|
||||
}
|
||||
}
|
||||
unwrapped = true;
|
||||
}
|
||||
|
||||
public static void unwrapAll() {
|
||||
for (CreateRegistry<?, ?> registry : ALL) {
|
||||
registry.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,8 +24,8 @@ import net.minecraft.core.Direction;
|
|||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
|
||||
public abstract class GhostBlockRenderer {
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ public class CKinetics extends ConfigBase {
|
|||
public final ConfigGroup contraptions = group(1, "contraptions", "Moving Contraptions");
|
||||
public final ConfigInt maxBlocksMoved = i(2048, 1, "maxBlocksMoved", Comments.maxBlocksMoved);
|
||||
public final ConfigInt maxDataSize =
|
||||
i(ContraptionData.DEFAULT_MAX, 0, "maxDataSize", Comments.bytes, Comments.maxDataDisable, Comments.maxDataSize, Comments.maxDataSize2);
|
||||
i(ContraptionData.DEFAULT_LIMIT, 0, "maxDataSize", Comments.bytes, Comments.maxDataDisable, Comments.maxDataSize, Comments.maxDataSize2);
|
||||
public final ConfigInt maxChassisRange = i(16, 1, "maxChassisRange", Comments.maxChassisRange);
|
||||
public final ConfigInt maxPistonPoles = i(64, 1, "maxPistonPoles", Comments.maxPistonPoles);
|
||||
public final ConfigInt maxRopeLength = i(256, 1, "maxRopeLength", Comments.maxRopeLength);
|
||||
|
|
|
@ -5,21 +5,17 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.simibubi.create.content.contraptions.Contraption;
|
||||
import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement;
|
||||
import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovingInteraction;
|
||||
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
|
||||
import com.simibubi.create.content.kinetics.gauge.SpeedGaugeBlockEntity;
|
||||
|
||||
import com.simibubi.create.content.kinetics.gauge.StressGaugeBlockEntity;
|
||||
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.simibubi.create.AllBlockEntityTypes;
|
||||
import com.simibubi.create.content.contraptions.Contraption;
|
||||
import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement;
|
||||
import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovingInteraction;
|
||||
import com.simibubi.create.content.contraptions.behaviour.MovementContext;
|
||||
import com.simibubi.create.content.kinetics.gauge.SpeedGaugeBlockEntity;
|
||||
import com.simibubi.create.content.kinetics.gauge.StressGaugeBlockEntity;
|
||||
import com.simibubi.create.content.logistics.tunnel.BrassTunnelBlockEntity.SelectionMode;
|
||||
import com.simibubi.create.content.redstone.nixieTube.NixieTubeBlockEntity;
|
||||
import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer;
|
||||
|
|
|
@ -14,7 +14,6 @@ import com.simibubi.create.infrastructure.gametest.CreateGameTestHelper;
|
|||
import com.simibubi.create.infrastructure.gametest.GameTestGroup;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2LongMap;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.gametest.framework.GameTest;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
|
|
|
@ -21,7 +21,6 @@ import com.simibubi.create.infrastructure.gametest.GameTestGroup;
|
|||
import it.unimi.dsi.fastutil.objects.Object2LongMap;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.gametest.framework.GameTest;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.world.item.EnchantedBookItem;
|
||||
|
|
|
@ -22,7 +22,6 @@ import com.simibubi.create.foundation.utility.Lang;
|
|||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.Tooltip;
|
||||
|
|
|
@ -7,7 +7,6 @@ import com.simibubi.create.compat.Mods;
|
|||
import com.simibubi.create.foundation.ponder.PonderRegistry;
|
||||
import com.simibubi.create.foundation.ponder.PonderTag;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
@ -314,7 +313,7 @@ public class AllPonderTags {
|
|||
.add(Blocks.TARGET);
|
||||
|
||||
Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> {
|
||||
Block computer = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_advanced"));
|
||||
Block computer = ForgeRegistries.BLOCKS.getValue(Mods.COMPUTERCRAFT.rl("computer_advanced"));
|
||||
if (computer != null)
|
||||
PonderRegistry.TAGS.forTag(DISPLAY_SOURCES).add(computer);
|
||||
});
|
||||
|
|
|
@ -33,6 +33,6 @@ Technology that empowers the player.'''
|
|||
[[dependencies.create]]
|
||||
modId="flywheel"
|
||||
mandatory=true
|
||||
versionRange="[0.6.9,0.6.10)"
|
||||
versionRange="[0.6.10,0.6.11)"
|
||||
ordering="AFTER"
|
||||
side="CLIENT"
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
"client.BlockDestructionProgressMixin",
|
||||
"client.CameraMixin",
|
||||
"client.EntityContraptionInteractionMixin",
|
||||
"client.FixNormalScalingMixin",
|
||||
"client.GameRendererMixin",
|
||||
"client.HeavyBootsOnPlayerMixin",
|
||||
"client.HumanoidArmorLayerMixin",
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
| Method | Description |
|
||||
|---------------------------------------|------------------------------------------------------|
|
||||
| [`setCursorPos(x, y)`](#setCursorPos) | Sets the cursor position |
|
||||
| [`getCursorPos()`](#getCursorPos) | Gets the current cursor position |
|
||||
| [`getSize()`](#getSize) | Gets the display size of the connected target |
|
||||
| [`isColor()`](#isColor) | Whether the connected display target supports color |
|
||||
| [`isColour()`](#isColour) | Whether the connected display target supports colour |
|
||||
| [`write(text)`](#writetext) | Writes text at the current cursor position |
|
||||
| [`clearLine()`](#clearLine) | Clears the line at the current cursor position |
|
||||
| [`clear()`](#clear) | Clears the whole display |
|
||||
| [`update()`](#update) | Pushes an update to the display target |
|
||||
|
||||
---
|
||||
### `setCursorPos(x, y)`
|
||||
Sets the cursor position. Can be outside the bounds of the connected display.
|
||||
|
||||
**Parameters**
|
||||
- _x:_ `number` The cursor x position.
|
||||
- _y:_ `number` The cursor y position.
|
||||
|
||||
---
|
||||
### `getCursorPos()`
|
||||
Gets the current cursor position.
|
||||
|
||||
**Returns**
|
||||
- `number` The cursor x position.
|
||||
- `number` The cursor y position.
|
||||
|
||||
---
|
||||
### `getSize()`
|
||||
Gets the size of the connected display target.
|
||||
|
||||
**Returns**
|
||||
- `number` The width of the display.
|
||||
- `number` The height of the display.
|
||||
|
||||
---
|
||||
### `isColor()`
|
||||
Checks whether the connected display target supports color.
|
||||
|
||||
**Returns**
|
||||
- `boolean` Whether the display supports color.
|
||||
|
||||
---
|
||||
### `isColour()`
|
||||
Checks whether the connected display target supports colour.
|
||||
|
||||
**Returns**
|
||||
- `boolean` Whether the display supports colour.
|
||||
|
||||
---
|
||||
### `write(text)`
|
||||
Writes text at the current cursor position, moving the cursor to the end of the text.
|
||||
This only writes to an internal buffer. For the changes to show up on the display [`update()`](#update) must be used.
|
||||
If the cursor is outside the bounds of the connected display, the text will not show up on the display.
|
||||
|
||||
This will overwrite any text currently at the cursor position.
|
||||
|
||||
**Parameters**
|
||||
- _text:_ `string` The text to write.
|
||||
|
||||
**See also**
|
||||
- [`update()`](#update) To push the changes to the display target.
|
||||
|
||||
---
|
||||
### `clearLine()`
|
||||
Clears the line at the current cursor position.
|
||||
|
||||
**See also**
|
||||
- [`update()`](#update) To push the changes to the display target.
|
||||
|
||||
---
|
||||
### `clear()`
|
||||
Clears the whole display.
|
||||
|
||||
**See also**
|
||||
- [`update()`](#update) To push the changes to the display target.
|
||||
|
||||
---
|
||||
### `update()`
|
||||
Pushes any changes to the connected display target.
|
||||
Any changes made are only made to an internal buffer.
|
||||
For them to show up on the display they must be pushed to the display using this function.
|
||||
This allows for this peripheral to be better multithreaded and for users to be able to change multiple lines at once by
|
||||
using multiple [`write(text)`](#writetext) calls and then one [`update()`](#update) call.
|
||||
|
||||
**See also**
|
||||
- [`write(text)`](#writetext) To write text to the display target.
|
|
@ -1,18 +0,0 @@
|
|||
| Method | Description |
|
||||
|-------------------------------------------------|----------------------------------------|
|
||||
| [`setTargetSpeed(speed)`](#setTargetSpeedspeed) | Sets the target rotation speed |
|
||||
| [`getTargetSpeed()`](#getTargetSpeed) | Gets the current target rotation speed |
|
||||
|
||||
---
|
||||
### `setTargetSpeed(speed)`
|
||||
Sets the rotation speed controller's target speed.
|
||||
|
||||
**Parameters**
|
||||
- _speed:_ `number` The target speed in RPM. Must be an integer within the range of [-256..256]. Values outside of this range will be clamped.
|
||||
|
||||
---
|
||||
### `getTargetSpeed()`
|
||||
Gets the rotation speed controller's current target speed.
|
||||
|
||||
**Returns**
|
||||
- `number` The current target rotation speed in RPM.
|
|
@ -1,28 +0,0 @@
|
|||
| Method | Description |
|
||||
|--------------------------------------------------------|--------------------------------------------------------------|
|
||||
| [`rotate(angle, [modifier])`](#rotateangle-modifier) | Rotates shaft by a set angle |
|
||||
| [`move(distance, [modifier])`](#movedistance-modifier) | Rotates shaft to move Piston/Pulley/Gantry by a set distance |
|
||||
| [`isRunning()`](#isRunning) | Whether the gearshift is currently spinning |
|
||||
|
||||
---
|
||||
### `rotate(angle, [modifier])`
|
||||
Rotates connected components by a set angle.
|
||||
|
||||
**Parameters**
|
||||
- _angle:_ `number` Angle to rotate the shaft by in degrees. Must be a positive integer. To do backwards rotation, set _modifier_ to a negative value.
|
||||
- _modifier?:_ `number = 1` Speed modifier which can be used to reverse rotation. Must be an integer within the range of [-2..2]. Values out of this range are ignored and the default of 1 is used.
|
||||
|
||||
---
|
||||
### `move(distance, [modifier])`
|
||||
Rotates connected components to move connected piston, pulley or gantry contractions by a set distance.
|
||||
|
||||
**Parameters**
|
||||
- _distance:_ `number` Distance to move connected piston, pulley or gantry contraptions by. Must be a positive integer. To do backwards movement, set _modifier_ to a negative value.
|
||||
- _modifier?:_ `number = 1` Speed modifier which can be used to reverse direction. Must be an integer within the range of [-2..2]. Values out of this range are ignored and the default of 1 is used.
|
||||
|
||||
---
|
||||
### `isRunning()`
|
||||
Checks if the sequenced gearshift is currently spinning.
|
||||
|
||||
**Returns**
|
||||
- `boolean` Whether the sequenced gearshift is currently spinning.
|
|
@ -1,10 +0,0 @@
|
|||
| Method | Description |
|
||||
|---------------------------|---------------------------------|
|
||||
| [`getSpeed()`](#getSpeed) | Gets the current rotation speed |
|
||||
|
||||
---
|
||||
### `getSpeed()`
|
||||
Gets the current rotation speed of the attached components.
|
||||
|
||||
**Returns**
|
||||
- `number` The current rotation speed in RPM.
|
|
@ -1,18 +0,0 @@
|
|||
| Method | Description |
|
||||
|---------------------------------------------|--------------------------------|
|
||||
| [`getStress()`](#getStress) | Gets the current stress level |
|
||||
| [`getStressCapacity()`](#getStressCapacity) | Gets the total stress capacity |
|
||||
|
||||
---
|
||||
### `getStress()`
|
||||
Gets the connected network's current stress level.
|
||||
|
||||
**Returns**
|
||||
- `number` The current stress level in SU.
|
||||
|
||||
---
|
||||
### `getStressCapacity()`
|
||||
Gets the connected network's total stress capacity.
|
||||
|
||||
**Returns**
|
||||
- `number` The total stress capacity in SU.
|
|
@ -1,195 +0,0 @@
|
|||
Train schedules are represented by a table in Lua. The table contains a list of entries where each entry has a single instruction and multiple conditions.
|
||||
Each instruction and condition has a `data` table that stores specific data about the instruction or condition.
|
||||
|
||||
```lua
|
||||
schedule = {
|
||||
cyclic = true, -- Does the schedule repeat itself after the end has been reached?
|
||||
entries = { -- List of entries, each entry contains a single instruction and multiple conditions.
|
||||
{
|
||||
instruction = {
|
||||
id = "create:destination", -- The different instructions are described below.
|
||||
data = { -- Data that is stored about the instruction. Different for each instruction type.
|
||||
text = "Station 1",
|
||||
},
|
||||
},
|
||||
conditions = { -- List of lists of conditions. The outer list is the "OR" list
|
||||
{ -- and the inner lists are "AND" lists.
|
||||
{
|
||||
id = "create:delay", -- The different conditions are described below.
|
||||
data = { -- Data that is stored about the condition. Different for each condition type.
|
||||
value = 5,
|
||||
time_unit = 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
id = "create:powered",
|
||||
data = {},
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
id = "create:time_of_day",
|
||||
data = {
|
||||
rotation = 0,
|
||||
hour = 14,
|
||||
minute = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
---
|
||||
## Instructions
|
||||
| ID | Description |
|
||||
|----------------------------------------------|---------------------------------|
|
||||
| [`"create:destination"`](#createdestination) | Move to a certain train station |
|
||||
| [`"create:rename"`](#createrename) | Change the schedule title |
|
||||
| [`"create:throttle"`](#createthrottle) | Change the train's throttle |
|
||||
|
||||
---
|
||||
### `"create:destination"`
|
||||
Moves the train to the chosen train station. This instruction must have at least one condition.
|
||||
|
||||
**Data**
|
||||
- _text:_ `string` The name of the station to travel to. Can include * as a wildcard.
|
||||
|
||||
---
|
||||
### `"create:rename"`
|
||||
Renames the schedule. This name shows up on display link targets. This instruction cannot have conditions.
|
||||
|
||||
**Data**
|
||||
- _text:_ `string` The name to rename the schedule to.
|
||||
|
||||
---
|
||||
### `"create:throttle"`
|
||||
Changes the throttle of the train. This instruction cannot have conditions.
|
||||
|
||||
**Data**
|
||||
- _value:_ `number` The throttle to set the train to. Must be an integer within the range of [5..100].
|
||||
|
||||
---
|
||||
## Conditions
|
||||
Conditions are stored in a list of lists of conditions. The inner lists contain conditions that get `AND`'ed together. They must all be met for that group to be true.
|
||||
The outer list contains the `AND`'ed groups of conditions that get `OR`'ed together. Only one of the groups needs to be true for the schedule to move onto the next instruction.
|
||||
|
||||
| ID | Description |
|
||||
|-----------------------------------------------------|-----------------------------------------------------|
|
||||
| [`"create:delay"`](#createdelay) | Wait for a certain delay |
|
||||
| [`"create:time_of_day"`](#createtimeofday) | Wait for a specific time of day |
|
||||
| [`"create:fluid_threshold"`](#createfluidthreshold) | Wait for a certain amount of fluid to be on board |
|
||||
| [`"create:item_threshold"`](#createitemthreshold) | Wait for a certain amount of items to be on board |
|
||||
| [`"create:redstone_link"`](#createredstonelink) | Wait for a redstone link to be powered |
|
||||
| [`"create:player_count"`](#createplayercount) | Wait for a certain amount of players to be on board |
|
||||
| [`"create:idle"`](#createidle) | Wait for cargo loading inactivity |
|
||||
| [`"create:unloaded"`](#createunloaded) | Wait for the current chunk to be unloaded |
|
||||
| [`"create:powered"`](#createpowered) | Wait for the station to be powered |
|
||||
|
||||
---
|
||||
### `"create:delay"`
|
||||
Wait for a set delay. Can be measured in ticks, seconds or minutes.
|
||||
|
||||
**Data**
|
||||
- _value:_ `number` The amount of time to wait for.
|
||||
- _time_unit:_ `number` The unit of time. 0 for ticks, 1 for seconds and 2 for minutes.
|
||||
|
||||
---
|
||||
### `"create:time_of_day"`
|
||||
Wait for a time of day, then repeat at a specified interval.
|
||||
|
||||
**Data**
|
||||
- _hour:_ `number` The hour of the day to wait for in a 24-hour format. Must be an integer within the range of [0..23].
|
||||
- _minute:_ `number` The minute of the hour to wait for. Must be an integer within the range of [0..59].
|
||||
- _rotation:_ `number` The interval to repeat at after the time of day has been met. Check the rotation table below for valid values. Must be an integer within the range of [0..9].
|
||||
|
||||
**Rotation**
|
||||
|
||||
| Rotation | Time Interval |
|
||||
|----------|------------------|
|
||||
| 0 | Every Day |
|
||||
| 1 | Every 12 Hours |
|
||||
| 2 | Every 6 Hours |
|
||||
| 3 | Every 4 Hours |
|
||||
| 4 | Every 3 Hours |
|
||||
| 5 | Every 2 Hours |
|
||||
| 6 | Every Hour |
|
||||
| 7 | Every 45 Minutes |
|
||||
| 8 | Every 30 Minutes |
|
||||
| 9 | Every 15 Minutes |
|
||||
|
||||
---
|
||||
### `"create:fluid_threshold"`
|
||||
Wait for a certain amount of a specific fluid to be loaded onto the train.
|
||||
|
||||
**Data**
|
||||
- _bucket:_ `table` The bucket item of the fluid.
|
||||
- _threshold:_ `number` The threshold in number of buckets of fluid. Must be a positive integer.
|
||||
- _operator:_ `number` Whether the condition should wait for the train to be loaded above the threshold, below the threshold or exactly at the threshold. 0 for greater than, 1 for less than, 2 for equal to.
|
||||
- _measure:_ `number` The unit to measure the fluid in. This condition supports buckets as the only unit. Set to 0.
|
||||
|
||||
**See also**
|
||||
- [Items](#items) How items are represented in Lua.
|
||||
|
||||
---
|
||||
### `"create:item_threshold"`
|
||||
Wait for a certain amount of a specific item to be loaded onto the train.
|
||||
|
||||
**Data**
|
||||
- _item:_ `table` The item.
|
||||
- _threshold:_ `number` The threshold of items. Must be a positive integer.
|
||||
- _operator:_ `number` Whether the condition should wait for the train to be loaded above the threshold, below the threshold or exactly at the threshold. 0 for greater than, 1 for less than, 2 for equal to.
|
||||
- _measure:_ `number` The unit to measure the items in. 0 for items. 1 for stacks of items.
|
||||
|
||||
**See also**
|
||||
- [Items](#items) How items are represented in Lua.
|
||||
|
||||
---
|
||||
### `"create:redstone_link"`
|
||||
Wait for a redstone link to be powered.
|
||||
|
||||
**Data**
|
||||
- _frequency:_ `{ table... }` A list of the two items making up the redstone link frequency.
|
||||
- _inverted:_ `number` Whether the redstone link should be powered or not to meet the condition. 0 for powered. 1 for not powered.
|
||||
|
||||
**See also**
|
||||
- [Items](#items) How items are represented in Lua.
|
||||
|
||||
---
|
||||
### `"create:player_count"`
|
||||
Wait for a certain amount of players to be seated on the train.
|
||||
|
||||
**Data**
|
||||
- _count:_ `number` The number of players to be seated on the train. Must be a positive integer.
|
||||
- _exact:_ `number` Whether the seated player count has to be exact to meet the condition. 0 for the exact amount of players seated, 1 for a greater than or equal amount of seated players.
|
||||
|
||||
---
|
||||
### `"create:idle"`
|
||||
Wait for a period of inactivity in loading or unloading the train. Can be measured in ticks, seconds or minutes.
|
||||
|
||||
**Data**
|
||||
- _value:_ `number` The amount of idle time to meet the condition. Must be a positive integer.
|
||||
- _time_unit:_ `number` The unit of time. 0 for ticks, 1 for seconds and 2 for minutes.
|
||||
|
||||
---
|
||||
### `"create:unloaded"`
|
||||
Wait for the chunk the train is in to be unloaded.
|
||||
|
||||
---
|
||||
### `"create:powered"`
|
||||
Wait for the station to be powered with a redstone signal.
|
||||
|
||||
---
|
||||
## Items
|
||||
In Lua, items are represented with an ID and a count.
|
||||
|
||||
```lua
|
||||
item = {
|
||||
id = "minecraft:stone",
|
||||
count = 1,
|
||||
}
|
||||
```
|
||||
|
||||
- _id:_ `string` The ID of the item.
|
||||
- _count:_ `number` The amount of items in the stack. For the purposes of working with train schedules the count should always be 1. Must be an integer.
|
|
@ -1,179 +0,0 @@
|
|||
| Method | Description |
|
||||
|-----------------------------------------------------------------|----------------------------------------------------|
|
||||
| [`assemble()`](#assemble) | Assembles a new train at the station |
|
||||
| [`disassemble()`](#disassemble) | Disassembles the currently present train |
|
||||
| [`setAssemblyMode(assemblyMode)`](#setAssemblyModeassemblyMode) | Sets the station's assembly mode |
|
||||
| [`isInAssemblyMode()`](#isInAssemblyMode) | Whether the station is in assembly mode |
|
||||
| [`getStationName()`](#getStationName) | Gets the station's current name |
|
||||
| [`setStationName(name)`](#setStationNamename) | Sets the station's name |
|
||||
| [`isTrainPresent()`](#isTrainPresent) | Whether a train is present at the station |
|
||||
| [`isTrainImminent()`](#isTrainImminent) | Whether a train is imminent to the station |
|
||||
| [`isTrainEnroute()`](#isTrainEnroute) | Whether a train is enroute to the station |
|
||||
| [`getTrainName()`](#getTrainName) | Gets the currently present train's name |
|
||||
| [`setTrainName(name)`](#setTrainNamename) | Sets the currently present train's name |
|
||||
| [`hasSchedule()`](#hasSchedule) | Whether the currently present train has a schedule |
|
||||
| [`getSchedule()`](#getSchedule) | Gets the currently present train's schedule |
|
||||
| [`setSchedule(schedule)`](#setScheduleschedule) | Sets the currently present train's schedule |
|
||||
|
||||
---
|
||||
### `assemble()`
|
||||
Assembles a new train at the station. The station must be in assembly mode prior to calling this function.
|
||||
This function also causes the station to exit assembly mode after the train is done assembing.
|
||||
|
||||
**Throws**
|
||||
- If the station is not in assembly mode.
|
||||
- If the station is not connected to a track.
|
||||
- If the train failed to assemble.
|
||||
- If the station failed to exit assembly mode.
|
||||
|
||||
**See also**
|
||||
- [`setAssemblyMode(assemblyMode)`](#setAssemblyModeassemblyMode) To set the assembly mode of the station.
|
||||
|
||||
---
|
||||
### `disassemble()`
|
||||
Disassembles the station's currently present train. The station must not be in assembly mode.
|
||||
|
||||
**Throws**
|
||||
- If the station is in assembly mode.
|
||||
- If the station is not connected to a track.
|
||||
- If there is currently no train present at the station.
|
||||
- If the train failed to disassemble.
|
||||
|
||||
**See also**
|
||||
- [`setAssemblyMode(assemblyMode)`](#setAssemblyModeassemblyMode) To set the assembly mode of the station.
|
||||
|
||||
---
|
||||
### `setAssemblyMode(assemblyMode)`
|
||||
Sets the station's assembly mode.
|
||||
|
||||
**Parameters**
|
||||
- _assemblyMode:_ `boolean` Whether the station should be in assembly mode.
|
||||
|
||||
**Throws**
|
||||
- If the station fails to enter or exit assembly mode.
|
||||
- If the station is not connected to a track.
|
||||
|
||||
---
|
||||
### `isInAssemblyMode()`
|
||||
Checks whether the station is in assembly mode.
|
||||
|
||||
**Returns**
|
||||
- `boolean` Whether the station is in assembly mode.
|
||||
|
||||
---
|
||||
### `getStationName()`
|
||||
Gets the station's current name.
|
||||
|
||||
**Returns**
|
||||
- `string` The station's current name.
|
||||
|
||||
**Throws**
|
||||
- If the station is not connected to a track.
|
||||
|
||||
---
|
||||
### `setStationName(name)`
|
||||
Sets the station's name.
|
||||
|
||||
**Parameters**
|
||||
- _name:_ `string` What to set the station's name to.
|
||||
|
||||
**Throws**
|
||||
- If the station name fails to be set.
|
||||
- If the station is not connected to a track.
|
||||
|
||||
---
|
||||
### `isTrainPresent()`
|
||||
Checks whether a train is currently present at the station.
|
||||
|
||||
**Returns**
|
||||
- `boolean` Whether a train is present at the station.
|
||||
|
||||
**Throws**
|
||||
- If the station is not connected to a track.
|
||||
|
||||
---
|
||||
### `isTrainImminent()`
|
||||
Checks whether a train is imminently arriving at the station.
|
||||
Imminent is defined as being within 30 blocks of the station.
|
||||
This will not be true if the train has arrived and stopped at the station.
|
||||
|
||||
**Returns**
|
||||
- `boolean` Whether a train is imminent to the station.
|
||||
|
||||
**Throws**
|
||||
- If the station is not connected to a track.
|
||||
|
||||
**See also**
|
||||
- [`isTrainPresent()`](#isTrainPresent) To check if a train is present at the station.
|
||||
|
||||
---
|
||||
### `isTrainEnroute()`
|
||||
Checks whether a train is enroute and navigating to the station.
|
||||
|
||||
**Returns**
|
||||
- `boolean` Whether a train is enroute to the station.
|
||||
|
||||
**Throws**
|
||||
- If the station is not connected to a track.
|
||||
|
||||
---
|
||||
### `getTrainName()`
|
||||
Gets the currently present train's name.
|
||||
|
||||
**Returns**
|
||||
- `string` The currently present train's name.
|
||||
|
||||
**Throws**
|
||||
- If the station is not connected to a track.
|
||||
- If there is currently no train present at the station.
|
||||
|
||||
---
|
||||
### `setTrainName(name)`
|
||||
Sets the currently present train's name.
|
||||
|
||||
**Parameters**
|
||||
- _name:_ `string` What to set the currently present train's name to.
|
||||
|
||||
**Throws**
|
||||
- If the station is not connected to a track.
|
||||
- If there is currently no train present at the station.
|
||||
|
||||
---
|
||||
### `hasSchedule()`
|
||||
Checks whether the currently present train has a schedule.
|
||||
|
||||
**Returns**
|
||||
- `boolean` Whether the currently present train has a schedule.
|
||||
|
||||
**Throws**
|
||||
- If the station is not connected to a track.
|
||||
- If there is currently no train present at the station.
|
||||
|
||||
---
|
||||
### `getSchedule()`
|
||||
Gets the currently present train's schedule.
|
||||
|
||||
**Returns**
|
||||
- `table` The train's schedule
|
||||
|
||||
**Throws**
|
||||
- If the station is not connected to a track.
|
||||
- If there is currently no train present at the station.
|
||||
- If the present train doesn't have a schedule.
|
||||
|
||||
**See also**
|
||||
- [Lua Train Schedules](#Lua-Train-Schedules) How train schedules are represented in Lua.
|
||||
|
||||
---
|
||||
### `setSchedule(schedule)`
|
||||
Sets the currently present train's schedule. This will overwrite the currently set schedule.
|
||||
|
||||
**Parameters**
|
||||
- _schedule:_ `table` The schedule to set the present train to.
|
||||
|
||||
**Throws**
|
||||
- If the station is not connected to a track.
|
||||
- If there is currently no train present at the station.
|
||||
|
||||
**See also**
|
||||
- [Lua Train Schedules](#Lua-Train-Schedules) How train schedules are represented in Lua.
|
|
@ -1,2 +0,0 @@
|
|||
Just before this PR is about to be merged this /wiki folder will be removed from the PR and the pages will be added to
|
||||
the wiki section of the Create GitHub under API Reference
|
Loading…
Reference in a new issue