dENUMinating fan processing

- Transform Fan Processing Types from Enum to Abstract class with subclasses
- Reorganise AirFlowParticle code and move type specific code to types themselves
This commit is contained in:
Lgmrszd 2023-07-18 21:30:12 +03:00
parent 0bfd98fccd
commit a411666dc8
No known key found for this signature in database
GPG key ID: D8E0CC2BFF5D4D9B
12 changed files with 610 additions and 410 deletions

View file

@ -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;
}
}
}

View file

@ -0,0 +1,113 @@
package com.simibubi.create.content.kinetics.fan;
import com.google.common.collect.Maps;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.processing.burner.LitBlazeBurnerBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
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 java.util.List;
import java.util.Map;
import static com.simibubi.create.content.processing.burner.BlazeBurnerBlock.getHeatLevelOf;
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 byBlock(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;
}
public static AbstractFanProcessingType valueOf(String name) {
return REGISTRY.getOrDefault(name, NONE);
}
public String name() {
return this.name;
}
}

View file

@ -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 = AbstractFanProcessingType.byBlock(world, currentPos);
if (newType != AbstractFanProcessingType.NONE)
type = newType;
if (currentSegment.type != type || currentSegment.startOffset == 0) {
currentSegment.endOffset = i;
@ -258,7 +257,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 +266,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 +280,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 +303,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 +311,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;
}

View file

@ -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);
}
}

View file

@ -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));
}
}
}

View file

@ -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)

View file

@ -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);

View file

@ -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();
}
}

View file

@ -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));
}
}
}

View file

@ -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();
}
}

View file

@ -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));
}
}
}

View file

@ -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)),