Cutting Edge

- Fixed Entity Types not registering correctly
- Fixed WorldRenderer being loaded server side
- Fixed the Tree Cutter search used by the Deforester
- Fixed Crushing wheel controller not dropping contents when removed
- Mechanical Saw can now process Cutting and Stonecutting Recipes
This commit is contained in:
simibubi 2019-11-10 15:53:44 +01:00
parent 6f185d4540
commit c2814f8ad2
25 changed files with 625 additions and 66 deletions

View file

@ -20,7 +20,7 @@ archivesBaseName = 'create'
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8'
minecraft {
mappings channel: 'snapshot', version: '20191021-1.14.3'
mappings channel: 'snapshot', version: '20191107-1.14.3'
runs {
client {
@ -71,7 +71,7 @@ repositories {
}
dependencies {
minecraft 'net.minecraftforge:forge:1.14.4-28.1.61'
minecraft 'net.minecraftforge:forge:1.14.4-28.1.85'
// compile against the JEI API but do not include it at runtime
compileOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.10:api")

View file

@ -56,6 +56,9 @@ public class Create {
modEventBus.addGenericListener(IRecipeSerializer.class, Create::registerRecipes);
modEventBus.addGenericListener(TileEntityType.class, Create::registerTileEntities);
modEventBus.addGenericListener(ContainerType.class, Create::registerContainers);
modEventBus.addGenericListener(VillagerProfession.class, Create::registerVillagerProfessions);
modEventBus.addGenericListener(PointOfInterestType.class, Create::registerPointsOfInterest);
modEventBus.addGenericListener(EntityType.class, Create::registerEntities);
modEventBus.addListener(Create::createConfigs);
CreateClient.addListeners(modEventBus);
@ -95,12 +98,10 @@ public class Create {
AllRecipes.register(event);
}
@SubscribeEvent
public static void registerEntities(final RegistryEvent.Register<EntityType<?>> event) {
AllEntities.register(event);
}
@SubscribeEvent
public static void registerVillagerProfessions(RegistryEvent.Register<VillagerProfession> event) {
LogisticianHandler.registerVillagerProfessions(event);
}
@ -110,7 +111,6 @@ public class Create {
LogisticianHandler.registerPointsOfInterest(event);
}
@SubscribeEvent
public static void createConfigs(ModConfig.ModConfigEvent event) {
if (event.getConfig().getSpec() == CreateConfig.specification)
config = event.getConfig();

View file

@ -66,8 +66,8 @@ public class TreeCutter {
visited.add(currentPos);
BlockState blockState = reader.getBlockState(currentPos);
boolean isLog = !isLog(blockState);
boolean isLeaf = !isLeaf(blockState);
boolean isLog = isLog(blockState);
boolean isLeaf = isLeaf(blockState);
if (!isLog && !isLeaf)
continue;
@ -108,7 +108,7 @@ public class TreeCutter {
if (!isLog(reader.getBlockState(currentPos)))
continue;
if (isLog(reader.getBlockState(currentPos.down())))
if (!pos.equals(currentPos.down()) && isLog(reader.getBlockState(currentPos.down())))
return false;
for (Direction direction : Direction.values()) {
@ -127,7 +127,7 @@ public class TreeCutter {
private static void addNeighbours(BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited) {
BlockPos.getAllInBox(pos.add(-1, -1, -1), pos.add(1, 1, 1)).filter(Predicates.not(visited::contains))
.forEach(frontier::add);
.forEach(p -> frontier.add(new BlockPos(p)));
}
private static boolean isLog(BlockState state) {

View file

@ -37,7 +37,7 @@ public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTil
protected static Map<BlockState, BufferManipulator> cachedBuffers;
public static boolean rainbowMode = false;
protected static class BlockModelSpinner extends BufferManipulator {
public static class BlockModelSpinner extends BufferManipulator {
public BlockModelSpinner(ByteBuffer original) {
super(original);
@ -78,14 +78,19 @@ public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTil
final BlockPos pos = te.getPos();
Axis axis = ((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState());
float time = AnimationTickHolder.getRenderTick();
float offset = getRotationOffsetForPosition(te, pos, axis);
float angle = (float) (((time * te.getSpeed() + offset) % 360) / 180 * (float) Math.PI);
float angle = getAngleForTe(te, pos, axis);
renderFromCache(buffer, state, getWorld(), (float) x, (float) y, (float) z, pos, axis, angle);
}
protected static void renderFromCache(BufferBuilder buffer, BlockState state, World world, float x, float y,
public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) {
float time = AnimationTickHolder.getRenderTick();
float offset = getRotationOffsetForPosition(te, pos, axis);
float angle = (float) (((time * te.getSpeed() + offset) % 360) / 180 * (float) Math.PI);
return angle;
}
public static void renderFromCache(BufferBuilder buffer, BlockState state, World world, float x, float y,
float z, BlockPos pos, Axis axis, float angle) {
int packedLightmapCoords = state.getPackedLightmapCoords(world, pos);
ByteBuffer transformed = ((BlockModelSpinner) getBuffer(state)).getTransformed(x, y, z, angle, axis,
@ -126,7 +131,7 @@ public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTil
}
}
protected float getRotationOffsetForPosition(KineticTileEntity te, final BlockPos pos, final Axis axis) {
protected static float getRotationOffsetForPosition(KineticTileEntity te, final BlockPos pos, final Axis axis) {
float offset = AllBlocks.LARGE_COGWHEEL.typeOf(te.getBlockState()) ? 11.25f : 0;
double d = (((axis == Axis.X) ? 0 : pos.getX()) + ((axis == Axis.Y) ? 0 : pos.getY())
+ ((axis == Axis.Z) ? 0 : pos.getZ())) % 2;

View file

@ -10,6 +10,7 @@ import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.inventory.InventoryHelper;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.state.BooleanProperty;
@ -39,7 +40,7 @@ public class CrushingWheelControllerBlock extends Block implements IWithoutBlock
public boolean hasTileEntity(BlockState state) {
return true;
}
@Override
public boolean isReplaceable(BlockState state, BlockItemUseContext useContext) {
return false;
@ -150,4 +151,21 @@ public class CrushingWheelControllerBlock extends Block implements IWithoutBlock
return VoxelShapes.fullCube();
}
@Override
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (worldIn.getTileEntity(pos) == null)
return;
CrushingWheelControllerTileEntity te = (CrushingWheelControllerTileEntity) worldIn.getTileEntity(pos);
for (int slot = 0; slot < te.inventory.getSizeInventory(); slot++) {
InventoryHelper.spawnItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(),
te.inventory.getStackInSlot(slot));
}
if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) {
worldIn.removeTileEntity(pos);
}
}
}

View file

@ -34,12 +34,12 @@ public class CrushingWheelControllerTileEntity extends SyncedTileEntity implemen
private UUID entityUUID;
protected boolean searchForEntity;
private ProcessingInventory contents;
public ProcessingInventory inventory;
public float crushingspeed;
public CrushingWheelControllerTileEntity() {
super(AllTileEntities.CRUSHING_WHEEL_CONTROLLER.type);
contents = new ProcessingInventory();
inventory = new ProcessingInventory();
}
@Override
@ -65,31 +65,31 @@ public class CrushingWheelControllerTileEntity extends SyncedTileEntity implemen
if (!hasEntity()) {
float processingSpeed = speed / (!contents.appliedRecipe ? contents.getStackInSlot(0).getCount() : 1);
contents.processingDuration -= processingSpeed;
spawnParticles(contents.getStackInSlot(0));
float processingSpeed = speed / (!inventory.appliedRecipe ? inventory.getStackInSlot(0).getCount() : 1);
inventory.remainingTime -= processingSpeed;
spawnParticles(inventory.getStackInSlot(0));
if (world.isRemote)
return;
if (contents.processingDuration < 20 && !contents.appliedRecipe) {
if (inventory.remainingTime < 20 && !inventory.appliedRecipe) {
applyRecipe();
contents.appliedRecipe = true;
inventory.appliedRecipe = true;
world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16);
return;
}
Vec3d outPos = new Vec3d(pos).add(.5, -.5, .5);
if (contents.processingDuration <= 0) {
for (int slot = 0; slot < contents.getSizeInventory(); slot++) {
ItemStack stack = contents.getStackInSlot(slot);
if (inventory.remainingTime <= 0) {
for (int slot = 0; slot < inventory.getSizeInventory(); slot++) {
ItemStack stack = inventory.getStackInSlot(slot);
if (stack.isEmpty())
continue;
ItemEntity entityIn = new ItemEntity(world, outPos.x, outPos.y, outPos.z, stack);
entityIn.setMotion(Vec3d.ZERO);
world.addEntity(entityIn);
}
contents.clear();
inventory.clear();
world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16);
return;
}
@ -140,12 +140,12 @@ public class CrushingWheelControllerTileEntity extends SyncedTileEntity implemen
}
private void applyRecipe() {
Optional<CrushingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.CRUSHING, contents,
Optional<CrushingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.CRUSHING, inventory,
world);
if (recipe.isPresent()) {
int rolls = contents.getStackInSlot(0).getCount();
contents.clear();
int rolls = inventory.getStackInSlot(0).getCount();
inventory.clear();
for (int roll = 0; roll < rolls; roll++) {
List<ItemStack> rolledResults = recipe.get().rollResults();
@ -153,8 +153,8 @@ public class CrushingWheelControllerTileEntity extends SyncedTileEntity implemen
for (int i = 0; i < rolledResults.size(); i++) {
ItemStack stack = rolledResults.get(i);
for (int slot = 0; slot < contents.getSizeInventory(); slot++) {
stack = contents.getItems().insertItem(slot, stack, false);
for (int slot = 0; slot < inventory.getSizeInventory(); slot++) {
stack = inventory.getItems().insertItem(slot, stack, false);
if (stack.isEmpty())
break;
@ -163,7 +163,7 @@ public class CrushingWheelControllerTileEntity extends SyncedTileEntity implemen
}
} else {
contents.clear();
inventory.clear();
}
}
@ -172,7 +172,7 @@ public class CrushingWheelControllerTileEntity extends SyncedTileEntity implemen
public CompoundNBT write(CompoundNBT compound) {
if (hasEntity() && !isFrozen())
compound.put("Entity", NBTUtil.writeUniqueId(entityUUID));
contents.write(compound);
inventory.write(compound);
compound.putFloat("Speed", crushingspeed);
return super.write(compound);
@ -187,7 +187,7 @@ public class CrushingWheelControllerTileEntity extends SyncedTileEntity implemen
this.searchForEntity = true;
}
crushingspeed = compound.getFloat("Speed");
contents = ProcessingInventory.read(compound);
inventory = ProcessingInventory.read(compound);
}
@ -197,13 +197,13 @@ public class CrushingWheelControllerTileEntity extends SyncedTileEntity implemen
}
private void insertItem(ItemEntity entity) {
contents.clear();
contents.setInventorySlotContents(0, entity.getItem());
Optional<CrushingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.CRUSHING, contents,
inventory.clear();
inventory.setInventorySlotContents(0, entity.getItem());
Optional<CrushingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.CRUSHING, inventory,
world);
contents.processingDuration = recipe.isPresent() ? recipe.get().getProcessingDuration() : 100;
contents.appliedRecipe = false;
inventory.remainingTime = recipe.isPresent() ? recipe.get().getProcessingDuration() : 100;
inventory.appliedRecipe = false;
}
public void clear() {
@ -212,7 +212,7 @@ public class CrushingWheelControllerTileEntity extends SyncedTileEntity implemen
}
public boolean isOccupied() {
return hasEntity() || !contents.isEmpty();
return hasEntity() || !inventory.isEmpty();
}
public boolean hasEntity() {

View file

@ -8,7 +8,8 @@ import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.RecipeWrapper;
public class ProcessingInventory extends RecipeWrapper {
protected int processingDuration;
protected int remainingTime;
protected int recipeDuration;
protected boolean appliedRecipe;
public ProcessingInventory() {
@ -18,7 +19,8 @@ public class ProcessingInventory extends RecipeWrapper {
@Override
public void clear() {
super.clear();
processingDuration = 0;
remainingTime = 0;
recipeDuration = 0;
appliedRecipe = false;
}
@ -29,7 +31,8 @@ public class ProcessingInventory extends RecipeWrapper {
stacks.add(stack);
}
ItemStackHelper.saveAllItems(nbt, stacks);
nbt.putInt("ProcessingTime", processingDuration);
nbt.putInt("ProcessingTime", remainingTime);
nbt.putInt("RecipeTime", recipeDuration);
nbt.putBoolean("AppliedRecipe", appliedRecipe);
}
@ -40,7 +43,8 @@ public class ProcessingInventory extends RecipeWrapper {
for (int slot = 0; slot < stacks.size(); slot++)
inventory.setInventorySlotContents(slot, stacks.get(slot));
inventory.processingDuration = nbt.getInt("ProcessingTime");
inventory.remainingTime = nbt.getInt("ProcessingTime");
inventory.recipeDuration = nbt.getInt("RecipeTime");
inventory.appliedRecipe = nbt.getBoolean("AppliedRecipe");
return inventory;

View file

@ -4,6 +4,7 @@ import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.VoxelShapers;
import com.simibubi.create.modules.contraptions.base.DirectionalAxisKineticBlock;
import com.simibubi.create.modules.contraptions.receivers.constructs.IHaveMovementBehavior;
import com.simibubi.create.modules.logistics.block.IBlockWithFilter;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -11,6 +12,8 @@ import net.minecraft.block.Blocks;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.InventoryHelper;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
@ -18,17 +21,20 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
public class SawBlock extends DirectionalAxisKineticBlock
implements IWithTileEntity<SawTileEntity>, IHaveMovementBehavior {
implements IWithTileEntity<SawTileEntity>, IHaveMovementBehavior, IBlockWithFilter {
public static final BooleanProperty RUNNING = BooleanProperty.create("running");
public static DamageSource damageSourceSaw = new DamageSource("create.saw").setDamageBypassesArmor();
@ -38,6 +44,12 @@ public class SawBlock extends DirectionalAxisKineticBlock
setDefaultState(getDefaultState().with(RUNNING, false));
}
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
return handleActivatedFilterSlots(state, worldIn, pos, player, handIn, hit);
}
@Override
public BlockRenderLayer getRenderLayer() {
return BlockRenderLayer.CUTOUT_MIPPED;
@ -92,7 +104,7 @@ public class SawBlock extends DirectionalAxisKineticBlock
if (!(entityIn instanceof ItemEntity))
return;
withTileEntityDo(entityIn.world, entityIn.getPosition(), te -> {
te.insertItem((ItemEntity) entityIn);
});
}
@ -116,4 +128,44 @@ public class SawBlock extends DirectionalAxisKineticBlock
: super.hasShaftTowards(world, pos, state, face);
}
@Override
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (worldIn.getTileEntity(pos) == null)
return;
if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) {
withTileEntityDo(worldIn, pos, te -> {
for (int slot = 0; slot < te.inventory.getSizeInventory(); slot++) {
InventoryHelper.spawnItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(),
te.inventory.getStackInSlot(slot));
}
});
worldIn.removeTileEntity(pos);
}
}
@Override
public Vec3d getFilterPosition(BlockState state) {
Vec3d x = new Vec3d(8f / 16f, 12.5f / 16f + 1f/256f, 12.25f / 16f);
Vec3d z = new Vec3d(12.25f / 16f, 12.5f / 16f + 1f/256f, 8f / 16f);
return state.get(AXIS_ALONG_FIRST_COORDINATE) ? z : x;
}
@Override
public float getFilterAngle(BlockState state) {
return 0;
}
@Override
public boolean isFilterVisible(BlockState state) {
return state.get(FACING) == Direction.UP;
}
@Override
public Direction getFilterFacing(BlockState state) {
return state.get(AXIS_ALONG_FIRST_COORDINATE) ? Direction.EAST : Direction.SOUTH;
}
}

View file

@ -2,21 +2,49 @@ package com.simibubi.create.modules.contraptions.receivers;
import static com.simibubi.create.modules.contraptions.receivers.SawBlock.RUNNING;
import java.util.Optional;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.logistics.block.IHaveFilter;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.item.crafting.StonecuttingRecipe;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.BlockParticleData;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.util.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
public class SawTileEntity extends KineticTileEntity {
public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
public ProcessingInventory inventory;
private int recipeIndex;
private ItemStack filter;
public SawTileEntity() {
super(AllTileEntities.SAW.type);
inventory = new ProcessingInventory();
inventory.remainingTime = -1;
filter = ItemStack.EMPTY;
recipeIndex = 0;
}
@Override
public boolean hasFastRenderer() {
return false;
}
@Override
@ -24,26 +52,198 @@ public class SawTileEntity extends KineticTileEntity {
boolean shouldRun = Math.abs(getSpeed()) > 1 / 64f;
boolean running = getBlockState().get(RUNNING);
if (shouldRun != running)
world.setBlockState(pos, getBlockState().with(RUNNING, shouldRun));
world.setBlockState(pos, getBlockState().with(RUNNING, shouldRun), 2 | 16);
}
@Override
public CompoundNBT write(CompoundNBT compound) {
inventory.write(compound);
compound.put("Filter", filter.write(new CompoundNBT()));
compound.putInt("RecipeIndex", recipeIndex);
return super.write(compound);
}
@Override
public void read(CompoundNBT compound) {
super.read(compound);
inventory = ProcessingInventory.read(compound);
recipeIndex = compound.getInt("RecipeIndex");
filter = ItemStack.read(compound.getCompound("Filter"));
}
@Override
public void tick() {
super.tick();
if (!canProcess())
return;
if (getSpeed() == 0)
return;
if (inventory.remainingTime == -1)
return;
float processingSpeed = MathHelper.clamp(Math.abs(getSpeed()) / 32, 1, 128);
inventory.remainingTime -= processingSpeed;
spawnParticles(inventory.getStackInSlot(0));
if (world.isRemote)
return;
if (inventory.remainingTime < 20 && !inventory.appliedRecipe) {
applyRecipe();
inventory.appliedRecipe = true;
sendData();
return;
}
Vec3d outPos = VecHelper.getCenterOf(pos).add(getItemMovementVec().scale(.5f).add(0, .5, 0));
Vec3d outMotion = getItemMovementVec().scale(.0625).add(0, .125, 0);
if (inventory.remainingTime <= 0) {
for (int slot = 0; slot < inventory.getSizeInventory(); slot++) {
ItemStack stack = inventory.getStackInSlot(slot);
if (stack.isEmpty())
continue;
ItemEntity entityIn = new ItemEntity(world, outPos.x, outPos.y, outPos.z, stack);
entityIn.setMotion(outMotion);
world.addEntity(entityIn);
}
inventory.clear();
inventory.remainingTime = -1;
sendData();
return;
}
return;
}
protected void spawnParticles(ItemStack stack) {
if (stack == null || stack.isEmpty())
return;
IParticleData particleData = null;
float speed = 1;
if (stack.getItem() instanceof BlockItem)
particleData = new BlockParticleData(ParticleTypes.BLOCK,
((BlockItem) stack.getItem()).getBlock().getDefaultState());
else {
particleData = new ItemParticleData(ParticleTypes.ITEM, stack);
speed = .125f;
}
Random r = world.rand;
Vec3d vec = getItemMovementVec();
Vec3d pos = VecHelper.getCenterOf(this.pos);
float offset = inventory.recipeDuration != 0 ? (float) (inventory.remainingTime) / inventory.recipeDuration : 0;
offset -= .5f;
world.addParticle(particleData, pos.getX() + -vec.x * offset, pos.getY() + .45f, pos.getZ() + -vec.z * offset,
vec.x * speed, r.nextFloat() * speed, vec.z * speed);
}
public Vec3d getItemMovementVec() {
boolean alongX = !getBlockState().get(SawBlock.AXIS_ALONG_FIRST_COORDINATE);
int offset = getSpeed() < 0 ? -1 : 1;
return new Vec3d(offset * (alongX ? 1 : 0), 0, offset * (alongX ? 0 : -1));
}
private void applyRecipe() {
List<IRecipe<?>> recipes = getRecipes();
if (recipes.isEmpty())
return;
if (recipeIndex >= recipes.size())
recipeIndex = 0;
IRecipe<?> recipe = recipes.get(recipeIndex);
int rolls = inventory.getStackInSlot(0).getCount();
inventory.clear();
for (int roll = 0; roll < rolls; roll++) {
List<ItemStack> results = new LinkedList<ItemStack>();
if (recipe instanceof CuttingRecipe)
results = ((CuttingRecipe) recipe).rollResults();
else if (recipe instanceof StonecuttingRecipe)
results.add(recipe.getRecipeOutput().copy());
for (int i = 0; i < results.size(); i++) {
ItemStack stack = results.get(i);
for (int slot = 0; slot < inventory.getSizeInventory(); slot++) {
stack = inventory.getItems().insertItem(slot, stack, false);
if (stack.isEmpty())
break;
}
}
}
}
private List<IRecipe<?>> getRecipes() {
List<IRecipe<?>> recipes = world.getRecipeManager().getRecipes().parallelStream()
.filter(r -> r.getType() == IRecipeType.STONECUTTING || r.getType() == AllRecipes.Types.CUTTING)
.filter(r -> filter.isEmpty() || ItemStack.areItemsEqual(filter, r.getRecipeOutput()))
.filter(r -> !r.getIngredients().isEmpty()
&& r.getIngredients().get(0).test(inventory.getStackInSlot(0)))
.collect(Collectors.toList());
return recipes;
}
public void insertItem(ItemEntity entity) {
if (!canProcess())
return;
if (!inventory.isEmpty())
return;
if (world.isRemote)
return;
inventory.clear();
inventory.setInventorySlotContents(0, entity.getItem().copy());
Optional<CuttingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.CUTTING, inventory, world);
inventory.processingDuration = recipe.isPresent() ? recipe.get().getProcessingDuration() : 100;
List<IRecipe<?>> recipes = getRecipes();
boolean valid = !recipes.isEmpty();
int time = 100;
if (recipes.isEmpty()) {
inventory.remainingTime = inventory.recipeDuration = 10;
inventory.appliedRecipe = false;
entity.remove();
sendData();
return;
}
if (valid) {
recipeIndex++;
if (recipeIndex >= recipes.size())
recipeIndex = 0;
}
IRecipe<?> recipe = recipes.get(recipeIndex);
if (recipe instanceof CuttingRecipe) {
time = ((CuttingRecipe) recipe).getProcessingDuration();
}
inventory.remainingTime = time * Math.max(1, (entity.getItem().getCount() / 5));
inventory.recipeDuration = inventory.remainingTime;
inventory.appliedRecipe = false;
entity.remove();
sendData();
}
protected boolean canProcess() {
return getBlockState().get(SawBlock.FACING) == Direction.UP;
}
@Override
public void setFilter(ItemStack stack) {
filter = stack.copy();
markDirty();
sendData();
}
@Override
public ItemStack getFilter() {
return filter;
}
}

View file

@ -3,16 +3,87 @@ package com.simibubi.create.modules.contraptions.receivers;
import static net.minecraft.state.properties.BlockStateProperties.AXIS;
import static net.minecraft.state.properties.BlockStateProperties.FACING;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer.BlockModelSpinner;
import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ItemCameraTransforms;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
public class SawTileEntityRenderer extends KineticTileEntityRenderer {
@SuppressWarnings("deprecation")
public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> {
FilteredTileEntityRenderer filterRenderer;
public SawTileEntityRenderer() {
filterRenderer = new FilteredTileEntityRenderer();
}
@Override
public void render(SawTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) {
super.render(te, x, y, z, partialTicks, destroyStage);
boolean processingMode = te.getBlockState().get(SawBlock.FACING) == Direction.UP;
if (processingMode && !te.inventory.isEmpty()) {
boolean alongZ = !te.getBlockState().get(SawBlock.AXIS_ALONG_FIRST_COORDINATE);
GlStateManager.pushMatrix();
float offset = te.inventory.recipeDuration != 0
? (float) (te.inventory.remainingTime) / te.inventory.recipeDuration
: 0;
if (te.getSpeed() == 0)
offset = .5f;
if (te.getSpeed() < 0 ^ alongZ)
offset = 1 - offset;
ItemStack stack = te.inventory.getStackInSlot(0);
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
IBakedModel modelWithOverrides = itemRenderer.getModelWithOverrides(stack);
boolean blockItem = modelWithOverrides.isGui3d();
GlStateManager.translated(x + (alongZ ? offset : .5), y + (blockItem ? .925f : 13f / 16f),
z + (alongZ ? .5 : offset));
GlStateManager.scaled(.5, .5, .5);
if (alongZ)
GlStateManager.rotated(90, 0, 1, 0);
GlStateManager.rotated(90, 1, 0, 0);
itemRenderer.renderItem(stack, ItemCameraTransforms.TransformType.FIXED);
GlStateManager.popMatrix();
}
// Filter
filterRenderer.render(te, x, y, z, partialTicks, destroyStage);
// Kinetic renders
final BlockState state = getRenderedBlockState(te);
KineticTileEntityRenderer.cacheIfMissing(state, getWorld(), BlockModelSpinner::new);
final BlockPos pos = te.getPos();
Axis axis = ((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState());
float angle = KineticTileEntityRenderer.getAngleForTe(te, pos, axis);
TessellatorHelper.prepareFastRender();
TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
KineticTileEntityRenderer.renderFromCache(Tessellator.getInstance().getBuffer(), state, getWorld(), (float) x,
(float) y, (float) z, pos, axis, angle);
TessellatorHelper.draw();
}
protected BlockState getRenderedBlockState(KineticTileEntity te) {
BlockState state = te.getBlockState();
if (state.get(FACING).getAxis().isHorizontal()) {

View file

@ -26,8 +26,6 @@ import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
@ -166,8 +164,9 @@ public class MovingConstructHandler {
return movingPistons.get(mechanicalPistonTileEntity.getWorld());
}
@SubscribeEvent
public static void onRenderWorld(RenderWorldLastEvent event) {
// @SubscribeEvent
// @OnlyIn(value = Dist.CLIENT)
// public static void onRenderWorld(RenderWorldLastEvent event) {
// for (AxisAlignedBB bb : renderedBBs) {
// TessellatorHelper.prepareForDrawing();
// GlStateManager.disableTexture();
@ -179,6 +178,6 @@ public class MovingConstructHandler {
// GlStateManager.enableTexture();
// TessellatorHelper.cleanUpAfterDrawing();
// }
}
// }
}

View file

@ -22,6 +22,10 @@ public class FilteredTileEntityRenderer {
float partialTicks, int destroyStage) {
BlockState state = tileEntityIn.getBlockState();
IBlockWithFilter block = (IBlockWithFilter) state.getBlock();
if (!block.isFilterVisible(state))
return;
Direction facing = block.getFilterFacing(state);
float scale = block.getItemHitboxScale();
@ -31,13 +35,13 @@ public class FilteredTileEntityRenderer {
BlockPos pos = tileEntityIn.getPos();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
renderFilterItem(tileEntityIn.getFilter(), position, facing, scale - 2 / 16f);
renderFilterItem(tileEntityIn.getFilter(), position, facing, scale - 2 / 16f, block.getFilterAngle(state));
TessellatorHelper.cleanUpAfterDrawing();
}
private void renderFilterItem(ItemStack stack, Vec3d position, Direction facing, float scaleDiff) {
private void renderFilterItem(ItemStack stack, Vec3d position, Direction facing, float scaleDiff, float angle) {
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
boolean vertical = facing.getAxis().isVertical();
@ -46,11 +50,11 @@ public class FilteredTileEntityRenderer {
float offX = 0;
float offY = 0;
float offZ = !blockItem ? 1 / 4f + 2 * scaleDiff - 1/16f : 1/16f;
float offZ = !blockItem ? 1 / 4f + 2 * scaleDiff - 1 / 16f : 1 / 16f;
if (vertical)
offZ = -offZ;
float rotX = vertical ? 90 : 0 - (blockItem ? -67.5f : 67.5f);
float rotX = vertical ? 90 : 0 - (blockItem ? -90f + angle : 90 - angle);
float rotY = vertical ? 0 : facing.getHorizontalAngle() + (blockItem ? 180 : 0);
float rotZ = vertical && facing == Direction.DOWN ? 180 : 0;
if (facing.getAxis() == Axis.X) {

View file

@ -41,6 +41,14 @@ public interface IBlockWithFilter {
return 2 / 16f;
}
public default float getFilterAngle(BlockState state) {
return 22.5f;
}
public default boolean isFilterVisible(BlockState state) {
return true;
}
public default boolean showsCount() {
return false;
}
@ -50,8 +58,10 @@ public interface IBlockWithFilter {
TileEntity te = worldIn.getTileEntity(pos);
if (te == null || !(te instanceof IHaveFilter))
return false;
IHaveFilter actor = (IHaveFilter) te;
if (!isFilterVisible(state))
return false;
IHaveFilter actor = (IHaveFilter) te;
Vec3d vec = new Vec3d(pos);
Vec3d position = vec.add(getFilterPosition(state));
ItemStack stack = player.getHeldItem(handIn);
@ -86,6 +96,9 @@ public interface IBlockWithFilter {
IHaveFilter actor = (IHaveFilter) te;
IBlockWithFilter filterBlock = (IBlockWithFilter) state.getBlock();
if (!filterBlock.isFilterVisible(state))
return;
Vec3d vec = new Vec3d(pos);
Vec3d position = filterBlock.getFilterPosition(state).add(vec);
float scale = filterBlock.getItemHitboxScale();
@ -112,7 +125,8 @@ public interface IBlockWithFilter {
Vec3i direction = facing.getDirectionVec();
GlStateManager.pushMatrix();
GlStateManager.translated(position.x, position.y, position.z);
GlStateManager.rotated(22.5f, direction.getZ(), 0, -direction.getX());
float filterAngle = filterBlock.getFilterAngle(state);
GlStateManager.rotated(filterAngle, direction.getZ(), 0, -direction.getX());
GlStateManager.translated(-center.x, -center.y, -center.z);
GlStateManager.translated(-position.x, -position.y, -position.z);
@ -138,7 +152,7 @@ public interface IBlockWithFilter {
GlStateManager.rotated(facing.getHorizontalAngle() * (facing.getAxis() == Axis.X ? -1 : 1), 0, 1, 0);
GlStateManager.scaled(textScale, -textScale, textScale);
GlStateManager.translated(17.5f, -5f, -5f);
GlStateManager.rotated(67.5f, 1, 0, 0);
GlStateManager.rotated(90 - filterAngle, 1, 0, 0);
String text = Lang.translate("logistics.filter");
FontRenderer font = Minecraft.getInstance().fontRenderer;
@ -149,7 +163,7 @@ public interface IBlockWithFilter {
if (filterBlock.showsCount() && !actor.getFilter().isEmpty()) {
String count = actor.getFilter().getCount() + "";
GlStateManager.translated(-7 - font.getStringWidth(count), 10, 10 + 1 / 4f);
GlStateManager.scaled(1.5,1.5, 1.5);
GlStateManager.scaled(1.5, 1.5, 1.5);
font.drawString(count, 0, 0, 0xEDEDED);
GlStateManager.translated(0, 0, -1 / 4f);
font.drawString(count, 1, 1, 0x4F4F4F);

View file

@ -0,0 +1,16 @@
{
"type": "create:cutting",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:acacia_log"
}
],
"results": [
{
"item": "minecraft:stripped_acacia_log",
"count": 1
}
],
"processingTime": 50
}

View file

@ -0,0 +1,16 @@
{
"type": "create:cutting",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:birch_log"
}
],
"results": [
{
"item": "minecraft:stripped_birch_log",
"count": 1
}
],
"processingTime": 50
}

View file

@ -0,0 +1,16 @@
{
"type": "create:cutting",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:dark_oak_log"
}
],
"results": [
{
"item": "minecraft:stripped_dark_oak_log",
"count": 1
}
],
"processingTime": 50
}

View file

@ -0,0 +1,16 @@
{
"type": "create:cutting",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:jungle_log"
}
],
"results": [
{
"item": "minecraft:stripped_jungle_log",
"count": 1
}
],
"processingTime": 50
}

View file

@ -0,0 +1,16 @@
{
"type": "create:cutting",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:oak_log"
}
],
"results": [
{
"item": "minecraft:stripped_oak_log",
"count": 1
}
],
"processingTime": 50
}

View file

@ -0,0 +1,16 @@
{
"type": "create:cutting",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:spruce_log"
}
],
"results": [
{
"item": "minecraft:stripped_spruce_log",
"count": 1
}
],
"processingTime": 50
}

View file

@ -0,0 +1,16 @@
{
"type": "create:cutting",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:stripped_acacia_log"
}
],
"results": [
{
"item": "minecraft:acacia_planks",
"count": 5
}
],
"processingTime": 100
}

View file

@ -0,0 +1,16 @@
{
"type": "create:cutting",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:stripped_birch_log"
}
],
"results": [
{
"item": "minecraft:birch_planks",
"count": 5
}
],
"processingTime": 100
}

View file

@ -0,0 +1,16 @@
{
"type": "create:cutting",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:stripped_dark_oak_log"
}
],
"results": [
{
"item": "minecraft:dark_oak_planks",
"count": 5
}
],
"processingTime": 100
}

View file

@ -0,0 +1,16 @@
{
"type": "create:cutting",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:stripped_jungle_log"
}
],
"results": [
{
"item": "minecraft:jungle_planks",
"count": 5
}
],
"processingTime": 100
}

View file

@ -0,0 +1,16 @@
{
"type": "create:cutting",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:stripped_oak_log"
}
],
"results": [
{
"item": "minecraft:oak_planks",
"count": 5
}
],
"processingTime": 100
}

View file

@ -0,0 +1,16 @@
{
"type": "create:cutting",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:stripped_spruce_log"
}
],
"results": [
{
"item": "minecraft:spruce_planks",
"count": 5
}
],
"processingTime": 100
}