Contraptions revisited

- Fixed Mechanical Piston & Bearing not disassembling when broken
- Mechanical Bearing can now generate rotation with tagged blocks
- Encased Fan can now generate rotation above fire
- Added Splashing recipe type
- Encased Fans with water now extinguish entities
- Drills now hurt entities in front of them depending on their speed
- Fixed some culling issues on rendered constructs
This commit is contained in:
simibubi 2019-09-12 14:32:11 +02:00
parent 4a2335672d
commit ee46359ce4
28 changed files with 605 additions and 181 deletions

View file

@ -0,0 +1,28 @@
package com.simibubi.create;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.Tag;
import net.minecraft.util.ResourceLocation;
public enum AllBlockTags {
WINDMILL_SAILS;
public Tag<Block> tag;
private AllBlockTags() {
this("");
}
private AllBlockTags(String path) {
tag = new BlockTags.Wrapper(
new ResourceLocation(Create.ID, (path.isEmpty() ? "" : path + "/") + name().toLowerCase()));
}
public boolean matches(BlockState block) {
return tag.contains(block.getBlock());
}
}

View file

@ -0,0 +1,23 @@
package com.simibubi.create;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.Tag;
import net.minecraft.util.ResourceLocation;
public enum AllItemTags {
;
public Tag<Item> tag;
private AllItemTags(String path) {
tag = new ItemTags.Wrapper(new ResourceLocation(Create.ID, path + "/" + name().toLowerCase()));
}
public boolean matches(ItemStack item) {
return tag.contains(item.getItem());
}
}

View file

@ -4,6 +4,7 @@ import java.util.function.Supplier;
import com.simibubi.create.modules.contraptions.base.ProcessingRecipeSerializer;
import com.simibubi.create.modules.contraptions.receivers.CrushingRecipe;
import com.simibubi.create.modules.contraptions.receivers.SplashingRecipe;
import com.simibubi.create.modules.curiosities.placementHandgun.BuilderGunUpgradeRecipe;
import net.minecraft.inventory.IInventory;
@ -21,11 +22,16 @@ public enum AllRecipes {
CRUSHING(() -> {
return new ProcessingRecipeSerializer<>(CrushingRecipe::new);
}, Types.CRUSHING),
SPLASHING(() -> {
return new ProcessingRecipeSerializer<>(SplashingRecipe::new);
}, Types.SPLASHING),
;
public static class Types {
public static IRecipeType<CrushingRecipe> CRUSHING = register("crushing");
public static IRecipeType<SplashingRecipe> SPLASHING = register("splashing");
static <T extends IRecipe<?>> IRecipeType<T> register(final String key) {
return Registry.register(Registry.RECIPE_TYPE, new ResourceLocation(key), new IRecipeType<T>() {

View file

@ -51,7 +51,8 @@ public class CreateConfig {
// Contraptions
public IntValue maxBeltLength, crushingDamage, maxMotorSpeed, maxRotationSpeed;
public IntValue fanMaxPushDistance, fanMaxPullDistance, fanBlockCheckRate, fanRotationArgmax, inWorldProcessingTime;
public IntValue fanMaxPushDistance, fanMaxPullDistance, fanBlockCheckRate, fanRotationArgmax, generatingFanSpeed,
inWorldProcessingTime;
public IntValue maxChassisForTranslation, maxChassisForRotation, maxChassisRange, maxPistonPoles;
// Logistics
@ -89,7 +90,7 @@ public class CreateConfig {
name = "enableLogistics";
enableLogistics = builder.translation(basePath + name).define(name, true);
name = "enablePalettes";
enablePalettes = builder.translation(basePath + name).define(name, true);
@ -193,6 +194,10 @@ public class CreateConfig {
name = "fanRotationArgmax";
fanRotationArgmax = builder.comment("", "Rotation speed at which the maximum stats of fans are reached.")
.translation(basePath + name).defineInRange(name, 8192, 64, Integer.MAX_VALUE);
name = "generatingFanSpeed";
generatingFanSpeed = builder.comment("", "Rotation speed generated by a vertical fan above fire.")
.translation(basePath + name).defineInRange(name, 32, 0, Integer.MAX_VALUE);
name = "inWorldProcessingTime";
inWorldProcessingTime = builder

View file

@ -0,0 +1,56 @@
package com.simibubi.create.foundation.utility;
import java.util.HashMap;
import java.util.function.Predicate;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class PlacementSimulationWorld extends WrappedWorld {
public HashMap<BlockPos, BlockState> blocksAdded;
public PlacementSimulationWorld(World wrapped) {
super(wrapped);
blocksAdded = new HashMap<>();
}
public void clear() {
blocksAdded.clear();
}
@Override
public boolean setBlockState(BlockPos pos, BlockState newState, int flags) {
blocksAdded.put(pos, newState);
return true;
}
@Override
public boolean setBlockState(BlockPos pos, BlockState state) {
return setBlockState(pos, state, 0);
}
@Override
public boolean hasBlockState(BlockPos pos, Predicate<BlockState> condition) {
return condition.test(getBlockState(pos));
}
@Override
public boolean isBlockPresent(BlockPos pos) {
return true;
}
@Override
public boolean isAreaLoaded(BlockPos center, int range) {
return true;
}
@Override
public BlockState getBlockState(BlockPos pos) {
if (blocksAdded.containsKey(pos))
return blocksAdded.get(pos);
return Blocks.AIR.getDefaultState();
}
}

View file

@ -0,0 +1,123 @@
package com.simibubi.create.foundation.utility;
import java.util.Collections;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.crafting.RecipeManager;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.tags.NetworkTagManager;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.EmptyTickList;
import net.minecraft.world.ITickList;
import net.minecraft.world.World;
import net.minecraft.world.storage.MapData;
public class WrappedWorld extends World {
protected World world;
public WrappedWorld(World world) {
super(world.getWorldInfo(), world.getDimension().getType(), (w, d) -> world.getChunkProvider(),
world.getProfiler(), world.isRemote);
this.world = world;
}
@Override
public World getWorld() {
return world;
}
@Override
public int getLight(BlockPos pos) {
return 15;
}
@Override
public int getLightSubtracted(BlockPos pos, int amount) {
return 15 - amount;
}
@Override
public ITickList<Block> getPendingBlockTicks() {
return EmptyTickList.get();
}
@Override
public ITickList<Fluid> getPendingFluidTicks() {
return EmptyTickList.get();
}
@Override
public void playEvent(PlayerEntity player, int type, BlockPos pos, int data) {
}
@Override
public List<? extends PlayerEntity> getPlayers() {
return Collections.emptyList();
}
@Override
public void notifyBlockUpdate(BlockPos pos, BlockState oldState, BlockState newState, int flags) {
}
@Override
public void playSound(PlayerEntity player, double x, double y, double z, SoundEvent soundIn, SoundCategory category,
float volume, float pitch) {
}
@Override
public void playMovingSound(PlayerEntity p_217384_1_, Entity p_217384_2_, SoundEvent p_217384_3_,
SoundCategory p_217384_4_, float p_217384_5_, float p_217384_6_) {
}
@Override
public Entity getEntityByID(int id) {
return null;
}
@Override
public MapData getMapData(String mapName) {
return null;
}
@Override
public void registerMapData(MapData mapDataIn) {
}
@Override
public int getNextMapId() {
return 0;
}
@Override
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {
}
@Override
public Scoreboard getScoreboard() {
return world.getScoreboard();
}
@Override
public RecipeManager getRecipeManager() {
return world.getRecipeManager();
}
@Override
public NetworkTagManager getTags() {
return world.getTags();
}
@Override
public int getMaxHeight() {
return 256;
}
}

View file

@ -120,5 +120,19 @@ public abstract class KineticTileEntity extends SyncedTileEntity {
setSpeed(0);
onSpeedChanged();
}
public void applyNewSpeed(float speed) {
detachKinetics();
this.speed = speed;
attachKinetics();
}
public void attachKinetics() {
RotationPropagator.handleAdded(world, pos, this);
}
public void detachKinetics() {
RotationPropagator.handleRemoved(world, pos, this);
}
}

View file

@ -9,6 +9,7 @@ import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import net.minecraft.block.AirBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.ItemStack;
@ -16,6 +17,8 @@ import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
@ -26,6 +29,7 @@ public class DrillTileEntity extends KineticTileEntity implements ITickableTileE
private static final AtomicInteger NEXT_DRILL_ID = new AtomicInteger();
private static DamageSource damageSourceDrill = new DamageSource("create.drill").setDamageBypassesArmor();
private int ticksUntilNextProgress;
private int destroyProgress;
private int drillId = -NEXT_DRILL_ID.incrementAndGet();
@ -74,19 +78,26 @@ public class DrillTileEntity extends KineticTileEntity implements ITickableTileE
if (speed == 0)
return;
if (ticksUntilNextProgress < 0)
BlockPos posToBreak = pos.offset(getBlockState().get(BlockStateProperties.FACING));
if (ticksUntilNextProgress < 0) {
for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, new AxisAlignedBB(posToBreak)))
if (!(entity instanceof ItemEntity))
entity.attackEntityFrom(damageSourceDrill, MathHelper.clamp(Math.abs(speed / 512f) + 1, 0, 20));
return;
}
if (ticksUntilNextProgress-- > 0)
return;
BlockPos posToBreak = pos.offset(getBlockState().get(BlockStateProperties.FACING));
BlockState stateToBreak = world.getBlockState(posToBreak);
float blockHardness = stateToBreak.getBlockHardness(world, posToBreak);
if (stateToBreak.getMaterial().isLiquid() || stateToBreak.getBlock() instanceof AirBlock
|| blockHardness == -1) {
destroyProgress = 0;
world.sendBlockBreakProgress(drillId, posToBreak, -1);
if (destroyProgress != 0) {
destroyProgress = 0;
world.sendBlockBreakProgress(drillId, posToBreak, -1);
}
return;
}

View file

@ -35,8 +35,13 @@ public class EncasedFanBlock extends EncasedShaftBlock implements IWithTileEntit
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
notifyFanTile(worldIn, pos);
if (worldIn.isRemote || state.get(AXIS).isHorizontal())
return;
withTileEntityDo(worldIn, pos, EncasedFanTileEntity::updateGenerator);
}
protected void notifyFanTile(IWorld world, BlockPos pos) {
withTileEntityDo(world, pos, EncasedFanTileEntity::updateFrontBlock);
}

View file

@ -10,6 +10,7 @@ import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.CreateClient;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.logistics.InWorldProcessing;
@ -49,6 +50,7 @@ public class EncasedFanTileEntity extends KineticTileEntity implements ITickable
protected int blockCheckCooldown;
protected boolean findFrontBlock;
protected BlockState frontBlock;
protected boolean isGenerator;
public EncasedFanTileEntity() {
super(AllTileEntities.ENCASED_FAN.type);
@ -57,6 +59,7 @@ public class EncasedFanTileEntity extends KineticTileEntity implements ITickable
frontBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
backBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
particleHandler = CreateClient.fanParticles;
isGenerator = false;
}
@Override
@ -66,26 +69,40 @@ public class EncasedFanTileEntity extends KineticTileEntity implements ITickable
updateBBs();
}
@Override
public CompoundNBT writeToClient(CompoundNBT tag) {
super.writeToClient(tag);
return tag;
}
@Override
public void read(CompoundNBT compound) {
super.read(compound);
isGenerator = compound.getBoolean("Generating");
pushDistance = compound.getFloat("PushDistance");
pullDistance = compound.getFloat("PullDistance");
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.putBoolean("Generating", isGenerator);
compound.putFloat("PushDistance", pushDistance);
compound.putFloat("PullDistance", pullDistance);
return super.write(compound);
}
@Override
public boolean isSource() {
return isGenerator;
}
public void updateGenerator() {
boolean shouldGenerate = world.isBlockPowered(pos) && world.isBlockPresent(pos.down())
&& world.getBlockState(pos.down()).getBlock() == Blocks.FIRE;
if (shouldGenerate == isGenerator)
return;
isGenerator = shouldGenerate;
if (isGenerator)
removeSource();
applyNewSpeed(isGenerator ? CreateConfig.parameters.generatingFanSpeed.get() : 0);
sendData();
}
protected void updateReachAndForce() {
if (getWorld() == null)
return;
@ -163,7 +180,7 @@ public class EncasedFanTileEntity extends KineticTileEntity implements ITickable
@Override
public void tick() {
if (speed == 0)
if (speed == 0 || isGenerator)
return;
List<Entity> frontEntities = world.getEntitiesWithinAABBExcludingEntity(null, frontBB);
@ -196,7 +213,7 @@ public class EncasedFanTileEntity extends KineticTileEntity implements ITickable
public void processEntity(Entity entity) {
if (InWorldProcessing.isFrozen())
return;
if (entity instanceof ItemEntity) {
if (world.rand.nextInt(4) == 0) {
Type processingType = getProcessingType();
@ -205,6 +222,9 @@ public class EncasedFanTileEntity extends KineticTileEntity implements ITickable
1 / 16f, 0);
if (processingType == Type.SMOKING)
world.addParticle(ParticleTypes.CLOUD, entity.posX, entity.posY + .25f, entity.posZ, 0, 1 / 16f, 0);
if (processingType == Type.SPLASHING)
world.addParticle(ParticleTypes.BUBBLE_POP, entity.posX + (world.rand.nextFloat() - .5f) * .5f,
entity.posY + .25f, entity.posZ + (world.rand.nextFloat() - .5f) * .5f, 0, 1 / 16f, 0);
}
if (world.isRemote)
@ -223,7 +243,7 @@ public class EncasedFanTileEntity extends KineticTileEntity implements ITickable
entity.attackEntityFrom(damageSourceLava, 8);
}
if (getProcessingType() == Type.SPLASHING) {
entity.setFire(0);
entity.extinguish();
world.playSound(null, entity.getPosition(), SoundEvents.ENTITY_GENERIC_EXTINGUISH_FIRE,
SoundCategory.NEUTRAL, 0.7F, 1.6F + (world.rand.nextFloat() - world.rand.nextFloat()) * 0.4F);
}

View file

@ -0,0 +1,29 @@
package com.simibubi.create.modules.contraptions.receivers;
import java.util.List;
import com.simibubi.create.AllRecipes;
import com.simibubi.create.modules.contraptions.base.ProcessingRecipe;
import com.simibubi.create.modules.contraptions.base.StochasticOutput;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import com.simibubi.create.modules.logistics.InWorldProcessing.SplashingInv;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
public class SplashingRecipe extends ProcessingRecipe<InWorldProcessing.SplashingInv> {
public SplashingRecipe(ResourceLocation id, String group, List<Ingredient> ingredients,
List<StochasticOutput> results, int processingDuration) {
super(AllRecipes.SPLASHING, id, group, ingredients, results, processingDuration);
}
@Override
public boolean matches(SplashingInv inv, World worldIn) {
if (inv.isEmpty())
return false;
return ingredients.get(0).test(inv.getStackInSlot(0));
}
}

View file

@ -1,9 +1,11 @@
package com.simibubi.create.modules.contraptions.receivers.constructs;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.ItemDescription;
import com.simibubi.create.foundation.utility.ItemDescription.Palette;
import com.simibubi.create.modules.contraptions.base.DirectionalKineticBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.tileentity.TileEntity;
@ -12,7 +14,8 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
public class MechanicalBearingBlock extends DirectionalKineticBlock {
public class MechanicalBearingBlock extends DirectionalKineticBlock
implements IWithTileEntity<MechanicalBearingTileEntity> {
public MechanicalBearingBlock() {
super(Properties.from(Blocks.PISTON));
@ -31,11 +34,20 @@ public class MechanicalBearingBlock extends DirectionalKineticBlock {
return new MechanicalBearingTileEntity();
}
@Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
if (worldIn.isRemote)
return;
withTileEntityDo(worldIn, pos, MechanicalBearingTileEntity::neighbourChanged);
}
@Override
public boolean hasShaftTowards(World world, BlockPos pos, BlockState state, Direction face) {
return face == state.get(FACING).getOpposite();
}
@Override
protected boolean hasStaticPart() {
return true;

View file

@ -1,6 +1,7 @@
package com.simibubi.create.modules.contraptions.receivers.constructs;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.modules.contraptions.RotationPropagator;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import net.minecraft.block.BlockState;
@ -21,9 +22,11 @@ public class MechanicalBearingTileEntity extends KineticTileEntity implements IT
protected float angle;
protected boolean running;
protected boolean assembleNextTick;
protected boolean isWindmill;
public MechanicalBearingTileEntity() {
super(AllTileEntities.MECHANICAL_BEARING.type);
isWindmill = false;
}
@Override
@ -31,9 +34,55 @@ public class MechanicalBearingTileEntity extends KineticTileEntity implements IT
return INFINITE_EXTENT_AABB;
}
@Override
public boolean isSource() {
return isWindmill;
}
public void neighbourChanged() {
boolean shouldWindmill = world.isBlockPowered(pos);
if (shouldWindmill == isWindmill)
return;
isWindmill = shouldWindmill;
if (isWindmill)
removeSource();
if (isWindmill && !running) {
assembleNextTick = true;
}
if (isWindmill && running) {
applyNewSpeed(getWindmillSpeed());
}
if (!isWindmill && running) {
applyNewSpeed(0);
if (speed == 0)
disassembleConstruct();
}
sendData();
}
@Override
public void remove() {
if (!world.isRemote)
disassembleConstruct();
super.remove();
}
public float getWindmillSpeed() {
if (!running)
return 0;
int sails = movingConstruct.getSailBlocks();
return MathHelper.clamp(sails, 0, 128);
}
@Override
public CompoundNBT write(CompoundNBT tag) {
tag.putBoolean("Running", running);
tag.putBoolean("Windmill", isWindmill);
tag.putFloat("Angle", angle);
if (running && !RotationConstruct.isFrozen())
tag.put("Construct", movingConstruct.writeNBT());
@ -44,6 +93,7 @@ public class MechanicalBearingTileEntity extends KineticTileEntity implements IT
@Override
public void read(CompoundNBT tag) {
running = tag.getBoolean("Running");
isWindmill = tag.getBoolean("Windmill");
angle = tag.getFloat("Angle");
if (running && !RotationConstruct.isFrozen())
movingConstruct = RotationConstruct.fromNBT(tag.getCompound("Construct"));
@ -62,7 +112,7 @@ public class MechanicalBearingTileEntity extends KineticTileEntity implements IT
super.onSpeedChanged();
assembleNextTick = true;
}
public float getAngularSpeed() {
return speed / 2048;
}
@ -74,6 +124,8 @@ public class MechanicalBearingTileEntity extends KineticTileEntity implements IT
movingConstruct = RotationConstruct.getAttachedForRotating(getWorld(), getPos(), direction);
if (movingConstruct == null)
return;
if (isWindmill && movingConstruct.getSailBlocks() == 0)
return;
// Run
running = true;
@ -83,6 +135,12 @@ public class MechanicalBearingTileEntity extends KineticTileEntity implements IT
for (BlockInfo info : movingConstruct.blocks.values()) {
getWorld().setBlockState(info.pos.add(pos), Blocks.AIR.getDefaultState(), 67);
}
if (isWindmill) {
RotationPropagator.handleRemoved(world, pos, this);
speed = getWindmillSpeed();
RotationPropagator.handleAdded(world, pos, this);
}
}
public void disassembleConstruct() {
@ -92,7 +150,7 @@ public class MechanicalBearingTileEntity extends KineticTileEntity implements IT
for (BlockInfo block : movingConstruct.blocks.values()) {
BlockPos targetPos = block.pos.add(pos);
BlockState state = block.state;
for (Direction face : Direction.values())
state = state.updatePostPlacement(face, world.getBlockState(targetPos.offset(face)), world, targetPos,
targetPos.offset(face));
@ -115,7 +173,7 @@ public class MechanicalBearingTileEntity extends KineticTileEntity implements IT
public void tick() {
if (running && RotationConstruct.isFrozen())
disassembleConstruct();
if (!world.isRemote && assembleNextTick) {
assembleNextTick = false;
if (running) {

View file

@ -8,6 +8,7 @@ import org.lwjgl.opengl.GL11;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.PlacementSimulationWorld;
import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
@ -30,6 +31,7 @@ import net.minecraftforge.client.model.data.EmptyModelData;
public class MechanicalBearingTileEntityRenderer extends KineticTileEntityRenderer {
protected static Cache<RotationConstruct, RotationConstructVertexBuffer> cachedConstructs;
protected static PlacementSimulationWorld renderWorld;
@Override
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
@ -68,22 +70,28 @@ public class MechanicalBearingTileEntityRenderer extends KineticTileEntityRender
cachedConstructs = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.SECONDS).build();
if (cachedConstructs.getIfPresent(c) != null)
return;
if (renderWorld == null || renderWorld.getWorld() != Minecraft.getInstance().world)
renderWorld = new PlacementSimulationWorld(Minecraft.getInstance().world);
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
Random random = new Random();
BufferBuilder builder = new BufferBuilder(0);
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
builder.setTranslation(0, 255, 0);
builder.setTranslation(0, 0, 0);
for (BlockPos localPos : c.blocks.keySet()) {
BlockInfo info = c.blocks.get(localPos);
for (BlockInfo info : c.blocks.values()) {
renderWorld.setBlockState(info.pos, info.state);
}
for (BlockInfo info : c.blocks.values()) {
IBakedModel originalModel = dispatcher.getModelForState(info.state);
blockRenderer.renderModel(getWorld(), originalModel, info.state, info.pos.down(255), builder, true, random,
42, EmptyModelData.INSTANCE);
blockRenderer.renderModel(renderWorld, originalModel, info.state, info.pos, builder, true, random, 42,
EmptyModelData.INSTANCE);
}
builder.finishDrawing();
renderWorld.clear();
cachedConstructs.put(c, new RotationConstructVertexBuffer(builder.getByteBuffer()));
}

View file

@ -120,6 +120,7 @@ public class MechanicalPistonBlock extends KineticBlock {
Direction direction = state.get(FACING);
BlockPos pistonHead = null;
BlockPos pistonBase = pos;
boolean dropBlocks = player == null || !player.isCreative();
Integer maxPoles = CreateConfig.parameters.maxPistonPoles.get();
for (int offset = 1; offset < maxPoles; offset++) {
@ -139,7 +140,7 @@ public class MechanicalPistonBlock extends KineticBlock {
if (pistonHead != null && pistonBase != null) {
BlockPos.getAllInBox(pistonBase, pistonHead).filter(p -> !p.equals(pos))
.forEach(p -> worldIn.destroyBlock(p, !player.isCreative()));
.forEach(p -> worldIn.destroyBlock(p, dropBlocks));
}
for (int offset = 1; offset < maxPoles; offset++) {
@ -148,7 +149,7 @@ public class MechanicalPistonBlock extends KineticBlock {
if (AllBlocks.PISTON_POLE.typeOf(block)
&& direction.getAxis() == block.get(BlockStateProperties.FACING).getAxis()) {
worldIn.destroyBlock(currentPos, !player.isCreative());
worldIn.destroyBlock(currentPos, dropBlocks);
continue;
}

View file

@ -43,6 +43,14 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
assembleNextTick = true;
}
@Override
public void remove() {
this.removed = true;
if (!world.isRemote)
disassembleConstruct();
super.remove();
}
@Override
public AxisAlignedBB getRenderBoundingBox() {
return INFINITE_EXTENT_AABB;
@ -71,7 +79,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
protected void onBlockVisited(float newOffset) {
if (TranslationConstruct.isFrozen())
return;
Direction direction = getBlockState().get(BlockStateProperties.FACING);
for (BlockInfo block : movingConstruct.actors) {
@ -126,13 +134,14 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
return;
Direction direction = getBlockState().get(BlockStateProperties.FACING);
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED), 3);
if (!removed)
getWorld().setBlockState(pos, getBlockState().with(MechanicalPistonBlock.STATE, PistonState.EXTENDED), 3);
for (BlockInfo block : movingConstruct.blocks.values()) {
BlockPos targetPos = block.pos.offset(direction, getModulatedOffset(offset));
BlockState state = block.state;
if (targetPos.equals(pos)) {
if (!AllBlocks.PISTON_POLE.typeOf(state))
if (!AllBlocks.PISTON_POLE.typeOf(state) && !removed)
getWorld().setBlockState(pos,
getBlockState().with(MechanicalPistonBlock.STATE, PistonState.RETRACTED), 3);
continue;
@ -154,6 +163,9 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
Create.constructHandler.remove(this);
movingConstruct = null;
sendData();
if (removed)
AllBlocks.MECHANICAL_PISTON.get().onBlockHarvested(world, pos, getBlockState(), null);
}
@Override
@ -210,7 +222,7 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ITi
private boolean hasBlockCollisions(float newOffset) {
if (TranslationConstruct.isFrozen())
return true;
Direction movementDirection = getBlockState().get(BlockStateProperties.FACING);
BlockPos relativePos = BlockPos.ZERO.offset(movementDirection, getModulatedOffset(newOffset));

View file

@ -8,6 +8,7 @@ import org.lwjgl.opengl.GL11;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.PlacementSimulationWorld;
import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
@ -27,6 +28,7 @@ import net.minecraftforge.client.model.data.EmptyModelData;
public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRenderer {
protected static Cache<TranslationConstruct, TranslationConstructVertexBuffer> cachedConstructs;
protected static PlacementSimulationWorld renderWorld;
@Override
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks,
@ -49,26 +51,33 @@ public class MechanicalPistonTileEntityRenderer extends KineticTileEntityRendere
cachedConstructs = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.SECONDS).build();
if (cachedConstructs.getIfPresent(c) != null)
return;
if (renderWorld == null || renderWorld.getWorld() != Minecraft.getInstance().world)
renderWorld = new PlacementSimulationWorld(Minecraft.getInstance().world);
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer();
Random random = new Random();
BufferBuilder builder = new BufferBuilder(0);
builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
builder.setTranslation(0, 255, 0);
builder.setTranslation(0, 0, 0);
for (BlockInfo info : c.blocks.values()) {
renderWorld.setBlockState(info.pos, info.state);
}
for (BlockInfo info : c.blocks.values()) {
IBakedModel originalModel = dispatcher.getModelForState(info.state);
blockRenderer.renderModel(getWorld(), originalModel, info.state, info.pos.down(255), builder, true, random,
42, EmptyModelData.INSTANCE);
blockRenderer.renderModel(renderWorld, originalModel, info.state, info.pos, builder, true, random, 42,
EmptyModelData.INSTANCE);
}
builder.finishDrawing();
renderWorld.clear();
cachedConstructs.put(c, new TranslationConstructVertexBuffer(builder.getByteBuffer()));
}
protected void renderConstructFromCache(TranslationConstruct c, MechanicalPistonTileEntity te, double x, double y, double z,
float partialTicks, BufferBuilder buffer) {
protected void renderConstructFromCache(TranslationConstruct c, MechanicalPistonTileEntity te, double x, double y,
double z, float partialTicks, BufferBuilder buffer) {
final Vec3d offset = te.getConstructOffset(partialTicks);
buffer.putBulkData(cachedConstructs.getIfPresent(c).getTransformed(te,
(float) (x + offset.x - te.getPos().getX()), (float) (y + offset.y - te.getPos().getY()),

View file

@ -8,6 +8,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import com.simibubi.create.AllBlockTags;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig;
@ -26,9 +27,11 @@ import net.minecraft.world.gen.feature.template.Template.BlockInfo;
public class RotationConstruct {
protected Map<BlockPos, BlockInfo> blocks;
protected int sailBlocks;
public RotationConstruct() {
blocks = new HashMap<>();
sailBlocks = 0;
}
public static RotationConstruct getAttachedForRotating(World world, BlockPos pos, Direction direction) {
@ -39,11 +42,15 @@ public class RotationConstruct {
return construct;
}
public int getSailBlocks() {
return sailBlocks;
}
protected boolean collectAttached(World world, BlockPos pos, Direction direction) {
if (isFrozen())
return false;
// Find chassis
List<BlockInfo> chassis = collectChassis(world, pos, direction);
if (chassis == null)
@ -69,6 +76,8 @@ public class RotationConstruct {
if (attachedBlocksByChassis == null)
return false;
attachedBlocksByChassis.forEach(info -> {
if (isSailBlock(info.state))
sailBlocks++;
blocks.put(info.pos, new BlockInfo(info.pos.subtract(pos), info.state, info.nbt));
});
}
@ -156,6 +165,10 @@ public class RotationConstruct {
return chassis;
}
private static boolean isSailBlock(BlockState state) {
return AllBlockTags.WINDMILL_SAILS.matches(state);
}
public CompoundNBT writeNBT() {
CompoundNBT nbt = new CompoundNBT();
ListNBT blocks = new ListNBT();
@ -193,5 +206,5 @@ public class RotationConstruct {
public static boolean isFrozen() {
return CreateConfig.parameters.freezeRotationConstructs.get();
}
}

View file

@ -17,6 +17,7 @@ import java.util.function.Function;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalPistonBlock.PistonState;
import net.minecraft.block.BlockState;
import net.minecraft.block.FallingBlock;
@ -116,16 +117,18 @@ public class TranslationConstruct {
int extensionsInFront = 0;
boolean sticky = STICKY_MECHANICAL_PISTON.typeOf(world.getBlockState(pos));
while (PISTON_POLE.typeOf(nextBlock) && nextBlock.get(FACING).getAxis() == direction.getAxis()
|| MECHANICAL_PISTON_HEAD.typeOf(nextBlock) && nextBlock.get(FACING) == direction) {
actualStart = actualStart.offset(direction);
poles.add(new BlockInfo(actualStart, nextBlock.with(FACING, direction), null));
extensionsInFront++;
nextBlock = world.getBlockState(actualStart.offset(direction));
if (extensionsInFront > parameters.maxPistonPoles.get())
return false;
if (world.getBlockState(pos).get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) {
while (PISTON_POLE.typeOf(nextBlock) && nextBlock.get(FACING).getAxis() == direction.getAxis()
|| MECHANICAL_PISTON_HEAD.typeOf(nextBlock) && nextBlock.get(FACING) == direction) {
actualStart = actualStart.offset(direction);
poles.add(new BlockInfo(actualStart, nextBlock.with(FACING, direction), null));
extensionsInFront++;
nextBlock = world.getBlockState(actualStart.offset(direction));
if (extensionsInFront > parameters.maxPistonPoles.get())
return false;
}
}
if (extensionsInFront == 0)

View file

@ -79,16 +79,16 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
PlayerEntity player) {
return new ItemStack(AllItems.BELT_CONNECTOR.item);
}
@Override
public void onLanded(IBlockReader worldIn, Entity entityIn) {
super.onLanded(worldIn, entityIn);
if (entityIn instanceof PlayerEntity && entityIn.isSneaking())
return;
if (entityIn instanceof PlayerEntity && ((PlayerEntity) entityIn).moveVertical > 0)
return;
BeltTileEntity belt = null;
BlockPos entityPosition = entityIn.getPosition();
@ -124,7 +124,7 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
return;
if (entityIn instanceof PlayerEntity && ((PlayerEntity) entityIn).moveVertical > 0)
return;
BeltTileEntity belt = null;
belt = (BeltTileEntity) worldIn.getTileEntity(pos);
@ -152,7 +152,7 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
te.attachmentTracker.findAttachments(te);
});
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(SLOPE, PART);
@ -217,11 +217,20 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
return false;
}
@Override
public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) {
withTileEntityDo(worldIn, pos, te -> {
if (te.hasPulley())
Block.spawnDrops(AllBlocks.SHAFT.get().getDefaultState(), worldIn, pos);
});
super.onBlockHarvested(worldIn, pos, state, player);
}
@Override
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (worldIn.isRemote)
return;
boolean endWasDestroyed = state.get(PART) == Part.END;
TileEntity tileEntity = worldIn.getTileEntity(pos);
if (tileEntity == null)
@ -381,7 +390,7 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
IBooleanFunction.AND));
return shape;
}
@Override
public ItemDescription getDescription() {
return new ItemDescription(color);

View file

@ -1,35 +1,21 @@
package com.simibubi.create.modules.gardens;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.function.Predicate;
import com.simibubi.create.foundation.item.InfoItem;
import com.simibubi.create.foundation.utility.ItemDescription;
import com.simibubi.create.foundation.utility.ItemDescription.Palette;
import com.simibubi.create.foundation.utility.PlacementSimulationWorld;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.SaplingBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.BoneMealItem;
import net.minecraft.item.ItemUseContext;
import net.minecraft.item.crafting.RecipeManager;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.tags.NetworkTagManager;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.EmptyTickList;
import net.minecraft.world.ITickList;
import net.minecraft.world.World;
import net.minecraft.world.storage.MapData;
public class TreeFertilizerItem extends InfoItem {
@ -91,120 +77,19 @@ public class TreeFertilizerItem extends InfoItem {
return super.onItemUse(context);
}
private class TreesDreamWorld extends World {
World wrapped;
HashMap<BlockPos, BlockState> blocksAdded;
private class TreesDreamWorld extends PlacementSimulationWorld {
protected TreesDreamWorld(World wrapped) {
super(wrapped.getWorldInfo(), wrapped.dimension.getType(), (w, d) -> wrapped.getChunkProvider(),
wrapped.getProfiler(), false);
this.wrapped = wrapped;
blocksAdded = new HashMap<>();
}
@Override
public int getMaxHeight() {
return 256;
}
@Override
public boolean setBlockState(BlockPos pos, BlockState newState, int flags) {
blocksAdded.put(pos, newState);
return true;
}
@Override
public boolean setBlockState(BlockPos pos, BlockState state) {
return setBlockState(pos, state, 0);
}
@Override
public boolean hasBlockState(BlockPos p_217375_1_, Predicate<BlockState> p_217375_2_) {
return p_217375_2_.test(getBlockState(p_217375_1_));
super(wrapped);
}
@Override
public BlockState getBlockState(BlockPos pos) {
if (blocksAdded.containsKey(pos))
return blocksAdded.get(pos);
if (pos.getY() <= 9)
return Blocks.GRASS_BLOCK.getDefaultState();
return Blocks.AIR.getDefaultState();
}
@Override
public ITickList<Block> getPendingBlockTicks() {
return EmptyTickList.get();
}
@Override
public ITickList<Fluid> getPendingFluidTicks() {
return EmptyTickList.get();
}
@Override
public void playEvent(PlayerEntity player, int type, BlockPos pos, int data) {
}
@Override
public List<? extends PlayerEntity> getPlayers() {
return Collections.emptyList();
}
@Override
public void notifyBlockUpdate(BlockPos pos, BlockState oldState, BlockState newState, int flags) {
}
@Override
public void playSound(PlayerEntity player, double x, double y, double z, SoundEvent soundIn,
SoundCategory category, float volume, float pitch) {
}
@Override
public void playMovingSound(PlayerEntity p_217384_1_, Entity p_217384_2_, SoundEvent p_217384_3_,
SoundCategory p_217384_4_, float p_217384_5_, float p_217384_6_) {
}
@Override
public Entity getEntityByID(int id) {
return null;
}
@Override
public MapData getMapData(String mapName) {
return wrapped.getMapData(mapName);
}
@Override
public void registerMapData(MapData mapDataIn) {
wrapped.registerMapData(mapDataIn);
return super.getBlockState(pos);
}
@Override
public int getNextMapId() {
return 0;
}
@Override
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {
}
@Override
public Scoreboard getScoreboard() {
return null;
}
@Override
public RecipeManager getRecipeManager() {
return null;
}
@Override
public NetworkTagManager getTags() {
return null;
}
}
}

View file

@ -3,8 +3,10 @@ package com.simibubi.create.modules.logistics;
import java.util.List;
import java.util.Optional;
import com.simibubi.create.AllRecipes;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.ItemHelper;
import com.simibubi.create.modules.contraptions.receivers.SplashingRecipe;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
@ -19,9 +21,19 @@ import net.minecraft.tileentity.BlastFurnaceTileEntity;
import net.minecraft.tileentity.FurnaceTileEntity;
import net.minecraft.tileentity.SmokerTileEntity;
import net.minecraft.world.World;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.RecipeWrapper;
public class InWorldProcessing {
public static class SplashingInv extends RecipeWrapper {
public SplashingInv() {
super(new ItemStackHandler(1));
}
}
public static SplashingInv splashingInv = new SplashingInv();
public enum Type {
SMOKING, BLASTING, SPLASHING
}
@ -46,7 +58,10 @@ public class InWorldProcessing {
}
if (type == Type.SPLASHING) {
return false;
splashingInv.setInventorySlotContents(0, entity.getItem());
Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING,
splashingInv, world);
return recipe.isPresent();
}
return false;
@ -58,6 +73,11 @@ public class InWorldProcessing {
return;
if (type == Type.SPLASHING) {
splashingInv.setInventorySlotContents(0, entity.getItem());
Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING,
splashingInv, world);
if (recipe.isPresent())
applyRecipeOn(entity, recipe.get());
return;
}
@ -132,7 +152,7 @@ public class InWorldProcessing {
for (ItemStack additional : stacks)
entity.world.addEntity(new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional));
}
public static boolean isFrozen() {
return CreateConfig.parameters.freezeInWorldProcessing.get();
}

View file

@ -127,9 +127,10 @@
"block.create.shop_shelf": "Shelf",
"death.attack.create.crush": "%1$s was crushed by a dangerous contraption",
"death.attack.create.fan_fire": "%1$s was burnt to death by hot air",
"death.attack.create.fan_lava": "%1$s tried to swim up a lava fountain",
"death.attack.create.crush": "%1$s was processed by Crushing Wheels",
"death.attack.create.fan_fire": "%1$s was burned to death by hot air",
"death.attack.create.fan_lava": "%1$s was burned to death by lava fan",
"death.attack.create.drill": "%1$s was impaled by Mechanical Drill",
"itemGroup.create": "Create"
}

View file

@ -0,0 +1,19 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "create:piston_pole"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}

View file

@ -0,0 +1,16 @@
{
"type": "create:splashing",
"group": "minecraft:misc",
"ingredients": [
{
"tag": "forge:stained_glass"
}
],
"results": [
{
"item": "minecraft:glass",
"count": 1
}
],
"processingTime": 100
}

View file

@ -0,0 +1,16 @@
{
"type": "create:splashing",
"group": "minecraft:misc",
"ingredients": [
{
"tag": "forge:stained_glass_panes"
}
],
"results": [
{
"item": "minecraft:glass_pane",
"count": 1
}
],
"processingTime": 100
}

View file

@ -0,0 +1,16 @@
{
"type": "create:splashing",
"group": "minecraft:misc",
"ingredients": [
{
"tag": "minecraft:wool"
}
],
"results": [
{
"item": "minecraft:white_wool",
"count": 1
}
],
"processingTime": 100
}

View file

@ -0,0 +1,6 @@
{
"replace": false,
"values": [
"#minecraft:wool"
]
}