mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-02-05 09:54:59 +01:00
merge mc1.19/dev
This commit is contained in:
commit
c847680b46
52 changed files with 1071 additions and 1387 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
|
|
|
@ -214,7 +214,7 @@ dependencies {
|
||||||
jarJar.ranged(it, '[MC1.19-1.1.5,)')
|
jarJar.ranged(it, '[MC1.19-1.1.5,)')
|
||||||
}
|
}
|
||||||
jarJar("com.jozufozu.flywheel:flywheel-forge-${flywheel_minecraft_version}:${flywheel_version}") {
|
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}")
|
implementation fg.deobf("com.tterrag.registrate:Registrate:${registrate_version}")
|
||||||
|
|
|
@ -4,7 +4,7 @@ org.gradle.jvmargs = -Xmx3G
|
||||||
org.gradle.daemon = false
|
org.gradle.daemon = false
|
||||||
|
|
||||||
# mod version info
|
# mod version info
|
||||||
mod_version = 0.5.1.c
|
mod_version = 0.5.1.e
|
||||||
artifact_minecraft_version = 1.19.2
|
artifact_minecraft_version = 1.19.2
|
||||||
|
|
||||||
minecraft_version = 1.19.2
|
minecraft_version = 1.19.2
|
||||||
|
@ -23,7 +23,7 @@ use_parchment = true
|
||||||
# dependency versions
|
# dependency versions
|
||||||
registrate_version = MC1.19-1.1.5
|
registrate_version = MC1.19-1.1.5
|
||||||
flywheel_minecraft_version = 1.19.2
|
flywheel_minecraft_version = 1.19.2
|
||||||
flywheel_version = 0.6.9-18
|
flywheel_version = 0.6.10-20
|
||||||
jei_minecraft_version = 1.19.2
|
jei_minecraft_version = 1.19.2
|
||||||
jei_version = 11.2.0.254
|
jei_version = 11.2.0.254
|
||||||
curios_minecraft_version = 1.19.2
|
curios_minecraft_version = 1.19.2
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
// 1.19.2 2023-08-24T18:35:23.8733985 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;
|
package com.simibubi.create;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.simibubi.create.compat.jei.ConversionRecipe;
|
import com.simibubi.create.compat.jei.ConversionRecipe;
|
||||||
import com.simibubi.create.content.equipment.sandPaper.SandPaperPolishingRecipe;
|
import com.simibubi.create.content.equipment.sandPaper.SandPaperPolishingRecipe;
|
||||||
import com.simibubi.create.content.equipment.toolbox.ToolboxDyeingRecipe;
|
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.crusher.CrushingRecipe;
|
||||||
import com.simibubi.create.content.kinetics.deployer.DeployerApplicationRecipe;
|
import com.simibubi.create.content.kinetics.deployer.DeployerApplicationRecipe;
|
||||||
import com.simibubi.create.content.kinetics.deployer.ManualApplicationRecipe;
|
import com.simibubi.create.content.kinetics.deployer.ManualApplicationRecipe;
|
||||||
import com.simibubi.create.content.kinetics.fan.HauntingRecipe;
|
import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe;
|
||||||
import com.simibubi.create.content.kinetics.fan.SplashingRecipe;
|
import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe;
|
||||||
import com.simibubi.create.content.kinetics.millstone.MillingRecipe;
|
import com.simibubi.create.content.kinetics.millstone.MillingRecipe;
|
||||||
import com.simibubi.create.content.kinetics.mixer.CompactingRecipe;
|
import com.simibubi.create.content.kinetics.mixer.CompactingRecipe;
|
||||||
import com.simibubi.create.content.kinetics.mixer.MixingRecipe;
|
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.content.processing.sequenced.SequencedAssemblyRecipeSerializer;
|
||||||
import com.simibubi.create.foundation.recipe.IRecipeTypeInfo;
|
import com.simibubi.create.foundation.recipe.IRecipeTypeInfo;
|
||||||
|
|
||||||
import net.createmod.catnip.platform.CatnipServices;
|
|
||||||
import net.createmod.catnip.utility.lang.Lang;
|
import net.createmod.catnip.utility.lang.Lang;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
@ -127,12 +124,9 @@ public enum AllRecipeTypes implements IRecipeTypeInfo {
|
||||||
.getRecipeFor(getType(), inv, world);
|
.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) {
|
public static boolean shouldIgnoreInAutomation(Recipe<?> recipe) {
|
||||||
RecipeSerializer<?> serializer = recipe.getSerializer();
|
RecipeSerializer<?> serializer = recipe.getSerializer();
|
||||||
if (serializer != null && RECIPE_DENY_SET.contains(CatnipServices.REGISTRIES.getKeyOrThrow(serializer)))
|
if (serializer != null && AllTags.AllRecipeSerializerTags.AUTOMATION_IGNORE.matches(serializer))
|
||||||
return true;
|
return true;
|
||||||
return recipe.getId()
|
return recipe.getId()
|
||||||
.getPath()
|
.getPath()
|
||||||
|
|
|
@ -19,6 +19,7 @@ import net.minecraft.world.entity.EntityType;
|
||||||
import net.minecraft.world.item.BlockItem;
|
import net.minecraft.world.item.BlockItem;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.material.Fluid;
|
import net.minecraft.world.level.material.Fluid;
|
||||||
|
@ -315,11 +316,54 @@ public class AllTags {
|
||||||
private static void init() {}
|
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(Registry.RECIPE_SERIALIZER_REGISTRY, 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() {
|
public static void init() {
|
||||||
AllBlockTags.init();
|
AllBlockTags.init();
|
||||||
AllItemTags.init();
|
AllItemTags.init();
|
||||||
AllFluidTags.init();
|
AllFluidTags.init();
|
||||||
AllEntityTags.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.equipment.potatoCannon.BuiltinPotatoProjectileTypes;
|
||||||
import com.simibubi.create.content.fluids.tank.BoilerHeaters;
|
import com.simibubi.create.content.fluids.tank.BoilerHeaters;
|
||||||
import com.simibubi.create.content.kinetics.TorquePropagator;
|
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.kinetics.mechanicalArm.AllArmInteractionPointTypes;
|
||||||
import com.simibubi.create.content.redstone.displayLink.AllDisplayBehaviours;
|
import com.simibubi.create.content.redstone.displayLink.AllDisplayBehaviours;
|
||||||
import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler;
|
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.schematics.ServerSchematicLoader;
|
||||||
import com.simibubi.create.content.trains.GlobalRailwayManager;
|
import com.simibubi.create.content.trains.GlobalRailwayManager;
|
||||||
import com.simibubi.create.content.trains.bogey.BogeySizes;
|
import com.simibubi.create.content.trains.bogey.BogeySizes;
|
||||||
|
@ -29,6 +29,7 @@ import com.simibubi.create.foundation.block.CopperRegistries;
|
||||||
import com.simibubi.create.foundation.data.AllLangPartials;
|
import com.simibubi.create.foundation.data.AllLangPartials;
|
||||||
import com.simibubi.create.foundation.data.CreateRegistrate;
|
import com.simibubi.create.foundation.data.CreateRegistrate;
|
||||||
import com.simibubi.create.foundation.data.LangMerger;
|
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.TagGen;
|
||||||
import com.simibubi.create.foundation.data.recipe.MechanicalCraftingRecipeGen;
|
import com.simibubi.create.foundation.data.recipe.MechanicalCraftingRecipeGen;
|
||||||
import com.simibubi.create.foundation.data.recipe.ProcessingRecipeGen;
|
import com.simibubi.create.foundation.data.recipe.ProcessingRecipeGen;
|
||||||
|
@ -71,7 +72,7 @@ public class Create {
|
||||||
|
|
||||||
public static final String ID = "create";
|
public static final String ID = "create";
|
||||||
public static final String NAME = "Create";
|
public static final String NAME = "Create";
|
||||||
public static final String VERSION = "0.5.1c";
|
public static final String VERSION = "0.5.1e";
|
||||||
|
|
||||||
public static final Logger LOGGER = LogUtils.getLogger();
|
public static final Logger LOGGER = LogUtils.getLogger();
|
||||||
|
|
||||||
|
@ -126,21 +127,26 @@ public class Create {
|
||||||
AllParticleTypes.register(modEventBus);
|
AllParticleTypes.register(modEventBus);
|
||||||
AllStructureProcessorTypes.register(modEventBus);
|
AllStructureProcessorTypes.register(modEventBus);
|
||||||
AllEntityDataSerializers.register(modEventBus);
|
AllEntityDataSerializers.register(modEventBus);
|
||||||
|
AllPackets.registerPackets();
|
||||||
AllOreFeatureConfigEntries.init();
|
AllOreFeatureConfigEntries.init();
|
||||||
AllFeatures.register(modEventBus);
|
AllFeatures.register(modEventBus);
|
||||||
AllPlacementModifiers.register(modEventBus);
|
AllPlacementModifiers.register(modEventBus);
|
||||||
BuiltinRegistration.register(modEventBus);
|
BuiltinRegistration.register(modEventBus);
|
||||||
BogeySizes.init();
|
|
||||||
AllBogeyStyles.register();
|
|
||||||
|
|
||||||
AllConfigs.register(modLoadingContext);
|
AllConfigs.register(modLoadingContext);
|
||||||
|
|
||||||
|
// FIXME: some of these registrations are not thread-safe
|
||||||
AllMovementBehaviours.registerDefaults();
|
AllMovementBehaviours.registerDefaults();
|
||||||
AllInteractionBehaviours.registerDefaults();
|
AllInteractionBehaviours.registerDefaults();
|
||||||
AllDisplayBehaviours.registerDefaults();
|
AllDisplayBehaviours.registerDefaults();
|
||||||
ContraptionMovementSetting.registerDefaults();
|
ContraptionMovementSetting.registerDefaults();
|
||||||
AllArmInteractionPointTypes.register();
|
AllArmInteractionPointTypes.register();
|
||||||
|
AllFanProcessingTypes.register();
|
||||||
BlockSpoutingBehaviour.registerDefaults();
|
BlockSpoutingBehaviour.registerDefaults();
|
||||||
|
BogeySizes.init();
|
||||||
|
AllBogeyStyles.register();
|
||||||
|
// ----
|
||||||
|
|
||||||
ComputerCraftProxy.register();
|
ComputerCraftProxy.register();
|
||||||
|
|
||||||
ForgeMod.enableMilkFluid();
|
ForgeMod.enableMilkFluid();
|
||||||
|
@ -152,21 +158,25 @@ public class Create {
|
||||||
|
|
||||||
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus));
|
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus));
|
||||||
|
|
||||||
|
// FIXME: this is not thread-safe
|
||||||
Mods.CURIOS.executeIfInstalled(() -> () -> Curios.init(modEventBus, forgeEventBus));
|
Mods.CURIOS.executeIfInstalled(() -> () -> Curios.init(modEventBus, forgeEventBus));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void init(final FMLCommonSetupEvent event) {
|
public static void init(final FMLCommonSetupEvent event) {
|
||||||
AllPackets.registerPackets();
|
AllFluids.registerFluidInteractions();
|
||||||
SchematicInstances.register();
|
|
||||||
BuiltinPotatoProjectileTypes.register();
|
|
||||||
CreateNBTProcessors.register();
|
CreateNBTProcessors.register();
|
||||||
|
|
||||||
event.enqueueWork(() -> {
|
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();
|
AttachedRegistry.unwrapAll();
|
||||||
AllAdvancements.register();
|
AllAdvancements.register();
|
||||||
AllTriggers.register();
|
AllTriggers.register();
|
||||||
BoilerHeaters.registerDefaults();
|
|
||||||
AllFluids.registerFluidInteractions();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,11 +188,13 @@ public class Create {
|
||||||
gen.addProvider(event.includeClient(), new LangMerger(gen, ID, NAME, AllLangPartials.values()));
|
gen.addProvider(event.includeClient(), new LangMerger(gen, ID, NAME, AllLangPartials.values()));
|
||||||
gen.addProvider(event.includeClient(), AllSoundEvents.provider(gen));
|
gen.addProvider(event.includeClient(), AllSoundEvents.provider(gen));
|
||||||
|
|
||||||
|
gen.addProvider(event.includeServer(), new RecipeSerializerTagGen(gen, event.getExistingFileHelper()));
|
||||||
gen.addProvider(event.includeServer(), new AllAdvancements(gen));
|
gen.addProvider(event.includeServer(), new AllAdvancements(gen));
|
||||||
gen.addProvider(event.includeServer(), new StandardRecipeGen(gen));
|
gen.addProvider(event.includeServer(), new StandardRecipeGen(gen));
|
||||||
gen.addProvider(event.includeServer(), new MechanicalCraftingRecipeGen(gen));
|
gen.addProvider(event.includeServer(), new MechanicalCraftingRecipeGen(gen));
|
||||||
gen.addProvider(event.includeServer(), new SequencedAssemblyRecipeGen(gen));
|
gen.addProvider(event.includeServer(), new SequencedAssemblyRecipeGen(gen));
|
||||||
|
|
||||||
|
|
||||||
if (event.includeServer()) {
|
if (event.includeServer()) {
|
||||||
ProcessingRecipeGen.registerAll(gen);
|
ProcessingRecipeGen.registerAll(gen);
|
||||||
//AllOreFeatureConfigEntries.gatherData(event);
|
//AllOreFeatureConfigEntries.gatherData(event);
|
||||||
|
|
|
@ -13,26 +13,42 @@ import net.minecraftforge.registries.ForgeRegistries;
|
||||||
* For compatibility with and without another mod present, we have to define load conditions of the specific code
|
* For compatibility with and without another mod present, we have to define load conditions of the specific code
|
||||||
*/
|
*/
|
||||||
public enum Mods {
|
public enum Mods {
|
||||||
DYNAMICTREES,
|
|
||||||
TCONSTRUCT,
|
|
||||||
CURIOS,
|
|
||||||
|
|
||||||
COMPUTERCRAFT,
|
COMPUTERCRAFT,
|
||||||
|
CONNECTIVITY,
|
||||||
|
CURIOS,
|
||||||
|
DYNAMICTREES,
|
||||||
|
OCCULTISM,
|
||||||
|
PACKETFIXER,
|
||||||
STORAGEDRAWERS,
|
STORAGEDRAWERS,
|
||||||
|
TCONSTRUCT,
|
||||||
XLPACKETS;
|
XLPACKETS;
|
||||||
|
|
||||||
/**
|
private final String id;
|
||||||
* @return a boolean of whether the mod is loaded or not based on mod id
|
|
||||||
*/
|
Mods() {
|
||||||
public boolean isLoaded() {
|
id = Lang.asId(name());
|
||||||
return ModList.get().isLoaded(asId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the mod id
|
* @return the mod id
|
||||||
*/
|
*/
|
||||||
public String asId() {
|
public String id() {
|
||||||
return Lang.asId(name());
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,8 +71,4 @@ public enum Mods {
|
||||||
toExecute.get().run();
|
toExecute.get().run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block getBlock(String id) {
|
|
||||||
return ForgeRegistries.BLOCKS.getValue(new ResourceLocation(asId(), id));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.DeployerApplicationRecipe;
|
||||||
import com.simibubi.create.content.kinetics.deployer.ItemApplicationRecipe;
|
import com.simibubi.create.content.kinetics.deployer.ItemApplicationRecipe;
|
||||||
import com.simibubi.create.content.kinetics.deployer.ManualApplicationRecipe;
|
import com.simibubi.create.content.kinetics.deployer.ManualApplicationRecipe;
|
||||||
import com.simibubi.create.content.kinetics.fan.HauntingRecipe;
|
import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe;
|
||||||
import com.simibubi.create.content.kinetics.fan.SplashingRecipe;
|
import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe;
|
||||||
import com.simibubi.create.content.kinetics.press.MechanicalPressBlockEntity;
|
import com.simibubi.create.content.kinetics.press.MechanicalPressBlockEntity;
|
||||||
import com.simibubi.create.content.kinetics.press.PressingRecipe;
|
import com.simibubi.create.content.kinetics.press.PressingRecipe;
|
||||||
import com.simibubi.create.content.kinetics.saw.CuttingRecipe;
|
import com.simibubi.create.content.kinetics.saw.CuttingRecipe;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
|
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.AllGuiTextures;
|
||||||
|
|
||||||
import net.createmod.catnip.gui.element.GuiGameElement;
|
import net.createmod.catnip.gui.element.GuiGameElement;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics;
|
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 net.createmod.catnip.gui.element.GuiGameElement;
|
import net.createmod.catnip.gui.element.GuiGameElement;
|
||||||
import net.minecraft.world.level.material.Fluids;
|
import net.minecraft.world.level.material.Fluids;
|
||||||
|
|
|
@ -3,39 +3,35 @@ package com.simibubi.create.compat.storageDrawers;
|
||||||
import com.simibubi.create.compat.Mods;
|
import com.simibubi.create.compat.Mods;
|
||||||
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
|
import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour;
|
||||||
|
|
||||||
|
import net.createmod.catnip.platform.CatnipServices;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
|
||||||
import net.minecraftforge.items.IItemHandler;
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
|
||||||
public class StorageDrawers {
|
public class StorageDrawers {
|
||||||
|
|
||||||
public static boolean isDrawer(BlockEntity be) {
|
public static boolean isDrawer(BlockEntity be) {
|
||||||
return be != null && Mods.STORAGEDRAWERS.asId()
|
return be != null && Mods.STORAGEDRAWERS.id().equals(
|
||||||
.equals(BlockEntityType.getKey(be.getType())
|
CatnipServices.REGISTRIES.getKeyOrThrow(be.getType()).getNamespace());
|
||||||
.getNamespace());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float getTrueFillLevel(IItemHandler inv, FilteringBehaviour filtering) {
|
public static float getTrueFillLevel(IItemHandler inv, FilteringBehaviour filtering) {
|
||||||
float occupied = 0;
|
float occupied = 0;
|
||||||
float totalSpace = 0;
|
float totalSpace = 0;
|
||||||
|
|
||||||
for (int slot = 1; slot < inv.getSlots(); slot++) {
|
for (int slot = 1; slot < inv.getSlots(); slot++) {
|
||||||
ItemStack stackInSlot = inv.getStackInSlot(slot);
|
ItemStack stackInSlot = inv.getStackInSlot(slot);
|
||||||
int space = inv.getSlotLimit(slot);
|
int space = inv.getSlotLimit(slot);
|
||||||
int count = stackInSlot.getCount();
|
int count = stackInSlot.getCount();
|
||||||
if (space == 0)
|
if (space == 0) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
totalSpace += 1;
|
totalSpace += 1;
|
||||||
if (filtering.test(stackInSlot))
|
if (filtering.test(stackInSlot)) occupied += count * (1f / space);
|
||||||
occupied += count * (1f / space);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalSpace == 0)
|
if (totalSpace == 0) return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
return occupied / totalSpace;
|
return occupied / totalSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -337,7 +337,7 @@ public class BlockMovementChecks {
|
||||||
return direction == state.getValue(StickerBlock.FACING)
|
return direction == state.getValue(StickerBlock.FACING)
|
||||||
&& !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite());
|
&& !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite());
|
||||||
}
|
}
|
||||||
if (block instanceof AbstractBogeyBlock bogey)
|
if (block instanceof AbstractBogeyBlock<?> bogey)
|
||||||
return bogey.getStickySurfaces(world, pos, state)
|
return bogey.getStickySurfaces(world, pos, state)
|
||||||
.contains(direction);
|
.contains(direction);
|
||||||
if (block instanceof WhistleBlock)
|
if (block instanceof WhistleBlock)
|
||||||
|
|
|
@ -1376,7 +1376,7 @@ public abstract class Contraption {
|
||||||
return blocks.values();
|
return blocks.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<BlockEntity> getSpecialRenderedTEs() {
|
public Collection<BlockEntity> getSpecialRenderedBEs() {
|
||||||
return specialRenderedBlockEntities;
|
return specialRenderedBlockEntities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,17 +14,46 @@ public class ContraptionData {
|
||||||
/**
|
/**
|
||||||
* A sane, default maximum for contraption data size.
|
* 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.
|
* 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}).
|
* Minecart item sizes are limited by the vanilla slot change packet ({@link ClientboundContainerSetSlotPacket}).
|
||||||
* {@link ContraptionData#DEFAULT_MAX} is used as the default.
|
* {@link #DEFAULT_LIMIT} 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.
|
* 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.
|
* @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.
|
* @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) {
|
public static boolean isTooLargeForPickup(CompoundTag data) {
|
||||||
return packetSize(data) > PICKUP_MAX;
|
return packetSize(data) > PICKUP_LIMIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -119,9 +119,9 @@ public class ContraptionRenderDispatcher {
|
||||||
ContraptionWorld contraptionWorld = c.getContraptionWorld();
|
ContraptionWorld contraptionWorld = c.getContraptionWorld();
|
||||||
|
|
||||||
BlockPos origin = c.anchor;
|
BlockPos origin = c.anchor;
|
||||||
int height = contraptionWorld.getHeight();
|
|
||||||
int minBuildHeight = contraptionWorld.getMinBuildHeight();
|
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
|
@Override
|
||||||
public boolean supportsFlywheel() {
|
public boolean supportsFlywheel() {
|
||||||
return canInstance();
|
return canInstance();
|
||||||
|
@ -134,13 +134,13 @@ public class ContraptionRenderDispatcher {
|
||||||
// Skip individual lighting updates to prevent lag with large contraptions
|
// Skip individual lighting updates to prevent lag with large contraptions
|
||||||
renderWorld.setBlock(info.pos, info.state, Block.UPDATE_SUPPRESS_LIGHT);
|
renderWorld.setBlock(info.pos, info.state, Block.UPDATE_SUPPRESS_LIGHT);
|
||||||
|
|
||||||
renderWorld.runLightingEngine();
|
renderWorld.runLightEngine();
|
||||||
return renderWorld;
|
return renderWorld;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void renderBlockEntities(Level world, VirtualRenderWorld renderWorld, Contraption c,
|
public static void renderBlockEntities(Level world, VirtualRenderWorld renderWorld, Contraption c,
|
||||||
ContraptionMatrices matrices, MultiBufferSource buffer) {
|
ContraptionMatrices matrices, MultiBufferSource buffer) {
|
||||||
BlockEntityRenderHelper.renderBlockEntities(world, renderWorld, c.getSpecialRenderedTEs(),
|
BlockEntityRenderHelper.renderBlockEntities(world, renderWorld, c.getSpecialRenderedBEs(),
|
||||||
matrices.getModelViewProjection(), matrices.getLight(), buffer);
|
matrices.getModelViewProjection(), matrices.getLight(), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,15 +31,14 @@ public class CopycatBarsModel extends CopycatModel {
|
||||||
protected List<BakedQuad> getCroppedQuads(BlockState state, Direction side, RandomSource rand, BlockState material,
|
protected List<BakedQuad> getCroppedQuads(BlockState state, Direction side, RandomSource rand, BlockState material,
|
||||||
ModelData wrappedData, RenderType renderType) {
|
ModelData wrappedData, RenderType renderType) {
|
||||||
BakedModel model = getModelOf(material);
|
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> superQuads = originalModel.getQuads(state, side, rand, wrappedData, renderType);
|
||||||
List<BakedQuad> quads = new ArrayList<>();
|
|
||||||
TextureAtlasSprite targetSprite = model.getParticleIcon(wrappedData);
|
TextureAtlasSprite targetSprite = model.getParticleIcon(wrappedData);
|
||||||
|
|
||||||
boolean vertical = state.getValue(CopycatPanelBlock.FACING)
|
boolean vertical = state.getValue(CopycatPanelBlock.FACING)
|
||||||
.getAxis() == Axis.Y;
|
.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++) {
|
for (int i = 0; i < templateQuads.size(); i++) {
|
||||||
BakedQuad quad = templateQuads.get(i);
|
BakedQuad quad = templateQuads.get(i);
|
||||||
if (quad.getDirection() != Direction.UP)
|
if (quad.getDirection() != Direction.UP)
|
||||||
|
@ -47,10 +46,13 @@ public class CopycatBarsModel extends CopycatModel {
|
||||||
targetSprite = quad.getSprite();
|
targetSprite = quad.getSprite();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (targetSprite == null)
|
if (targetSprite == null)
|
||||||
return superQuads;
|
return superQuads;
|
||||||
|
|
||||||
|
List<BakedQuad> quads = new ArrayList<>();
|
||||||
|
|
||||||
for (int i = 0; i < superQuads.size(); i++) {
|
for (int i = 0; i < superQuads.size(); i++) {
|
||||||
BakedQuad quad = superQuads.get(i);
|
BakedQuad quad = superQuads.get(i);
|
||||||
TextureAtlasSprite original = quad.getSprite();
|
TextureAtlasSprite original = quad.getSprite();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.simibubi.create.content.decoration.copycat;
|
package com.simibubi.create.content.decoration.copycat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
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,
|
// Rubidium: render side!=null versions of the base material during side==null,
|
||||||
// to avoid getting culled away
|
// 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)
|
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));
|
croppedQuads.addAll(getCroppedQuads(state, nonOcclusionSide, rand, material, wrappedData, renderType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return croppedQuads;
|
return croppedQuads;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The returned list must not be mutated.
|
||||||
|
*/
|
||||||
protected abstract List<BakedQuad> getCroppedQuads(BlockState state, Direction side, RandomSource rand,
|
protected abstract List<BakedQuad> getCroppedQuads(BlockState state, Direction side, RandomSource rand,
|
||||||
BlockState material, ModelData wrappedData, RenderType renderType);
|
BlockState material, ModelData wrappedData, RenderType renderType);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ package com.simibubi.create.content.kinetics.belt.transport;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import com.simibubi.create.content.kinetics.belt.BeltHelper;
|
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.core.Direction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
@ -25,7 +25,7 @@ public class TransportedItemStack implements Comparable<TransportedItemStack> {
|
||||||
public float prevBeltPosition;
|
public float prevBeltPosition;
|
||||||
public float prevSideOffset;
|
public float prevSideOffset;
|
||||||
|
|
||||||
public FanProcessing.Type processedBy;
|
public FanProcessingType processedBy;
|
||||||
public int processingTime;
|
public int processingTime;
|
||||||
|
|
||||||
public TransportedItemStack(ItemStack stack) {
|
public TransportedItemStack(ItemStack stack) {
|
||||||
|
|
|
@ -16,4 +16,9 @@ public abstract class AbstractCrushingRecipe extends ProcessingRecipe<RecipeWrap
|
||||||
protected int getMaxInputCount() {
|
protected int getMaxInputCount() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canSpecifyDuration() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,9 @@ import com.simibubi.create.AllTags;
|
||||||
import com.simibubi.create.content.decoration.copycat.CopycatBlock;
|
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;
|
||||||
import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult;
|
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.advancement.AllAdvancements;
|
||||||
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
|
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
|
||||||
import com.simibubi.create.infrastructure.config.AllConfigs;
|
import com.simibubi.create.infrastructure.config.AllConfigs;
|
||||||
|
@ -29,7 +31,6 @@ import net.minecraft.world.entity.item.ItemEntity;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
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.AABB;
|
||||||
import net.minecraft.world.phys.BlockHitResult;
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
@ -49,7 +50,7 @@ public class AirCurrent {
|
||||||
public boolean pushing;
|
public boolean pushing;
|
||||||
public float maxDistance;
|
public float maxDistance;
|
||||||
|
|
||||||
protected List<Pair<TransportedItemStackHandlerBehaviour, FanProcessing.Type>> affectedItemHandlers =
|
protected List<Pair<TransportedItemStackHandlerBehaviour, FanProcessingType>> affectedItemHandlers =
|
||||||
new ArrayList<>();
|
new ArrayList<>();
|
||||||
protected List<Entity> caughtEntities = new ArrayList<>();
|
protected List<Entity> caughtEntities = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -110,14 +111,14 @@ public class AirCurrent {
|
||||||
((ServerPlayer) entity).connection.aboveGroundTickCount = 0;
|
((ServerPlayer) entity).connection.aboveGroundTickCount = 0;
|
||||||
|
|
||||||
entityDistance -= .5f;
|
entityDistance -= .5f;
|
||||||
FanProcessing.Type processingType = getSegmentAt((float) entityDistance);
|
FanProcessingType processingType = getSegmentAt((float) entityDistance);
|
||||||
|
|
||||||
if (processingType == null || processingType == Type.NONE)
|
if (processingType == AllFanProcessingTypes.NONE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (entity instanceof ItemEntity itemEntity) {
|
if (entity instanceof ItemEntity itemEntity) {
|
||||||
if (world.isClientSide) {
|
if (world != null && world.isClientSide) {
|
||||||
processingType.spawnParticlesForProcessing(world, entity.position());
|
processingType.spawnProcessingParticles(world, entity.position());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (FanProcessing.canProcess(itemEntity, processingType))
|
if (FanProcessing.canProcess(itemEntity, processingType))
|
||||||
|
@ -127,7 +128,8 @@ public class AirCurrent {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
processingType.affectEntity(entity, world);
|
if (world != null)
|
||||||
|
processingType.affectEntity(entity, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -155,7 +157,7 @@ public class AirCurrent {
|
||||||
AirCurrentSegment currentSegment = new AirCurrentSegment();
|
AirCurrentSegment currentSegment = new AirCurrentSegment();
|
||||||
segments.clear();
|
segments.clear();
|
||||||
currentSegment.startOffset = 0;
|
currentSegment.startOffset = 0;
|
||||||
FanProcessing.Type type = Type.NONE;
|
FanProcessingType type = AllFanProcessingTypes.NONE;
|
||||||
|
|
||||||
int limit = (int) (maxDistance + .5f);
|
int limit = (int) (maxDistance + .5f);
|
||||||
int searchStart = pushing ? 0 : limit;
|
int searchStart = pushing ? 0 : limit;
|
||||||
|
@ -164,8 +166,8 @@ public class AirCurrent {
|
||||||
|
|
||||||
for (int i = searchStart; i * searchStep <= searchEnd * searchStep; i += searchStep) {
|
for (int i = searchStart; i * searchStep <= searchEnd * searchStep; i += searchStep) {
|
||||||
BlockPos currentPos = start.relative(direction, i);
|
BlockPos currentPos = start.relative(direction, i);
|
||||||
FanProcessing.Type newType = FanProcessing.Type.byBlock(world, currentPos);
|
FanProcessingType newType = FanProcessingType.getAt(world, currentPos);
|
||||||
if (newType != Type.NONE)
|
if (newType != AllFanProcessingTypes.NONE)
|
||||||
type = newType;
|
type = newType;
|
||||||
if (currentSegment.type != type || currentSegment.startOffset == 0) {
|
if (currentSegment.type != type || currentSegment.startOffset == 0) {
|
||||||
currentSegment.endOffset = i;
|
currentSegment.endOffset = i;
|
||||||
|
@ -258,21 +260,18 @@ public class AirCurrent {
|
||||||
BlockPos start = source.getAirCurrentPos();
|
BlockPos start = source.getAirCurrentPos();
|
||||||
affectedItemHandlers.clear();
|
affectedItemHandlers.clear();
|
||||||
for (int i = 0; i < maxDistance + 1; i++) {
|
for (int i = 0; i < maxDistance + 1; i++) {
|
||||||
Type type = getSegmentAt(i);
|
FanProcessingType segmentType = getSegmentAt(i);
|
||||||
if (type == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (int offset : Iterate.zeroAndOne) {
|
for (int offset : Iterate.zeroAndOne) {
|
||||||
BlockPos pos = start.relative(direction, i)
|
BlockPos pos = start.relative(direction, i)
|
||||||
.below(offset);
|
.below(offset);
|
||||||
TransportedItemStackHandlerBehaviour behaviour =
|
TransportedItemStackHandlerBehaviour behaviour =
|
||||||
BlockEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE);
|
BlockEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE);
|
||||||
FanProcessing.Type typeAtHandler = type;
|
if (behaviour == null)
|
||||||
if (world.getFluidState(pos)
|
continue;
|
||||||
.is(Fluids.WATER))
|
FanProcessingType type = FanProcessingType.getAt(world, pos);
|
||||||
typeAtHandler = Type.SPLASHING;
|
if (type == AllFanProcessingTypes.NONE)
|
||||||
if (behaviour != null)
|
type = segmentType;
|
||||||
affectedItemHandlers.add(Pair.of(behaviour, typeAtHandler));
|
affectedItemHandlers.add(Pair.of(behaviour, type));
|
||||||
if (direction.getAxis()
|
if (direction.getAxis()
|
||||||
.isVertical())
|
.isVertical())
|
||||||
break;
|
break;
|
||||||
|
@ -281,15 +280,14 @@ public class AirCurrent {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tickAffectedHandlers() {
|
public void tickAffectedHandlers() {
|
||||||
for (Pair<TransportedItemStackHandlerBehaviour, Type> pair : affectedItemHandlers) {
|
for (Pair<TransportedItemStackHandlerBehaviour, FanProcessingType> pair : affectedItemHandlers) {
|
||||||
TransportedItemStackHandlerBehaviour handler = pair.getKey();
|
TransportedItemStackHandlerBehaviour handler = pair.getKey();
|
||||||
Level world = handler.getWorld();
|
Level world = handler.getWorld();
|
||||||
FanProcessing.Type processingType = pair.getRight();
|
FanProcessingType processingType = pair.getRight();
|
||||||
|
|
||||||
handler.handleProcessingOnAllItems((transported) -> {
|
handler.handleProcessingOnAllItems(transported -> {
|
||||||
if (world.isClientSide) {
|
if (world.isClientSide) {
|
||||||
if (world != null)
|
processingType.spawnProcessingParticles(world, handler.getWorldPositionOf(transported));
|
||||||
processingType.spawnParticlesForProcessing(world, handler.getWorldPositionOf(transported));
|
|
||||||
return TransportedResult.doNothing();
|
return TransportedResult.doNothing();
|
||||||
}
|
}
|
||||||
TransportedResult applyProcessing = FanProcessing.applyProcessing(transported, world, processingType);
|
TransportedResult applyProcessing = FanProcessing.applyProcessing(transported, world, processingType);
|
||||||
|
@ -304,7 +302,7 @@ public class AirCurrent {
|
||||||
return AllTags.AllBlockTags.FAN_TRANSPARENT.matches(state);
|
return AllTags.AllBlockTags.FAN_TRANSPARENT.matches(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FanProcessing.Type getSegmentAt(float offset) {
|
public FanProcessingType getSegmentAt(float offset) {
|
||||||
for (AirCurrentSegment airCurrentSegment : segments) {
|
for (AirCurrentSegment airCurrentSegment : segments) {
|
||||||
if (offset > airCurrentSegment.endOffset && pushing)
|
if (offset > airCurrentSegment.endOffset && pushing)
|
||||||
continue;
|
continue;
|
||||||
|
@ -312,11 +310,11 @@ public class AirCurrent {
|
||||||
continue;
|
continue;
|
||||||
return airCurrentSegment.type;
|
return airCurrentSegment.type;
|
||||||
}
|
}
|
||||||
return FanProcessing.Type.NONE;
|
return AllFanProcessingTypes.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AirCurrentSegment {
|
public static class AirCurrentSegment {
|
||||||
FanProcessing.Type type;
|
FanProcessingType type;
|
||||||
int startOffset;
|
int startOffset;
|
||||||
int endOffset;
|
int endOffset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,10 @@ package com.simibubi.create.content.kinetics.fan;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.kinetics.fan.processing.AllFanProcessingTypes;
|
||||||
|
import com.simibubi.create.content.kinetics.fan.processing.FanProcessingType;
|
||||||
|
|
||||||
import net.createmod.catnip.utility.VecHelper;
|
import net.createmod.catnip.utility.VecHelper;
|
||||||
import net.createmod.catnip.utility.theme.Color;
|
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
import net.minecraft.client.particle.Particle;
|
import net.minecraft.client.particle.Particle;
|
||||||
import net.minecraft.client.particle.ParticleProvider;
|
import net.minecraft.client.particle.ParticleProvider;
|
||||||
|
@ -12,16 +14,15 @@ import net.minecraft.client.particle.SimpleAnimatedParticle;
|
||||||
import net.minecraft.client.particle.SpriteSet;
|
import net.minecraft.client.particle.SpriteSet;
|
||||||
import net.minecraft.client.renderer.LevelRenderer;
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.particles.BlockParticleOption;
|
import net.minecraft.core.particles.ParticleOptions;
|
||||||
import net.minecraft.core.particles.ParticleTypes;
|
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
public class AirFlowParticle extends SimpleAnimatedParticle {
|
public class AirFlowParticle extends SimpleAnimatedParticle {
|
||||||
|
|
||||||
private final IAirCurrentSource source;
|
private final IAirCurrentSource source;
|
||||||
|
private final Access access = new Access();
|
||||||
|
|
||||||
protected AirFlowParticle(ClientLevel world, IAirCurrentSource source, double x, double y, double z,
|
protected AirFlowParticle(ClientLevel world, IAirCurrentSource source, double x, double y, double z,
|
||||||
SpriteSet sprite) {
|
SpriteSet sprite) {
|
||||||
|
@ -31,11 +32,12 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
|
||||||
this.lifetime = 40;
|
this.lifetime = 40;
|
||||||
hasPhysics = false;
|
hasPhysics = false;
|
||||||
selectSprite(7);
|
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.setPos(x + offset.x, y + offset.y, z + offset.z);
|
||||||
this.xo = x;
|
this.xo = x;
|
||||||
this.yo = y;
|
this.yo = y;
|
||||||
this.zo = z;
|
this.zo = z;
|
||||||
|
setColor(0xEEEEEE);
|
||||||
setAlpha(.25f);
|
setAlpha(.25f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,36 +49,44 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
if (source == null || source.isSourceRemoved()) {
|
if (source == null || source.isSourceRemoved()) {
|
||||||
dissipate();
|
remove();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.xo = this.x;
|
this.xo = this.x;
|
||||||
this.yo = this.y;
|
this.yo = this.y;
|
||||||
this.zo = this.z;
|
this.zo = this.z;
|
||||||
if (this.age++ >= this.lifetime) {
|
if (this.age++ >= this.lifetime) {
|
||||||
this.remove();
|
remove();
|
||||||
} else {
|
} else {
|
||||||
if (source.getAirCurrent() == null || !source.getAirCurrent().bounds.inflate(.25f).contains(x, y, z)) {
|
AirCurrent airCurrent = source.getAirCurrent();
|
||||||
dissipate();
|
if (airCurrent == null || !airCurrent.bounds.inflate(.25f).contains(x, y, z)) {
|
||||||
|
remove();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 directionVec = Vec3.atLowerCornerOf(source.getAirCurrent().direction.getNormal());
|
Vec3 directionVec = Vec3.atLowerCornerOf(airCurrent.direction.getNormal());
|
||||||
Vec3 motion = directionVec.scale(1 / 8f);
|
Vec3 motion = directionVec.scale(1 / 8f);
|
||||||
if (!source.getAirCurrent().pushing)
|
if (!source.getAirCurrent().pushing)
|
||||||
motion = motion.scale(-1);
|
motion = motion.scale(-1);
|
||||||
|
|
||||||
double distance = new Vec3(x, y, z).subtract(VecHelper.getCenterOf(source.getAirCurrentPos()))
|
double distance = new Vec3(x, y, z).subtract(VecHelper.getCenterOf(source.getAirCurrentPos()))
|
||||||
.multiply(directionVec).length() - .5f;
|
.multiply(directionVec).length() - .5f;
|
||||||
if (distance > source.getAirCurrent().maxDistance + 1 || distance < -.25f) {
|
if (distance > airCurrent.maxDistance + 1 || distance < -.25f) {
|
||||||
dissipate();
|
remove();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
motion = motion.scale(source.getAirCurrent().maxDistance - (distance - 1f)).scale(.5f);
|
motion = motion.scale(airCurrent.maxDistance - (distance - 1f)).scale(.5f);
|
||||||
selectSprite((int) Mth.clamp((distance / source.getAirCurrent().maxDistance) * 8 + level.random.nextInt(4),
|
|
||||||
0, 7));
|
|
||||||
|
|
||||||
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;
|
xd = motion.x;
|
||||||
yd = motion.y;
|
yd = motion.y;
|
||||||
|
@ -92,68 +102,10 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void morphType(double distance) {
|
private FanProcessingType getType(double distance) {
|
||||||
if (source.getAirCurrent() == null)
|
if (source.getAirCurrent() == null)
|
||||||
return;
|
return AllFanProcessingTypes.NONE;
|
||||||
FanProcessing.Type type = source.getAirCurrent().getSegmentAt((float) distance);
|
return 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLightColor(float partialTick) {
|
public int getLightColor(float partialTick) {
|
||||||
|
@ -181,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,452 +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.mojang.math.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.infrastructure.config.AllConfigs;
|
|
||||||
|
|
||||||
import net.createmod.catnip.utility.VecHelper;
|
|
||||||
import net.createmod.catnip.utility.theme.Color;
|
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
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 DamageSource FIRE_DAMAGE_SOURCE = new DamageSource("create.fan_fire").setScalesWithDifficulty()
|
|
||||||
.setIsFire();
|
|
||||||
private static final DamageSource LAVA_DAMAGE_SOURCE = new DamageSource("create.fan_lava").setScalesWithDifficulty()
|
|
||||||
.setIsFire();
|
|
||||||
|
|
||||||
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(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(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()) {
|
|
||||||
if (!smokingRecipe.isPresent() || !ItemStack.isSame(smokingRecipe.get()
|
|
||||||
.getResultItem(),
|
|
||||||
smeltingRecipe.get()
|
|
||||||
.getResultItem())) {
|
|
||||||
return RecipeApplier.applyRecipeOn(stack, smeltingRecipe.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == Type.SMOKING && smokingRecipe.isPresent())
|
|
||||||
return RecipeApplier.applyRecipeOn(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(DamageSource.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(FIRE_DAMAGE_SOURCE, 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(LAVA_DAMAGE_SOURCE, 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,488 @@
|
||||||
|
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 com.mojang.math.Vector3f;
|
||||||
|
import com.simibubi.create.AllBlocks;
|
||||||
|
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 it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
|
||||||
|
import net.createmod.catnip.utility.VecHelper;
|
||||||
|
import net.createmod.catnip.utility.theme.Color;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
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.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.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));
|
||||||
|
private static final DamageSource LAVA_DAMAGE_SOURCE = new DamageSource("create.fan_lava").setScalesWithDifficulty()
|
||||||
|
.setIsFire();
|
||||||
|
|
||||||
|
@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()) {
|
||||||
|
if (!smokingRecipe.isPresent() || !ItemStack.isSame(smokingRecipe.get()
|
||||||
|
.getResultItem(),
|
||||||
|
smeltingRecipe.get()
|
||||||
|
.getResultItem())) {
|
||||||
|
return RecipeApplier.applyRecipeOn(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(LAVA_DAMAGE_SOURCE, 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(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));
|
||||||
|
private static final DamageSource FIRE_DAMAGE_SOURCE = new DamageSource("create.fan_fire").setScalesWithDifficulty()
|
||||||
|
.setIsFire();
|
||||||
|
|
||||||
|
@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(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(FIRE_DAMAGE_SOURCE, 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(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(DamageSource.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 javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
import com.simibubi.create.AllRecipeTypes;
|
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.ProcessingRecipe;
|
||||||
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams;
|
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams;
|
||||||
|
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraftforge.items.ItemStackHandler;
|
||||||
|
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||||
|
|
||||||
@ParametersAreNonnullByDefault
|
@ParametersAreNonnullByDefault
|
||||||
public class HauntingRecipe extends ProcessingRecipe<FanProcessing.HauntingWrapper> {
|
public class HauntingRecipe extends ProcessingRecipe<HauntingWrapper> {
|
||||||
|
|
||||||
public HauntingRecipe(ProcessingRecipeParams params) {
|
public HauntingRecipe(ProcessingRecipeParams params) {
|
||||||
super(AllRecipeTypes.HAUNTING, params);
|
super(AllRecipeTypes.HAUNTING, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(FanProcessing.HauntingWrapper inv, Level worldIn) {
|
public boolean matches(HauntingWrapper inv, Level worldIn) {
|
||||||
if (inv.isEmpty())
|
if (inv.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
return ingredients.get(0)
|
return ingredients.get(0)
|
||||||
|
@ -33,4 +36,10 @@ public class HauntingRecipe extends ProcessingRecipe<FanProcessing.HauntingWrapp
|
||||||
return 12;
|
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 javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
import com.simibubi.create.AllRecipeTypes;
|
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.ProcessingRecipe;
|
||||||
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams;
|
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams;
|
||||||
|
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraftforge.items.ItemStackHandler;
|
||||||
|
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||||
|
|
||||||
@ParametersAreNonnullByDefault
|
@ParametersAreNonnullByDefault
|
||||||
public class SplashingRecipe extends ProcessingRecipe<FanProcessing.SplashingWrapper> {
|
public class SplashingRecipe extends ProcessingRecipe<SplashingWrapper> {
|
||||||
|
|
||||||
public SplashingRecipe(ProcessingRecipeParams params) {
|
public SplashingRecipe(ProcessingRecipeParams params) {
|
||||||
super(AllRecipeTypes.SPLASHING, params);
|
super(AllRecipeTypes.SPLASHING, params);
|
||||||
|
@ -34,4 +36,10 @@ public class SplashingRecipe extends ProcessingRecipe<FanProcessing.SplashingWra
|
||||||
return 12;
|
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;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canSpecifyDuration() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addAssemblyIngredients(List<Ingredient> list) {}
|
public void addAssemblyIngredients(List<Ingredient> list) {}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.AllRecipeTypes;
|
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.BookAuthorAttribute;
|
||||||
import com.simibubi.create.content.logistics.filter.attribute.BookCopyAttribute;
|
import com.simibubi.create.content.logistics.filter.attribute.BookCopyAttribute;
|
||||||
import com.simibubi.create.content.logistics.filter.attribute.ColorAttribute;
|
import com.simibubi.create.content.logistics.filter.attribute.ColorAttribute;
|
||||||
|
@ -146,8 +146,8 @@ public interface ItemAttribute {
|
||||||
EQUIPABLE(s -> LivingEntity.getEquipmentSlotForItem(s)
|
EQUIPABLE(s -> LivingEntity.getEquipmentSlotForItem(s)
|
||||||
.getType() != EquipmentSlot.Type.HAND),
|
.getType() != EquipmentSlot.Type.HAND),
|
||||||
FURNACE_FUEL(AbstractFurnaceBlockEntity::isFuel),
|
FURNACE_FUEL(AbstractFurnaceBlockEntity::isFuel),
|
||||||
WASHABLE(FanProcessing::isWashable),
|
WASHABLE(AllFanProcessingTypes.SPLASHING::canProcess),
|
||||||
HAUNTABLE(FanProcessing::isHauntable),
|
HAUNTABLE(AllFanProcessingTypes.HAUNTING::canProcess),
|
||||||
CRUSHABLE((s, w) -> testRecipe(s, w, AllRecipeTypes.CRUSHING.getType())
|
CRUSHABLE((s, w) -> testRecipe(s, w, AllRecipeTypes.CRUSHING.getType())
|
||||||
|| testRecipe(s, w, AllRecipeTypes.MILLING.getType())),
|
|| testRecipe(s, w, AllRecipeTypes.MILLING.getType())),
|
||||||
SMELTABLE((s, w) -> testRecipe(s, w, RecipeType.SMELTING)),
|
SMELTABLE((s, w) -> testRecipe(s, w, RecipeType.SMELTING)),
|
||||||
|
|
|
@ -208,6 +208,11 @@ public class BasinRecipe extends ProcessingRecipe<SmartInventory> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canSpecifyDuration() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(SmartInventory inv, @Nonnull Level worldIn) {
|
public boolean matches(SmartInventory inv, @Nonnull Level worldIn) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -71,7 +71,7 @@ public abstract class ProcessingRecipe<T extends Container> implements Recipe<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canSpecifyDuration() {
|
protected boolean canSpecifyDuration() {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getMaxFluidInputCount() {
|
protected int getMaxFluidInputCount() {
|
||||||
|
|
|
@ -237,10 +237,10 @@ public class AllDisplayBehaviours {
|
||||||
Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> {
|
Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> {
|
||||||
DisplayBehaviour computerDisplaySource = register(Create.asResource("computer_display_source"), new ComputerDisplaySource());
|
DisplayBehaviour computerDisplaySource = register(Create.asResource("computer_display_source"), new ComputerDisplaySource());
|
||||||
|
|
||||||
assignBlockEntity(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "wired_modem_full"));
|
assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("wired_modem_full"));
|
||||||
assignBlockEntity(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_normal"));
|
assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_normal"));
|
||||||
assignBlockEntity(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_advanced"));
|
assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_advanced"));
|
||||||
assignBlockEntity(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_command"));
|
assignBlockEntity(computerDisplaySource, Mods.COMPUTERCRAFT.rl("computer_command"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,19 +24,13 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
|
||||||
|
|
||||||
public class SchematicInstances {
|
public class SchematicInstances {
|
||||||
|
|
||||||
public static final WorldAttached<Cache<Integer, SchematicLevel>> loadedSchematics;
|
private static final WorldAttached<Cache<Integer, SchematicLevel>> LOADED_SCHEMATICS = new WorldAttached<>($ -> CacheBuilder.newBuilder()
|
||||||
|
|
||||||
static {
|
|
||||||
loadedSchematics = new WorldAttached<>($ -> CacheBuilder.newBuilder()
|
|
||||||
.expireAfterAccess(5, TimeUnit.MINUTES)
|
.expireAfterAccess(5, TimeUnit.MINUTES)
|
||||||
.build());
|
.build());
|
||||||
}
|
|
||||||
|
|
||||||
public static void register() {}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static SchematicLevel get(Level world, ItemStack schematic) {
|
public static SchematicLevel get(Level world, ItemStack schematic) {
|
||||||
Cache<Integer, SchematicLevel> map = loadedSchematics.get(world);
|
Cache<Integer, SchematicLevel> map = LOADED_SCHEMATICS.get(world);
|
||||||
int hash = getHash(schematic);
|
int hash = getHash(schematic);
|
||||||
SchematicLevel ifPresent = map.getIfPresent(hash);
|
SchematicLevel ifPresent = map.getIfPresent(hash);
|
||||||
if (ifPresent != null)
|
if (ifPresent != null)
|
||||||
|
|
|
@ -289,9 +289,9 @@ public class CarriageContraption extends Contraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<BlockEntity> getSpecialRenderedTEs() {
|
public Collection<BlockEntity> getSpecialRenderedBEs() {
|
||||||
if (notInPortal())
|
if (notInPortal())
|
||||||
return super.getSpecialRenderedTEs();
|
return super.getSpecialRenderedBEs();
|
||||||
return specialRenderedBEsOutsidePortal;
|
return specialRenderedBEsOutsidePortal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import com.simibubi.create.AllSpecialTextures;
|
||||||
import com.simibubi.create.AllTags;
|
import com.simibubi.create.AllTags;
|
||||||
import com.simibubi.create.content.equipment.blueprint.BlueprintOverlayRenderer;
|
import com.simibubi.create.content.equipment.blueprint.BlueprintOverlayRenderer;
|
||||||
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
|
import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
|
||||||
|
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||||
import com.simibubi.create.foundation.utility.CreateLang;
|
import com.simibubi.create.foundation.utility.CreateLang;
|
||||||
import com.simibubi.create.infrastructure.config.AllConfigs;
|
import com.simibubi.create.infrastructure.config.AllConfigs;
|
||||||
|
|
||||||
|
@ -44,7 +45,6 @@ import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.EntityBlock;
|
import net.minecraft.world.level.block.EntityBlock;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
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.BlockHitResult;
|
||||||
import net.minecraft.world.phys.HitResult;
|
import net.minecraft.world.phys.HitResult;
|
||||||
import net.minecraft.world.phys.HitResult.Type;
|
import net.minecraft.world.phys.HitResult.Type;
|
||||||
|
@ -478,18 +478,6 @@ public class TrackPlacement {
|
||||||
info.requiredPavement += TrackPaver.paveCurve(level, info.curve, block, simulate, visited);
|
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,
|
private static PlacementInfo placeTracks(Level level, PlacementInfo info, BlockState state1, BlockState state2,
|
||||||
BlockPos targetPos1, BlockPos targetPos2, boolean simulate) {
|
BlockPos targetPos1, BlockPos targetPos2, boolean simulate) {
|
||||||
info.requiredTracks = 0;
|
info.requiredTracks = 0;
|
||||||
|
@ -518,7 +506,7 @@ public class TrackPlacement {
|
||||||
BlockPos offsetPos = pos.offset(offset.x, offset.y, offset.z);
|
BlockPos offsetPos = pos.offset(offset.x, offset.y, offset.z);
|
||||||
BlockState stateAtPos = level.getBlockState(offsetPos);
|
BlockState stateAtPos = level.getBlockState(offsetPos);
|
||||||
// copy over all shared properties from the shaped state to the correct track material block
|
// 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.getMaterial()
|
boolean canPlace = stateAtPos.getMaterial()
|
||||||
.isReplaceable();
|
.isReplaceable();
|
||||||
|
@ -544,12 +532,12 @@ public class TrackPlacement {
|
||||||
BlockState onto = info.trackMaterial.getBlock().defaultBlockState();
|
BlockState onto = info.trackMaterial.getBlock().defaultBlockState();
|
||||||
BlockState stateAtPos = level.getBlockState(targetPos1);
|
BlockState stateAtPos = level.getBlockState(targetPos1);
|
||||||
level.setBlock(targetPos1, ProperWaterloggedBlock.withWater(level,
|
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);
|
.setValue(TrackBlock.HAS_BE, true), targetPos1), 3);
|
||||||
|
|
||||||
stateAtPos = level.getBlockState(targetPos2);
|
stateAtPos = level.getBlockState(targetPos2);
|
||||||
level.setBlock(targetPos2, ProperWaterloggedBlock.withWater(level,
|
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);
|
.setValue(TrackBlock.HAS_BE, true), targetPos2), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.simibubi.create.foundation.data;
|
||||||
|
|
||||||
|
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.Registry;
|
||||||
|
import net.minecraft.data.DataGenerator;
|
||||||
|
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(DataGenerator generator, @Nullable ExistingFileHelper existingFileHelper) {
|
||||||
|
super(generator, Registry.RECIPE_SERIALIZER, Create.ID, existingFileHelper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Create's Recipe Serializer Tags";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addTags() {
|
||||||
|
this.tag(AllRecipeSerializerTags.AUTOMATION_IGNORE.tag)
|
||||||
|
.addOptional(Mods.OCCULTISM.rl("spirit_trade"))
|
||||||
|
.addOptional(Mods.OCCULTISM.rl("ritual"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 = "Lcom/mojang/math/Matrix3f;mul(F)V", shift = Shift.AFTER), 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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -31,7 +31,7 @@ public class CKinetics extends ConfigBase {
|
||||||
public final ConfigGroup contraptions = group(1, "contraptions", "Moving Contraptions");
|
public final ConfigGroup contraptions = group(1, "contraptions", "Moving Contraptions");
|
||||||
public final ConfigInt maxBlocksMoved = i(2048, 1, "maxBlocksMoved", Comments.maxBlocksMoved);
|
public final ConfigInt maxBlocksMoved = i(2048, 1, "maxBlocksMoved", Comments.maxBlocksMoved);
|
||||||
public final ConfigInt maxDataSize =
|
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 maxChassisRange = i(16, 1, "maxChassisRange", Comments.maxChassisRange);
|
||||||
public final ConfigInt maxPistonPoles = i(64, 1, "maxPistonPoles", Comments.maxPistonPoles);
|
public final ConfigInt maxPistonPoles = i(64, 1, "maxPistonPoles", Comments.maxPistonPoles);
|
||||||
public final ConfigInt maxRopeLength = i(256, 1, "maxRopeLength", Comments.maxRopeLength);
|
public final ConfigInt maxRopeLength = i(256, 1, "maxRopeLength", Comments.maxRopeLength);
|
||||||
|
|
|
@ -9,7 +9,6 @@ import com.tterrag.registrate.util.entry.RegistryEntry;
|
||||||
|
|
||||||
import net.createmod.ponder.foundation.CustomPonderRegistrationHelper;
|
import net.createmod.ponder.foundation.CustomPonderRegistrationHelper;
|
||||||
import net.createmod.ponder.foundation.PonderTag;
|
import net.createmod.ponder.foundation.PonderTag;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraft.world.item.DyeColor;
|
import net.minecraft.world.item.DyeColor;
|
||||||
import net.minecraft.world.item.Items;
|
import net.minecraft.world.item.Items;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
|
@ -318,7 +317,7 @@ public class AllPonderTags {
|
||||||
.add(Blocks.TARGET);
|
.add(Blocks.TARGET);
|
||||||
|
|
||||||
Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> {
|
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)
|
if (computer != null)
|
||||||
HELPER.addToTag(DISPLAY_SOURCES).add(computer);
|
HELPER.addToTag(DISPLAY_SOURCES).add(computer);
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,7 +32,7 @@ ${mod_description}
|
||||||
[[dependencies.create]]
|
[[dependencies.create]]
|
||||||
modId="flywheel"
|
modId="flywheel"
|
||||||
mandatory=true
|
mandatory=true
|
||||||
versionRange="[0.6.9,0.6.10)"
|
versionRange="[0.6.10,0.6.11)"
|
||||||
ordering="AFTER"
|
ordering="AFTER"
|
||||||
side="CLIENT"
|
side="CLIENT"
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
"client.BlockDestructionProgressMixin",
|
"client.BlockDestructionProgressMixin",
|
||||||
"client.CameraMixin",
|
"client.CameraMixin",
|
||||||
"client.EntityContraptionInteractionMixin",
|
"client.EntityContraptionInteractionMixin",
|
||||||
"client.FixNormalScalingMixin",
|
|
||||||
"client.GameRendererMixin",
|
"client.GameRendererMixin",
|
||||||
"client.HeavyBootsOnPlayerMixin",
|
"client.HeavyBootsOnPlayerMixin",
|
||||||
"client.HumanoidArmorLayerMixin",
|
"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