Merge 50e7140900
into 0bfd98fccd
This commit is contained in:
commit
764b7ea5ab
|
@ -3,8 +3,8 @@ package com.simibubi.create.content.kinetics.belt.transport;
|
|||
import java.util.Random;
|
||||
|
||||
import com.simibubi.create.content.kinetics.belt.BeltHelper;
|
||||
import com.simibubi.create.content.kinetics.fan.FanProcessing;
|
||||
|
||||
import com.simibubi.create.content.kinetics.fan.AbstractFanProcessingType;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
@ -25,7 +25,7 @@ public class TransportedItemStack implements Comparable<TransportedItemStack> {
|
|||
public float prevBeltPosition;
|
||||
public float prevSideOffset;
|
||||
|
||||
public FanProcessing.Type processedBy;
|
||||
public AbstractFanProcessingType processedBy;
|
||||
public int processingTime;
|
||||
|
||||
public TransportedItemStack(ItemStack stack) {
|
||||
|
@ -95,4 +95,4 @@ public class TransportedItemStack implements Comparable<TransportedItemStack> {
|
|||
return stack;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package com.simibubi.create.content.kinetics.fan;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Make Class extending this if you want to add your own Fan processing type.
|
||||
* After that, register it's condition using {@link ProcessingTypeTransformerRegistry#registerProcessingTypeTransformer(int, ProcessingTypeTransformerRegistry.ProcessingTypeTransformer)}
|
||||
*/
|
||||
public abstract class AbstractFanProcessingType {
|
||||
|
||||
public static final Map<String, AbstractFanProcessingType> REGISTRY = Maps.newConcurrentMap();
|
||||
public static final AbstractFanProcessingType NONE = new AbstractFanProcessingType("NONE") {
|
||||
@Override
|
||||
public void spawnParticlesForProcessing(Level level, Vec3 pos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void affectEntity(Entity entity, Level level) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void particleMorphType(AirFlowParticle particle) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> process(ItemStack stack, AbstractFanProcessingType type, Level world) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
public final String name;
|
||||
|
||||
public AbstractFanProcessingType(String name) {
|
||||
this.name = name;
|
||||
AbstractFanProcessingType old = REGISTRY.put(name, this);
|
||||
if (old != null) {
|
||||
throw new IllegalArgumentException("repeated processing type name: "
|
||||
+ name + " for class " + old.getClass().getCanonicalName()
|
||||
+ " and class " + this.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
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 abstract void particleMorphType(AirFlowParticle particle);
|
||||
|
||||
public abstract List<ItemStack> process(ItemStack stack, AbstractFanProcessingType type, Level world);
|
||||
|
||||
public static AbstractFanProcessingType valueOf(String name) {
|
||||
return REGISTRY.getOrDefault(name, NONE);
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
|
@ -10,7 +10,6 @@ import com.simibubi.create.AllTags;
|
|||
import com.simibubi.create.content.decoration.copycat.CopycatBlock;
|
||||
import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour;
|
||||
import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult;
|
||||
import com.simibubi.create.content.kinetics.fan.FanProcessing.Type;
|
||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
@ -49,7 +48,7 @@ public class AirCurrent {
|
|||
public boolean pushing;
|
||||
public float maxDistance;
|
||||
|
||||
protected List<Pair<TransportedItemStackHandlerBehaviour, FanProcessing.Type>> affectedItemHandlers =
|
||||
protected List<Pair<TransportedItemStackHandlerBehaviour, AbstractFanProcessingType>> affectedItemHandlers =
|
||||
new ArrayList<>();
|
||||
protected List<Entity> caughtEntities = new ArrayList<>();
|
||||
|
||||
|
@ -110,9 +109,9 @@ public class AirCurrent {
|
|||
((ServerPlayer) entity).connection.aboveGroundTickCount = 0;
|
||||
|
||||
entityDistance -= .5f;
|
||||
FanProcessing.Type processingType = getSegmentAt((float) entityDistance);
|
||||
AbstractFanProcessingType processingType = getSegmentAt((float) entityDistance);
|
||||
|
||||
if (processingType == null || processingType == Type.NONE)
|
||||
if (processingType == null || processingType == AbstractFanProcessingType.NONE)
|
||||
continue;
|
||||
|
||||
if (entity instanceof ItemEntity itemEntity) {
|
||||
|
@ -155,7 +154,7 @@ public class AirCurrent {
|
|||
AirCurrentSegment currentSegment = new AirCurrentSegment();
|
||||
segments.clear();
|
||||
currentSegment.startOffset = 0;
|
||||
FanProcessing.Type type = Type.NONE;
|
||||
AbstractFanProcessingType type = AbstractFanProcessingType.NONE;
|
||||
|
||||
int limit = (int) (maxDistance + .5f);
|
||||
int searchStart = pushing ? 0 : limit;
|
||||
|
@ -164,8 +163,8 @@ public class AirCurrent {
|
|||
|
||||
for (int i = searchStart; i * searchStep <= searchEnd * searchStep; i += searchStep) {
|
||||
BlockPos currentPos = start.relative(direction, i);
|
||||
FanProcessing.Type newType = FanProcessing.Type.byBlock(world, currentPos);
|
||||
if (newType != Type.NONE)
|
||||
AbstractFanProcessingType newType = ProcessingTypeTransformerRegistry.byBlock(world, currentPos);
|
||||
if (newType != AbstractFanProcessingType.NONE)
|
||||
type = newType;
|
||||
if (currentSegment.type != type || currentSegment.startOffset == 0) {
|
||||
currentSegment.endOffset = i;
|
||||
|
@ -217,6 +216,9 @@ public class AirCurrent {
|
|||
BlockState copycatState = CopycatBlock.getMaterial(world, currentPos);
|
||||
if (shouldAlwaysPass(copycatState.isAir() ? state : copycatState))
|
||||
continue;
|
||||
// If there's defined Processing Type for the block, it's probably passable for the Air Current
|
||||
if (ProcessingTypeTransformerRegistry.byBlock(world, currentPos) != AbstractFanProcessingType.NONE)
|
||||
continue;
|
||||
VoxelShape voxelshape = state.getCollisionShape(world, currentPos, CollisionContext.empty());
|
||||
if (voxelshape.isEmpty())
|
||||
continue;
|
||||
|
@ -258,7 +260,7 @@ public class AirCurrent {
|
|||
BlockPos start = source.getAirCurrentPos();
|
||||
affectedItemHandlers.clear();
|
||||
for (int i = 0; i < maxDistance + 1; i++) {
|
||||
Type type = getSegmentAt(i);
|
||||
AbstractFanProcessingType type = getSegmentAt(i);
|
||||
if (type == null)
|
||||
continue;
|
||||
|
||||
|
@ -267,10 +269,10 @@ public class AirCurrent {
|
|||
.below(offset);
|
||||
TransportedItemStackHandlerBehaviour behaviour =
|
||||
BlockEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE);
|
||||
FanProcessing.Type typeAtHandler = type;
|
||||
AbstractFanProcessingType typeAtHandler = type;
|
||||
if (world.getFluidState(pos)
|
||||
.is(Fluids.WATER))
|
||||
typeAtHandler = Type.SPLASHING;
|
||||
typeAtHandler = FanProcessing.SPLASHING;
|
||||
if (behaviour != null)
|
||||
affectedItemHandlers.add(Pair.of(behaviour, typeAtHandler));
|
||||
if (direction.getAxis()
|
||||
|
@ -281,10 +283,10 @@ public class AirCurrent {
|
|||
}
|
||||
|
||||
public void tickAffectedHandlers() {
|
||||
for (Pair<TransportedItemStackHandlerBehaviour, Type> pair : affectedItemHandlers) {
|
||||
for (Pair<TransportedItemStackHandlerBehaviour, AbstractFanProcessingType> pair : affectedItemHandlers) {
|
||||
TransportedItemStackHandlerBehaviour handler = pair.getKey();
|
||||
Level world = handler.getWorld();
|
||||
FanProcessing.Type processingType = pair.getRight();
|
||||
AbstractFanProcessingType processingType = pair.getRight();
|
||||
|
||||
handler.handleProcessingOnAllItems((transported) -> {
|
||||
if (world.isClientSide) {
|
||||
|
@ -304,7 +306,7 @@ public class AirCurrent {
|
|||
return AllTags.AllBlockTags.FAN_TRANSPARENT.matches(state);
|
||||
}
|
||||
|
||||
public FanProcessing.Type getSegmentAt(float offset) {
|
||||
public AbstractFanProcessingType getSegmentAt(float offset) {
|
||||
for (AirCurrentSegment airCurrentSegment : segments) {
|
||||
if (offset > airCurrentSegment.endOffset && pushing)
|
||||
continue;
|
||||
|
@ -312,11 +314,11 @@ public class AirCurrent {
|
|||
continue;
|
||||
return airCurrentSegment.type;
|
||||
}
|
||||
return FanProcessing.Type.NONE;
|
||||
return AbstractFanProcessingType.NONE;
|
||||
}
|
||||
|
||||
public static class AirCurrentSegment {
|
||||
FanProcessing.Type type;
|
||||
AbstractFanProcessingType type;
|
||||
int startOffset;
|
||||
int endOffset;
|
||||
}
|
||||
|
|
|
@ -14,10 +14,8 @@ import net.minecraft.client.particle.SimpleAnimatedParticle;
|
|||
import net.minecraft.client.particle.SpriteSet;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.particles.BlockParticleOption;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
|
@ -97,60 +95,75 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
|
|||
public void morphType(double distance) {
|
||||
if (source.getAirCurrent() == null)
|
||||
return;
|
||||
FanProcessing.Type type = source.getAirCurrent().getSegmentAt((float) distance);
|
||||
AbstractFanProcessingType type = source.getAirCurrent().getSegmentAt((float) distance);
|
||||
|
||||
if (type == FanProcessing.Type.SPLASHING) {
|
||||
setColor(Color.mixColors(0x4499FF, 0x2277FF, level.random.nextFloat()));
|
||||
setAlpha(1f);
|
||||
selectSprite(level.random.nextInt(3));
|
||||
if (level.random.nextFloat() < 1 / 32f)
|
||||
level.addParticle(ParticleTypes.BUBBLE, x, y, z, xd * .125f, yd * .125f,
|
||||
zd * .125f);
|
||||
if (level.random.nextFloat() < 1 / 32f)
|
||||
level.addParticle(ParticleTypes.BUBBLE_POP, x, y, z, xd * .125f, yd * .125f,
|
||||
zd * .125f);
|
||||
}
|
||||
// if (type == FanProcessing.Type.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.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.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 == 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);
|
||||
return;
|
||||
}
|
||||
|
||||
type.particleMorphType(this);
|
||||
}
|
||||
|
||||
public void setProperties(int color_1, int color_2, float alpha, int sprite_length) {
|
||||
setColor(Color.mixColors(color_1, color_2, level.random.nextFloat()));
|
||||
setAlpha(alpha);
|
||||
selectSprite(level.random.nextInt(sprite_length));
|
||||
}
|
||||
|
||||
public void addParticle(ParticleOptions option, float chance, float speed) {
|
||||
if (level.random.nextFloat() < chance) {
|
||||
level.addParticle(option, x, y, z, xd * speed, yd * speed, zd * speed);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,71 +1,38 @@
|
|||
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.foundation.utility.Color;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
import com.simibubi.create.content.kinetics.fan.processingTypes.BlastingType;
|
||||
import com.simibubi.create.content.kinetics.fan.processingTypes.HauntingType;
|
||||
import com.simibubi.create.content.kinetics.fan.processingTypes.SmokingType;
|
||||
import com.simibubi.create.content.kinetics.fan.processingTypes.SplashingType;
|
||||
import com.simibubi.create.infrastructure.config.AllConfigs;
|
||||
|
||||
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()
|
||||
public 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()
|
||||
public static final DamageSource LAVA_DAMAGE_SOURCE = new DamageSource("create.fan_lava").setScalesWithDifficulty()
|
||||
.setIsFire();
|
||||
public static final AbstractFanProcessingType SPLASHING = new SplashingType();
|
||||
public static final AbstractFanProcessingType SMOKING = new SmokingType();
|
||||
public static final AbstractFanProcessingType HAUNTING = new HauntingType();
|
||||
public static final AbstractFanProcessingType BLASTING = new BlastingType();
|
||||
|
||||
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 final RecipeWrapper RECIPE_WRAPPER = new RecipeWrapper(new ItemStackHandler(1));
|
||||
|
||||
public static boolean canProcess(ItemEntity entity, Type type) {
|
||||
public static boolean canProcess(ItemEntity entity, AbstractFanProcessingType type) {
|
||||
if (entity.getPersistentData()
|
||||
.contains("CreateData")) {
|
||||
CompoundTag compound = entity.getPersistentData()
|
||||
|
@ -73,7 +40,7 @@ public class FanProcessing {
|
|||
if (compound.contains("Processing")) {
|
||||
CompoundTag processing = compound.getCompound("Processing");
|
||||
|
||||
if (Type.valueOf(processing.getString("Type")) != type)
|
||||
if (AbstractFanProcessingType.valueOf(processing.getString("Type")) != type)
|
||||
return type.canProcess(entity.getItem(), entity.level);
|
||||
else if (processing.getInt("Time") >= 0)
|
||||
return true;
|
||||
|
@ -84,19 +51,7 @@ public class FanProcessing {
|
|||
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) {
|
||||
public static boolean applyProcessing(ItemEntity entity, AbstractFanProcessingType type) {
|
||||
if (decrementProcessingTime(entity, type) != 0)
|
||||
return false;
|
||||
List<ItemStack> stacks = process(entity.getItem(), type, entity.level);
|
||||
|
@ -115,7 +70,7 @@ public class FanProcessing {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static TransportedResult applyProcessing(TransportedItemStack transported, Level world, Type type) {
|
||||
public static TransportedResult applyProcessing(TransportedItemStack transported, Level world, AbstractFanProcessingType type) {
|
||||
TransportedResult ignore = TransportedResult.doNothing();
|
||||
if (transported.processedBy != type) {
|
||||
transported.processedBy = type;
|
||||
|
@ -145,55 +100,13 @@ public class FanProcessing {
|
|||
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());
|
||||
private static List<ItemStack> process(ItemStack stack, AbstractFanProcessingType type, Level world) {
|
||||
if (type != null) return type.process(stack, type, world);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int decrementProcessingTime(ItemEntity entity, Type type) {
|
||||
private static int decrementProcessingTime(ItemEntity entity, AbstractFanProcessingType type) {
|
||||
CompoundTag nbt = entity.getPersistentData();
|
||||
|
||||
if (!nbt.contains("CreateData"))
|
||||
|
@ -204,7 +117,7 @@ public class FanProcessing {
|
|||
createData.put("Processing", new CompoundTag());
|
||||
CompoundTag processing = createData.getCompound("Processing");
|
||||
|
||||
if (!processing.contains("Type") || Type.valueOf(processing.getString("Type")) != type) {
|
||||
if (!processing.contains("Type") || AbstractFanProcessingType.valueOf(processing.getString("Type")) != type) {
|
||||
processing.putString("Type", type.name());
|
||||
int timeModifierForStackSize = ((entity.getItem()
|
||||
.getCount() - 1) / 16) + 1;
|
||||
|
@ -218,235 +131,4 @@ public class FanProcessing {
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,20 +3,21 @@ package com.simibubi.create.content.kinetics.fan;
|
|||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.content.kinetics.fan.processingTypes.HauntingType;
|
||||
import com.simibubi.create.content.processing.recipe.ProcessingRecipe;
|
||||
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams;
|
||||
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public class HauntingRecipe extends ProcessingRecipe<FanProcessing.HauntingWrapper> {
|
||||
public class HauntingRecipe extends ProcessingRecipe<HauntingType.HauntingWrapper> {
|
||||
|
||||
public HauntingRecipe(ProcessingRecipeParams params) {
|
||||
super(AllRecipeTypes.HAUNTING, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(FanProcessing.HauntingWrapper inv, Level worldIn) {
|
||||
public boolean matches(HauntingType.HauntingWrapper inv, Level worldIn) {
|
||||
if (inv.isEmpty())
|
||||
return false;
|
||||
return ingredients.get(0)
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package com.simibubi.create.content.kinetics.fan;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
|
||||
import com.simibubi.create.content.processing.burner.LitBlazeBurnerBlock;
|
||||
import com.simibubi.create.foundation.utility.Pair;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
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 java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import static com.simibubi.create.content.processing.burner.BlazeBurnerBlock.getHeatLevelOf;
|
||||
|
||||
public class ProcessingTypeTransformerRegistry {
|
||||
|
||||
private static final List<Pair<Integer, ProcessingTypeTransformer>> REG = Lists.newArrayList();
|
||||
private static List<ProcessingTypeTransformer> REG_SORTED = Collections.emptyList();
|
||||
|
||||
static {
|
||||
registerProcessingTypeTransformer(0, (BlockGetter reader, BlockPos pos) -> {
|
||||
FluidState fluidState = reader.getFluidState(pos);
|
||||
if (fluidState.getType() == Fluids.WATER || fluidState.getType() == Fluids.FLOWING_WATER)
|
||||
return FanProcessing.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 FanProcessing.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 FanProcessing.SMOKING;
|
||||
if (block == Blocks.LAVA || getHeatLevelOf(blockState).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING))
|
||||
return FanProcessing.BLASTING;
|
||||
return AbstractFanProcessingType.NONE;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Air Current Transformation.
|
||||
* @param priority Priority of this transform (smallest comes first)
|
||||
* @param transformer Function that provides a Processing Type or {@link AbstractFanProcessingType#NONE}
|
||||
* if no processing type is available
|
||||
*/
|
||||
|
||||
public static void registerProcessingTypeTransformer(int priority, ProcessingTypeTransformer transformer) {
|
||||
REG.add(Pair.of(priority, transformer));
|
||||
REG_SORTED = rebuild();
|
||||
}
|
||||
|
||||
public static AbstractFanProcessingType byBlock(BlockGetter reader, BlockPos pos) {
|
||||
for (ProcessingTypeTransformer ptt : REG_SORTED) {
|
||||
AbstractFanProcessingType processingType = ptt.apply(reader, pos);
|
||||
if (processingType != AbstractFanProcessingType.NONE) return processingType;
|
||||
}
|
||||
return AbstractFanProcessingType.NONE;
|
||||
}
|
||||
|
||||
private static List<ProcessingTypeTransformer> rebuild() {
|
||||
return REG.stream().sorted(Comparator.comparing(Pair::getFirst)).map(Pair::getSecond).toList();
|
||||
}
|
||||
|
||||
public interface ProcessingTypeTransformer extends BiFunction<BlockGetter, BlockPos, AbstractFanProcessingType> {}
|
||||
}
|
|
@ -3,14 +3,14 @@ package com.simibubi.create.content.kinetics.fan;
|
|||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.content.kinetics.fan.FanProcessing.SplashingWrapper;
|
||||
import com.simibubi.create.content.kinetics.fan.processingTypes.SplashingType.SplashingWrapper;
|
||||
import com.simibubi.create.content.processing.recipe.ProcessingRecipe;
|
||||
import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams;
|
||||
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public class SplashingRecipe extends ProcessingRecipe<FanProcessing.SplashingWrapper> {
|
||||
public class SplashingRecipe extends ProcessingRecipe<SplashingWrapper> {
|
||||
|
||||
public SplashingRecipe(ProcessingRecipeParams params) {
|
||||
super(AllRecipeTypes.SPLASHING, params);
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
package com.simibubi.create.content.kinetics.fan.processingTypes;
|
||||
|
||||
import com.simibubi.create.content.kinetics.fan.AirFlowParticle;
|
||||
import com.simibubi.create.content.kinetics.fan.FanProcessing;
|
||||
import com.simibubi.create.content.kinetics.fan.AbstractFanProcessingType;
|
||||
import com.simibubi.create.foundation.recipe.RecipeApplier;
|
||||
|
||||
import net.minecraft.core.particles.BlockParticleOption;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.*;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class BlastingType extends AbstractFanProcessingType {
|
||||
public BlastingType() {
|
||||
super("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(FanProcessing.LAVA_DAMAGE_SOURCE, 4);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void particleMorphType(AirFlowParticle particle) {
|
||||
particle.setProperties(0xFF4400, 0xFF8855, .5f, 3);
|
||||
particle.addParticle(ParticleTypes.FLAME, 1 / 128f, .25f);
|
||||
particle.addParticle(new BlockParticleOption(ParticleTypes.BLOCK, Blocks.LAVA.defaultBlockState()),
|
||||
1 / 16f, .25f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> process(ItemStack stack, AbstractFanProcessingType type, Level world) {
|
||||
FanProcessing.RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<SmokingRecipe> smokingRecipe = world.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMOKING, FanProcessing.RECIPE_WRAPPER, world);
|
||||
FanProcessing.RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<? extends AbstractCookingRecipe> smeltingRecipe = world.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMELTING, FanProcessing.RECIPE_WRAPPER, world);
|
||||
if (!smeltingRecipe.isPresent()) {
|
||||
FanProcessing.RECIPE_WRAPPER.setItem(0, stack);
|
||||
smeltingRecipe = world.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.BLASTING, FanProcessing.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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
FanProcessing.RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<SmeltingRecipe> smeltingRecipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMELTING, FanProcessing.RECIPE_WRAPPER, level);
|
||||
|
||||
if (smeltingRecipe.isPresent())
|
||||
return true;
|
||||
|
||||
FanProcessing.RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<BlastingRecipe> blastingRecipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.BLASTING, FanProcessing.RECIPE_WRAPPER, level);
|
||||
|
||||
if (blastingRecipe.isPresent())
|
||||
return true;
|
||||
|
||||
return !stack.getItem()
|
||||
.isFireResistant();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
package com.simibubi.create.content.kinetics.fan.processingTypes;
|
||||
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.content.kinetics.fan.AirFlowParticle;
|
||||
import com.simibubi.create.content.kinetics.fan.AbstractFanProcessingType;
|
||||
import com.simibubi.create.content.kinetics.fan.HauntingRecipe;
|
||||
import com.simibubi.create.foundation.recipe.RecipeApplier;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
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.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class HauntingType extends AbstractFanProcessingType {
|
||||
public static final HauntingWrapper HAUNTING_WRAPPER = new HauntingWrapper();
|
||||
|
||||
public HauntingType() {
|
||||
super("HAUNTING");
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@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 void particleMorphType(AirFlowParticle particle) {
|
||||
particle.setProperties(0x0, 0x126568, 1f, 3);
|
||||
particle.addParticle(ParticleTypes.SOUL_FIRE_FLAME, 1 / 128f, .125f);
|
||||
particle.addParticle(ParticleTypes.SMOKE, 1 / 32f, .125f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> process(ItemStack stack, AbstractFanProcessingType type, Level world) {
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
return isHauntable(stack, level);
|
||||
}
|
||||
|
||||
public static class HauntingWrapper extends RecipeWrapper {
|
||||
public HauntingWrapper() {
|
||||
super(new ItemStackHandler(1));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package com.simibubi.create.content.kinetics.fan.processingTypes;
|
||||
|
||||
import com.simibubi.create.content.kinetics.fan.AirFlowParticle;
|
||||
import com.simibubi.create.content.kinetics.fan.FanProcessing;
|
||||
import com.simibubi.create.content.kinetics.fan.AbstractFanProcessingType;
|
||||
import com.simibubi.create.foundation.recipe.RecipeApplier;
|
||||
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.item.crafting.SmokingRecipe;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class SmokingType extends AbstractFanProcessingType {
|
||||
public SmokingType() {
|
||||
super("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(FanProcessing.FIRE_DAMAGE_SOURCE, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void particleMorphType(AirFlowParticle particle) {
|
||||
particle.setProperties(0x0, 0x555555, 1f, 3);
|
||||
particle.addParticle(ParticleTypes.SMOKE, 1 / 32f, .125f);
|
||||
particle.addParticle(ParticleTypes.LARGE_SMOKE, 1 / 32f, .125f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> process(ItemStack stack, AbstractFanProcessingType type, Level world) {
|
||||
FanProcessing.RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<SmokingRecipe> smokingRecipe = world.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMOKING, FanProcessing.RECIPE_WRAPPER, world);
|
||||
if (smokingRecipe.isPresent()) return RecipeApplier.applyRecipeOn(stack, smokingRecipe.get());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
FanProcessing.RECIPE_WRAPPER.setItem(0, stack);
|
||||
Optional<SmokingRecipe> recipe = level.getRecipeManager()
|
||||
.getRecipeFor(RecipeType.SMOKING, FanProcessing.RECIPE_WRAPPER, level);
|
||||
return recipe.isPresent();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
package com.simibubi.create.content.kinetics.fan.processingTypes;
|
||||
|
||||
import com.mojang.math.Vector3f;
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.content.kinetics.fan.AirFlowParticle;
|
||||
import com.simibubi.create.content.kinetics.fan.AbstractFanProcessingType;
|
||||
import com.simibubi.create.content.kinetics.fan.SplashingRecipe;
|
||||
import com.simibubi.create.foundation.recipe.RecipeApplier;
|
||||
import com.simibubi.create.foundation.utility.Color;
|
||||
|
||||
import net.minecraft.core.particles.DustParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.monster.EnderMan;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class SplashingType extends AbstractFanProcessingType {
|
||||
public static final SplashingWrapper SPLASHING_WRAPPER = new SplashingWrapper();
|
||||
|
||||
public SplashingType() {
|
||||
super("SPLASHING");
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@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 void particleMorphType(AirFlowParticle particle) {
|
||||
particle.setProperties(0x4499FF, 0x2277FF, 1f, 3);
|
||||
particle.addParticle(ParticleTypes.BUBBLE, 1 / 32f, .125f);
|
||||
particle.addParticle(ParticleTypes.BUBBLE_POP, 1 / 32f, .125f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> process(ItemStack stack, AbstractFanProcessingType type, Level world) {
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(ItemStack stack, Level level) {
|
||||
return isWashable(stack, level);
|
||||
}
|
||||
|
||||
public static class SplashingWrapper extends RecipeWrapper {
|
||||
public SplashingWrapper() {
|
||||
super(new ItemStackHandler(1));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,11 +9,13 @@ import java.util.function.BiPredicate;
|
|||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.simibubi.create.content.kinetics.fan.processingTypes.HauntingType;
|
||||
import com.simibubi.create.content.kinetics.fan.processingTypes.SplashingType;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.simibubi.create.AllRecipeTypes;
|
||||
import com.simibubi.create.content.kinetics.fan.FanProcessing;
|
||||
import com.simibubi.create.content.logistics.filter.attribute.BookAuthorAttribute;
|
||||
import com.simibubi.create.content.logistics.filter.attribute.BookCopyAttribute;
|
||||
import com.simibubi.create.content.logistics.filter.attribute.ColorAttribute;
|
||||
|
@ -145,8 +147,8 @@ public interface ItemAttribute {
|
|||
EQUIPABLE(s -> LivingEntity.getEquipmentSlotForItem(s)
|
||||
.getType() != EquipmentSlot.Type.HAND),
|
||||
FURNACE_FUEL(AbstractFurnaceBlockEntity::isFuel),
|
||||
WASHABLE(FanProcessing::isWashable),
|
||||
HAUNTABLE(FanProcessing::isHauntable),
|
||||
WASHABLE(SplashingType::isWashable),
|
||||
HAUNTABLE(HauntingType::isHauntable),
|
||||
CRUSHABLE((s, w) -> testRecipe(s, w, AllRecipeTypes.CRUSHING.getType())
|
||||
|| testRecipe(s, w, AllRecipeTypes.MILLING.getType())),
|
||||
SMELTABLE((s, w) -> testRecipe(s, w, RecipeType.SMELTING)),
|
||||
|
|
Loading…
Reference in a new issue