mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-10 20:45:10 +01:00
Merge remote-tracking branch 'origin/mc1.15/dev' into mc1.16/dev
# Conflicts: # src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java # src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java
This commit is contained in:
commit
78fbb52ddc
@ -50,10 +50,7 @@ import com.simibubi.create.content.contraptions.components.press.PressInstance;
|
||||
import com.simibubi.create.content.contraptions.components.saw.SawInstance;
|
||||
import com.simibubi.create.content.contraptions.components.saw.SawRenderer;
|
||||
import com.simibubi.create.content.contraptions.components.saw.SawTileEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingRenderer;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingTileEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingTileEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingTileEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.*;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisTileEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerInstance;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerRenderer;
|
||||
@ -380,21 +377,21 @@ public class AllTileEntities {
|
||||
|
||||
public static final TileEntityEntry<WindmillBearingTileEntity> WINDMILL_BEARING = Create.registrate()
|
||||
.tileEntity("windmill_bearing", WindmillBearingTileEntity::new)
|
||||
.instance(() -> BackHalfShaftInstance::new)
|
||||
.instance(() -> BearingInstance::new)
|
||||
.validBlocks(AllBlocks.WINDMILL_BEARING)
|
||||
.renderer(() -> BearingRenderer::new)
|
||||
.register();
|
||||
|
||||
public static final TileEntityEntry<MechanicalBearingTileEntity> MECHANICAL_BEARING = Create.registrate()
|
||||
.tileEntity("mechanical_bearing", MechanicalBearingTileEntity::new)
|
||||
.instance(() -> BackHalfShaftInstance::new)
|
||||
.instance(() -> BearingInstance::new)
|
||||
.validBlocks(AllBlocks.MECHANICAL_BEARING)
|
||||
.renderer(() -> BearingRenderer::new)
|
||||
.register();
|
||||
|
||||
public static final TileEntityEntry<ClockworkBearingTileEntity> CLOCKWORK_BEARING = Create.registrate()
|
||||
.tileEntity("clockwork_bearing", ClockworkBearingTileEntity::new)
|
||||
.instance(() -> BackHalfShaftInstance::new)
|
||||
.instance(() -> BearingInstance::new)
|
||||
.validBlocks(AllBlocks.CLOCKWORK_BEARING)
|
||||
.renderer(() -> BearingRenderer::new)
|
||||
.register();
|
||||
|
@ -13,6 +13,7 @@ import org.apache.commons.lang3.mutable.MutableInt;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllMovementBehaviours;
|
||||
import com.simibubi.create.content.contraptions.components.actors.BlockBreakingMovementBehaviour;
|
||||
@ -221,6 +222,7 @@ public class ContraptionCollider {
|
||||
totalResponse = VecHelper.rotate(totalResponse, yawOffset, Axis.Y);
|
||||
collisionNormal = rotationMatrix.transform(collisionNormal);
|
||||
collisionNormal = VecHelper.rotate(collisionNormal, yawOffset, Axis.Y);
|
||||
collisionNormal = collisionNormal.normalize();
|
||||
collisionLocation = rotationMatrix.transform(collisionLocation);
|
||||
collisionLocation = VecHelper.rotate(collisionLocation, yawOffset, Axis.Y);
|
||||
rotationMatrix.transpose();
|
||||
@ -248,16 +250,11 @@ public class ContraptionCollider {
|
||||
boolean hasNormal = !collisionNormal.equals(Vector3d.ZERO);
|
||||
boolean anyCollision = hardCollision || temporalCollision;
|
||||
|
||||
if (bounce > 0 && hasNormal && anyCollision) {
|
||||
collisionNormal = collisionNormal.normalize();
|
||||
Vector3d newNormal = collisionNormal.crossProduct(collisionNormal.crossProduct(entityMotionNoTemporal))
|
||||
.normalize();
|
||||
if (bounceEntity(entity, newNormal, contraptionEntity, bounce)) {
|
||||
entity.world.playSound(playerType == PlayerType.CLIENT ? (PlayerEntity) entity : null,
|
||||
entity.getX(), entity.getY(), entity.getZ(), SoundEvents.BLOCK_SLIME_BLOCK_FALL,
|
||||
SoundCategory.BLOCKS, .5f, 1);
|
||||
continue;
|
||||
}
|
||||
if (bounce > 0 && hasNormal && anyCollision && bounceEntity(entity, collisionNormal, contraptionEntity, bounce)) {
|
||||
entity.world.playSound(playerType == PlayerType.CLIENT ? (PlayerEntity) entity : null,
|
||||
entity.getX(), entity.getY(), entity.getZ(), SoundEvents.BLOCK_SLIME_BLOCK_FALL,
|
||||
SoundCategory.BLOCKS, .5f, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (temporalCollision) {
|
||||
@ -288,7 +285,6 @@ public class ContraptionCollider {
|
||||
}
|
||||
|
||||
if (bounce == 0 && slide > 0 && hasNormal && anyCollision && rotation.hasVerticalRotation()) {
|
||||
collisionNormal = collisionNormal.normalize();
|
||||
Vector3d motionIn = entityMotionNoTemporal.mul(0, 1, 0)
|
||||
.add(0, -.01f, 0);
|
||||
Vector3d slideNormal = collisionNormal.crossProduct(motionIn.crossProduct(collisionNormal))
|
||||
@ -346,35 +342,14 @@ public class ContraptionCollider {
|
||||
return false;
|
||||
if (entity.bypassesLandingEffects())
|
||||
return false;
|
||||
if (normal.equals(Vector3d.ZERO))
|
||||
return false;
|
||||
|
||||
Vector3d contraptionVec = Vector3d.ZERO;
|
||||
Vector3d contactPointMotion = contraption.getContactPointMotion(entity.getPositionVec());
|
||||
Vector3d motion = entity.getMotion()
|
||||
.subtract(contactPointMotion);
|
||||
|
||||
Vector3d v2 = motion.crossProduct(normal)
|
||||
.normalize();
|
||||
if (v2 != Vector3d.ZERO)
|
||||
contraptionVec = normal.scale(contraptionVec.dotProduct(normal))
|
||||
.add(v2.scale(contraptionVec.dotProduct(v2)));
|
||||
else
|
||||
v2 = normal.crossProduct(normal.add(Math.random(), Math.random(), Math.random()))
|
||||
.normalize();
|
||||
|
||||
Vector3d v3 = normal.crossProduct(v2);
|
||||
motion = motion.subtract(contraptionVec);
|
||||
Vector3d lr = new Vector3d(factor * motion.dotProduct(normal), -motion.dotProduct(v2), -motion.dotProduct(v3));
|
||||
|
||||
if (lr.dotProduct(lr) > 1 / 16f) {
|
||||
Vector3d newMot = contactPointMotion.add(normal.x * lr.x + v2.x * lr.y + v3.x * lr.z,
|
||||
normal.y * lr.x + v2.y * lr.y + v3.y * lr.z, normal.z * lr.x + v2.z * lr.y + v3.z * lr.z);
|
||||
entity.setMotion(newMot);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
Vector3d motion = entity.getMotion().subtract(contactPointMotion);
|
||||
Vector3d deltav = normal.scale(factor*2*motion.dotProduct(normal));
|
||||
if (deltav.dotProduct(deltav) < 0.1f)
|
||||
return false;
|
||||
entity.setMotion(entity.getMotion().subtract(deltav));
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Vector3d getWorldToLocalTranslation(Entity entity, AbstractContraptionEntity contraptionEntity) {
|
||||
|
@ -8,15 +8,6 @@ public class NonStationaryLighter<C extends Contraption> extends ContraptionLigh
|
||||
super(contraption);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GridAlignedBB contraptionBoundsToVolume(GridAlignedBB bounds) {
|
||||
bounds.grow(2); // so we have at least enough data on the edges to avoid artifacts and have smooth lighting
|
||||
bounds.minY = Math.max(bounds.minY, 0);
|
||||
bounds.maxY = Math.min(bounds.maxY, 255);
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(RenderedContraption owner) {
|
||||
super.tick(owner);
|
||||
|
@ -0,0 +1,77 @@
|
||||
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
|
||||
|
||||
import net.minecraft.client.renderer.Quaternion;
|
||||
import net.minecraft.client.renderer.Vector3f;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.util.Direction;
|
||||
|
||||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.content.contraptions.base.BackHalfShaftInstance;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.foundation.render.backend.core.OrientedData;
|
||||
import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance;
|
||||
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
|
||||
public class BearingInstance<B extends KineticTileEntity & IBearingTileEntity> extends BackHalfShaftInstance implements IDynamicInstance {
|
||||
final B bearing;
|
||||
|
||||
final OrientedData topInstance;
|
||||
|
||||
final Vector3f rotationAxis;
|
||||
final Quaternion blockOrientation;
|
||||
|
||||
public BearingInstance(InstancedTileRenderer<?> modelManager, B tile) {
|
||||
super(modelManager, tile);
|
||||
this.bearing = tile;
|
||||
|
||||
Direction facing = blockState.get(BlockStateProperties.FACING);
|
||||
rotationAxis = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector();
|
||||
|
||||
blockOrientation = getBlockStateOrientation(facing);
|
||||
|
||||
AllBlockPartials top =
|
||||
bearing.isWoodenTop() ? AllBlockPartials.BEARING_TOP_WOODEN : AllBlockPartials.BEARING_TOP;
|
||||
|
||||
topInstance = getOrientedMaterial().getModel(top, blockState).createInstance();
|
||||
|
||||
topInstance.setPosition(getInstancePosition()).setRotation(blockOrientation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginFrame() {
|
||||
|
||||
float interpolatedAngle = bearing.getInterpolatedAngle(AnimationTickHolder.getPartialTicks() - 1);
|
||||
Quaternion rot = rotationAxis.getDegreesQuaternion(interpolatedAngle);
|
||||
|
||||
rot.multiply(blockOrientation);
|
||||
|
||||
topInstance.setRotation(rot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
super.updateLight();
|
||||
relight(pos, topInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
topInstance.delete();
|
||||
}
|
||||
|
||||
static Quaternion getBlockStateOrientation(Direction facing) {
|
||||
Quaternion orientation;
|
||||
|
||||
if (facing.getAxis().isHorizontal()) {
|
||||
orientation = Vector3f.POSITIVE_Y.getDegreesQuaternion(AngleHelper.horizontalAngle(facing.getOpposite()));
|
||||
} else {
|
||||
orientation = Quaternion.IDENTITY.copy();
|
||||
}
|
||||
|
||||
orientation.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(-90 - AngleHelper.verticalAngle(facing)));
|
||||
return orientation;
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
@ -22,6 +23,9 @@ public class BearingRenderer extends KineticTileEntityRenderer {
|
||||
@Override
|
||||
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
|
||||
if (FastRenderDispatcher.available(te.getWorld())) return;
|
||||
|
||||
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
|
||||
|
||||
IBearingTileEntity bearingTe = (IBearingTileEntity) te;
|
||||
|
@ -0,0 +1,51 @@
|
||||
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.Quaternion;
|
||||
import net.minecraft.client.renderer.Vector3f;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.util.Direction;
|
||||
|
||||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer;
|
||||
import com.simibubi.create.foundation.render.backend.core.OrientedData;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
|
||||
public class StabilizedBearingInstance extends ActorInstance {
|
||||
|
||||
final OrientedData topInstance;
|
||||
|
||||
final Direction facing;
|
||||
final Vector3f rotationAxis;
|
||||
final Quaternion blockOrientation;
|
||||
|
||||
public StabilizedBearingInstance(ContraptionKineticRenderer modelManager, MovementContext context) {
|
||||
super(modelManager, context);
|
||||
|
||||
BlockState blockState = context.state;
|
||||
|
||||
facing = blockState.get(BlockStateProperties.FACING);
|
||||
rotationAxis = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, facing.getAxis()).getUnitVector();
|
||||
|
||||
blockOrientation = BearingInstance.getBlockStateOrientation(facing);
|
||||
|
||||
topInstance = modelManager.getOrientedMaterial().getModel(AllBlockPartials.BEARING_TOP, blockState).createInstance();
|
||||
|
||||
topInstance.setPosition(context.localPos)
|
||||
.setRotation(blockOrientation)
|
||||
.setBlockLight(localBlockLight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginFrame() {
|
||||
float counterRotationAngle = StabilizedBearingMovementBehaviour.getCounterRotationAngle(context, facing, AnimationTickHolder.getPartialTicks());
|
||||
|
||||
Quaternion rotation = rotationAxis.getDegreesQuaternion(counterRotationAngle);
|
||||
|
||||
rotation.multiply(blockOrientation);
|
||||
|
||||
topInstance.setRotation(rotation);
|
||||
}
|
||||
}
|
@ -7,12 +7,16 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.Quaternion;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.util.Direction;
|
||||
@ -20,28 +24,57 @@ import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
|
||||
|
||||
@Override
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal,
|
||||
IRenderTypeBuffer buffer) {
|
||||
if (FastRenderDispatcher.available()) return;
|
||||
|
||||
Direction facing = context.state.get(BlockStateProperties.FACING);
|
||||
AllBlockPartials top = AllBlockPartials.BEARING_TOP;
|
||||
SuperByteBuffer superBuffer = top.renderOn(context.state);
|
||||
float renderPartialTicks = AnimationTickHolder.getPartialTicks();
|
||||
|
||||
// rotate to match blockstate
|
||||
Axis axis = facing.getAxis();
|
||||
if (axis.isHorizontal())
|
||||
superBuffer.rotateCentered(Direction.UP,
|
||||
AngleHelper.rad(AngleHelper.horizontalAngle(facing.getOpposite())));
|
||||
superBuffer.rotateCentered(Direction.EAST, AngleHelper.rad(-90 - AngleHelper.verticalAngle(facing)));
|
||||
Quaternion orientation = BearingInstance.getBlockStateOrientation(facing);
|
||||
|
||||
// rotate against parent
|
||||
float angle = getCounterRotationAngle(context, facing, renderPartialTicks) * facing.getAxisDirection().getOffset();
|
||||
|
||||
Quaternion rotation = facing.getUnitVector().getDegreesQuaternion(angle);
|
||||
|
||||
rotation.multiply(orientation);
|
||||
|
||||
orientation = rotation;
|
||||
|
||||
superBuffer.rotateCentered(orientation);
|
||||
|
||||
// render
|
||||
superBuffer.light(msLocal.peek()
|
||||
.getModel(), ContraptionRenderDispatcher.getLightOnContraption(context));
|
||||
superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSpecialInstancedRendering() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ActorInstance createInstance(ContraptionKineticRenderer kr, MovementContext context) {
|
||||
return new StabilizedBearingInstance(kr, context);
|
||||
}
|
||||
|
||||
static float getCounterRotationAngle(MovementContext context, Direction facing, float renderPartialTicks) {
|
||||
float offset = 0;
|
||||
int offsetMultiplier = facing.getAxisDirection().getOffset();
|
||||
|
||||
|
||||
Axis axis = facing.getAxis();
|
||||
|
||||
AbstractContraptionEntity entity = context.contraption.entity;
|
||||
if (entity instanceof ControlledContraptionEntity) {
|
||||
ControlledContraptionEntity controlledCE = (ControlledContraptionEntity) entity;
|
||||
@ -54,17 +87,12 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour {
|
||||
offset = -orientedCE.getYaw(renderPartialTicks);
|
||||
else {
|
||||
if (orientedCE.isInitialOrientationPresent() && orientedCE.getInitialOrientation()
|
||||
.getAxis() == axis)
|
||||
.getAxis() == axis)
|
||||
offset = -orientedCE.getPitch(renderPartialTicks);
|
||||
}
|
||||
}
|
||||
if (offset != 0)
|
||||
superBuffer.rotateCentered(Direction.UP, AngleHelper.rad(offset * offsetMultiplier));
|
||||
|
||||
// render
|
||||
superBuffer.light(msLocal.peek()
|
||||
.getModel(), ContraptionRenderDispatcher.getLightOnContraption(context));
|
||||
superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ public class TreeFertilizerItem extends Item {
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
TreesDreamWorld world = new TreesDreamWorld((ServerWorld) context.getWorld(), context.getPos());
|
||||
BlockPos saplingPos = context.getPos();
|
||||
TreesDreamWorld world = new TreesDreamWorld((ServerWorld) context.getWorld(), saplingPos);
|
||||
|
||||
for (BlockPos pos : BlockPos.getAllInBoxMutable(-1, 0, -1, 1, 0, 1)) {
|
||||
if (context.getWorld()
|
||||
@ -45,8 +45,8 @@ public class TreeFertilizerItem extends Item {
|
||||
state.with(SaplingBlock.STAGE, 1));
|
||||
|
||||
for (BlockPos pos : world.blocksAdded.keySet()) {
|
||||
BlockPos actualPos = pos.add(saplingPos)
|
||||
.down(10);
|
||||
BlockPos actualPos = pos.add(saplingPos).down(10);
|
||||
BlockState newState = world.blocksAdded.get(pos);
|
||||
|
||||
// Don't replace Bedrock
|
||||
if (context.getWorld()
|
||||
@ -54,21 +54,15 @@ public class TreeFertilizerItem extends Item {
|
||||
.getBlockHardness(context.getWorld(), actualPos) == -1)
|
||||
continue;
|
||||
// Don't replace solid blocks with leaves
|
||||
if (!world.getBlockState(pos)
|
||||
.isNormalCube(world, pos)
|
||||
if (!newState.isNormalCube(world, pos)
|
||||
&& !context.getWorld()
|
||||
.getBlockState(actualPos)
|
||||
.getCollisionShape(context.getWorld(), actualPos)
|
||||
.isEmpty())
|
||||
continue;
|
||||
if (world.getBlockState(pos)
|
||||
.getBlock() == Blocks.GRASS_BLOCK
|
||||
|| world.getBlockState(pos)
|
||||
.getBlock() == Blocks.PODZOL)
|
||||
continue;
|
||||
|
||||
context.getWorld()
|
||||
.setBlockState(actualPos, world.getBlockState(pos));
|
||||
.setBlockState(actualPos, newState);
|
||||
}
|
||||
|
||||
if (context.getPlayer() != null && !context.getPlayer()
|
||||
@ -84,21 +78,27 @@ public class TreeFertilizerItem extends Item {
|
||||
|
||||
private class TreesDreamWorld extends PlacementSimulationServerWorld {
|
||||
private final BlockPos saplingPos;
|
||||
private final BlockState soil;
|
||||
|
||||
protected TreesDreamWorld(ServerWorld wrapped, BlockPos saplingPos) {
|
||||
super(wrapped);
|
||||
this.saplingPos = saplingPos;
|
||||
soil = wrapped.getBlockState(saplingPos.down());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
if (pos.getY() <= 9)
|
||||
return world.getBlockState(saplingPos.down());
|
||||
return soil;
|
||||
return super.getBlockState(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlockState(BlockPos pos, BlockState newState, int flags) {
|
||||
if (newState.getBlock() == Blocks.PODZOL)
|
||||
return true;
|
||||
return super.setBlockState(pos, newState, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -30,9 +30,15 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||
|
||||
private final ArrayList<ModelData> models;
|
||||
private final ArmTileEntity arm;
|
||||
private final Boolean ceiling;
|
||||
|
||||
private boolean firstTick = true;
|
||||
|
||||
private float baseAngle = Float.NaN;
|
||||
private float lowerArmAngle = Float.NaN;
|
||||
private float upperArmAngle = Float.NaN;
|
||||
private float headAngle = Float.NaN;
|
||||
|
||||
public ArmInstance(InstancedTileRenderer<?> modelManager, ArmTileEntity tile) {
|
||||
super(modelManager, tile);
|
||||
|
||||
@ -51,31 +57,49 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||
clawGrips = Lists.newArrayList(clawGrip1, clawGrip2);
|
||||
models = Lists.newArrayList(base, lowerBody, upperBody, head, claw, clawGrip1, clawGrip2);
|
||||
arm = tile;
|
||||
ceiling = blockState.get(ArmBlock.CEILING);
|
||||
|
||||
animateArm(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginFrame() {
|
||||
if (arm.phase == ArmTileEntity.Phase.DANCING) {
|
||||
animateArm(true);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean settled = arm.baseAngle.settled() && arm.lowerArmAngle.settled() && arm.upperArmAngle.settled() && arm.headAngle.settled();
|
||||
boolean rave = arm.phase == ArmTileEntity.Phase.DANCING;
|
||||
float pt = AnimationTickHolder.getPartialTicks();
|
||||
|
||||
if (!settled || rave || firstTick)
|
||||
animateArm(rave);
|
||||
float baseAngleNow = this.arm.baseAngle.get(pt);
|
||||
float lowerArmAngleNow = this.arm.lowerArmAngle.get(pt);
|
||||
float upperArmAngleNow = this.arm.upperArmAngle.get(pt);
|
||||
float headAngleNow = this.arm.headAngle.get(pt);
|
||||
|
||||
boolean settled = MathHelper.epsilonEquals(baseAngle, baseAngleNow)
|
||||
&& MathHelper.epsilonEquals(lowerArmAngle, lowerArmAngleNow)
|
||||
&& MathHelper.epsilonEquals(upperArmAngle, upperArmAngleNow)
|
||||
&& MathHelper.epsilonEquals(headAngle, headAngleNow);
|
||||
|
||||
this.baseAngle = baseAngleNow;
|
||||
this.lowerArmAngle = lowerArmAngleNow;
|
||||
this.upperArmAngle = upperArmAngleNow;
|
||||
this.headAngle = headAngleNow;
|
||||
|
||||
if (!settled || firstTick)
|
||||
animateArm(false);
|
||||
|
||||
if (settled)
|
||||
firstTick = false;
|
||||
}
|
||||
|
||||
private void animateArm(boolean rave) {
|
||||
float pt = AnimationTickHolder.getPartialTicks();
|
||||
int color = 0xFFFFFF;
|
||||
|
||||
float baseAngle = this.arm.baseAngle.get(pt);
|
||||
float lowerArmAngle = this.arm.lowerArmAngle.get(pt) - 135;
|
||||
float upperArmAngle = this.arm.upperArmAngle.get(pt) - 90;
|
||||
float headAngle = this.arm.headAngle.get(pt);
|
||||
int color;
|
||||
float baseAngle;
|
||||
float lowerArmAngle;
|
||||
float upperArmAngle;
|
||||
float headAngle;
|
||||
|
||||
if (rave) {
|
||||
float renderTick = AnimationTickHolder.getRenderTime(this.arm.getWorld()) + (tile.hashCode() % 64);
|
||||
@ -83,7 +107,15 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||
lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15);
|
||||
upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95);
|
||||
headAngle = -lowerArmAngle;
|
||||
|
||||
color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100);
|
||||
} else {
|
||||
baseAngle = this.baseAngle;
|
||||
lowerArmAngle = this.lowerArmAngle - 135;
|
||||
upperArmAngle = this.upperArmAngle - 90;
|
||||
headAngle = this.headAngle;
|
||||
|
||||
color = 0xFFFFFF;
|
||||
}
|
||||
|
||||
MatrixStack msLocal = new MatrixStack();
|
||||
@ -91,7 +123,7 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta
|
||||
msr.translate(getInstancePosition());
|
||||
msr.centre();
|
||||
|
||||
if (blockState.get(ArmBlock.CEILING))
|
||||
if (ceiling)
|
||||
msr.rotateX(180);
|
||||
|
||||
ArmRenderer.transformBase(msr, baseAngle);
|
||||
|
@ -196,11 +196,21 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SuperByteBuffer rotate(Quaternion q) {
|
||||
transforms.multiply(q);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SuperByteBuffer rotateCentered(Direction axis, float radians) {
|
||||
return translate(.5f, .5f, .5f).rotate(axis, radians)
|
||||
.translate(-.5f, -.5f, -.5f);
|
||||
}
|
||||
|
||||
public SuperByteBuffer rotateCentered(Quaternion q) {
|
||||
return translate(.5f, .5f, .5f).rotate(q)
|
||||
.translate(-.5f, -.5f, -.5f);
|
||||
}
|
||||
|
||||
public SuperByteBuffer shiftUV(SpriteShiftEntry entry) {
|
||||
this.spriteShiftFunc = (builder, u, v) -> {
|
||||
float targetU = entry.getTarget().getInterpolatedU((getUnInterpolatedU(entry.getOriginal(), u)));
|
||||
|
@ -1,19 +1,17 @@
|
||||
package com.simibubi.create.foundation.render.backend;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.simibubi.create.foundation.render.backend.gl.GlFog;
|
||||
import com.simibubi.create.foundation.render.backend.gl.shader.*;
|
||||
import com.simibubi.create.foundation.render.backend.gl.versioned.GlFeatureCompat;
|
||||
import com.simibubi.create.foundation.render.backend.gl.versioned.GlCompat;
|
||||
import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld;
|
||||
import net.minecraft.world.World;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
|
||||
@ -28,7 +26,7 @@ public class Backend {
|
||||
|
||||
public static final Logger log = LogManager.getLogger(Backend.class);
|
||||
public static GLCapabilities capabilities;
|
||||
public static GlFeatureCompat compat;
|
||||
public static GlCompat compat;
|
||||
|
||||
private static boolean instancingAvailable;
|
||||
private static boolean enabled;
|
||||
@ -97,7 +95,7 @@ public class Backend {
|
||||
public static void refresh() {
|
||||
capabilities = GL.createCapabilities();
|
||||
|
||||
compat = new GlFeatureCompat(capabilities);
|
||||
compat = new GlCompat(capabilities);
|
||||
|
||||
instancingAvailable = compat.vertexArrayObjectsSupported() &&
|
||||
compat.drawInstancedSupported() &&
|
||||
|
@ -1,17 +1,16 @@
|
||||
package com.simibubi.create.foundation.render.backend;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.simibubi.create.foundation.render.backend.gl.GlFogMode;
|
||||
import com.simibubi.create.foundation.render.backend.gl.shader.*;
|
||||
import com.simibubi.create.foundation.render.backend.gl.versioned.GlFeatureCompat;
|
||||
|
||||
import net.minecraft.resources.IResource;
|
||||
import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.resource.IResourceType;
|
||||
import net.minecraftforge.resource.VanillaResourceType;
|
||||
import org.lwjgl.opengl.GL;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -4,6 +4,7 @@ import org.lwjgl.opengl.GL20;
|
||||
|
||||
import com.simibubi.create.foundation.render.backend.Backend;
|
||||
import com.simibubi.create.foundation.render.backend.gl.GlObject;
|
||||
import com.simibubi.create.foundation.render.backend.gl.versioned.GlCompat;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
@ -17,7 +18,7 @@ public class GlShader extends GlObject {
|
||||
this.name = name;
|
||||
int handle = GL20.glCreateShader(type.glEnum);
|
||||
|
||||
GL20.glShaderSource(handle, source);
|
||||
GlCompat.safeShaderSource(handle, source);
|
||||
GL20.glCompileShader(handle);
|
||||
|
||||
String log = GL20.glGetShaderInfoLog(handle);
|
||||
|
@ -1,6 +1,10 @@
|
||||
package com.simibubi.create.foundation.render.backend.gl.versioned;
|
||||
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.opengl.GL20C;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
@ -13,7 +17,7 @@ import java.util.function.Consumer;
|
||||
* Each field stores an enum variant that provides access to the
|
||||
* most appropriate version of a feature for the current system.
|
||||
*/
|
||||
public class GlFeatureCompat {
|
||||
public class GlCompat {
|
||||
public final MapBuffer mapBuffer;
|
||||
|
||||
public final VertexArrayObject vertexArrayObject;
|
||||
@ -22,7 +26,7 @@ public class GlFeatureCompat {
|
||||
|
||||
public final RGPixelFormat pixelFormat;
|
||||
|
||||
public GlFeatureCompat(GLCapabilities caps) {
|
||||
public GlCompat(GLCapabilities caps) {
|
||||
mapBuffer = getLatest(MapBuffer.class, caps);
|
||||
|
||||
vertexArrayObject = getLatest(VertexArrayObject.class, caps);
|
||||
@ -85,5 +89,33 @@ public class GlFeatureCompat {
|
||||
|
||||
return Arrays.stream(constants).filter(it -> it.supported(caps)).findFirst().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied from:
|
||||
* <br> https://github.com/grondag/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96
|
||||
*
|
||||
* <p>Identical in function to {@link GL20C#glShaderSource(int, CharSequence)} but
|
||||
* passes a null pointer for string length to force the driver to rely on the null
|
||||
* terminator for string length. This is a workaround for an apparent flaw with some
|
||||
* AMD drivers that don't receive or interpret the length correctly, resulting in
|
||||
* an access violation when the driver tries to read past the string memory.
|
||||
*
|
||||
* <p>Hat tip to fewizz for the find and the fix.
|
||||
*/
|
||||
public static void safeShaderSource(int glId, CharSequence source) {
|
||||
final MemoryStack stack = MemoryStack.stackGet();
|
||||
final int stackPointer = stack.getPointer();
|
||||
|
||||
try {
|
||||
final ByteBuffer sourceBuffer = MemoryUtil.memUTF8(source, true);
|
||||
final PointerBuffer pointers = stack.mallocPointer(1);
|
||||
pointers.put(sourceBuffer);
|
||||
|
||||
GL20C.nglShaderSource(glId, 1, pointers.address0(), 0);
|
||||
org.lwjgl.system.APIUtil.apiArrayFree(pointers.address0(), 1);
|
||||
} finally {
|
||||
stack.setPointer(stackPointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||
protected Map<MaterialType<?>, RenderMaterial<P, ?>> materials = new HashMap<>();
|
||||
|
||||
protected int frame;
|
||||
protected int tick;
|
||||
|
||||
protected InstancedTileRenderer() {
|
||||
registerMaterials();
|
||||
@ -43,6 +44,8 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||
public abstract void registerMaterials();
|
||||
|
||||
public void tick(double cameraX, double cameraY, double cameraZ) {
|
||||
tick++;
|
||||
|
||||
// integer camera pos
|
||||
int cX = (int) cameraX;
|
||||
int cY = (int) cameraY;
|
||||
@ -61,7 +64,7 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||
int dY = pos.getY() - cY;
|
||||
int dZ = pos.getZ() - cZ;
|
||||
|
||||
if ((frame % getUpdateDivisor(dX, dY, dZ)) == 0)
|
||||
if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0)
|
||||
instance.tick();
|
||||
}
|
||||
}
|
||||
@ -198,9 +201,9 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
||||
int dY = worldPos.getY() - cY;
|
||||
int dZ = worldPos.getZ() - cZ;
|
||||
|
||||
float dot = dX * lookX + dY * lookY + dZ * lookZ;
|
||||
float dot = (dX + lookX * 2) * lookX + (dY + lookY * 2) * lookY + (dZ + lookZ * 2) * lookZ;
|
||||
|
||||
if (dot < 0) return false; // is it behind the camera?
|
||||
if (dot < 0) return false; // is it more than 2 blocks behind the camera?
|
||||
|
||||
return (frame % getUpdateDivisor(dX, dY, dZ)) == 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user