A not-perfect cache for the VoxelShape to improve performance.
This commit is contained in:
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013 AlgorithmX2
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package appeng.api.parts;
|
||||
|
||||
public interface IBoxProvider {
|
||||
|
||||
/**
|
||||
* add your collision information to the the list.
|
||||
*
|
||||
* @param boxes collision boxes
|
||||
*/
|
||||
void getBoxes(IPartCollisionHelper boxes);
|
||||
}
|
||||
@@ -45,10 +45,10 @@ public interface IFacadePart {
|
||||
/**
|
||||
* used to collide, and pick the part
|
||||
*
|
||||
* @param ch collision helper
|
||||
* @param e colliding entity
|
||||
* @param ch collision helper
|
||||
* @param livingEntity collision with a living entity?
|
||||
*/
|
||||
void getBoxes(IPartCollisionHelper ch, Entity e);
|
||||
void getBoxes(IPartCollisionHelper ch, boolean livingEntity);
|
||||
|
||||
/**
|
||||
* @return side the facade is in
|
||||
|
||||
@@ -56,7 +56,7 @@ import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
|
||||
public interface IPart extends IBoxProvider, ICustomCableConnection {
|
||||
public interface IPart extends ICustomCableConnection {
|
||||
|
||||
/**
|
||||
* get an ItemStack that represents the bus, should contain the settings for
|
||||
@@ -364,4 +364,11 @@ public interface IPart extends IBoxProvider, ICustomCableConnection {
|
||||
return EmptyModelData.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* add your collision information to the the list.
|
||||
*
|
||||
* @param bch collision boxes
|
||||
*/
|
||||
void getBoxes(final IPartCollisionHelper bch);
|
||||
|
||||
}
|
||||
|
||||
@@ -370,36 +370,22 @@ public class CableBusBlock extends AEBaseTileBlock<CableBusTileEntity> implement
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, IBlockReader w, BlockPos pos, ISelectionContext context) {
|
||||
|
||||
// FIXME: this has to be cached, optimized, fixed in all kinds of ways
|
||||
CableBusTileEntity te = getTileEntity(w, pos);
|
||||
VoxelShape result = VoxelShapes.empty();
|
||||
if (te != null) {
|
||||
for (final AxisAlignedBB bx : te.getCableBus().getSelectedBoundingBoxesFromPool(false, true,
|
||||
context.getEntity(), true)) {
|
||||
result = VoxelShapes.or(result,
|
||||
VoxelShapes.create(new AxisAlignedBB(bx.minX, bx.minY, bx.minZ, bx.maxX, bx.maxY, bx.maxZ)));
|
||||
}
|
||||
if (te == null) {
|
||||
return VoxelShapes.empty();
|
||||
} else {
|
||||
return te.getCableBus().getShape();
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getCollisionShape(BlockState state, IBlockReader w, BlockPos pos, ISelectionContext context) {
|
||||
|
||||
// FIXME: this has to be cached, optimized, fixed in all kinds of ways
|
||||
CableBusTileEntity te = getTileEntity(w, pos);
|
||||
VoxelShape result = VoxelShapes.empty();
|
||||
if (te != null) {
|
||||
for (final AxisAlignedBB bx : te.getCableBus().getSelectedBoundingBoxesFromPool(false, true,
|
||||
context.getEntity(), false)) {
|
||||
result = VoxelShapes.or(result,
|
||||
VoxelShapes.create(new AxisAlignedBB(bx.minX, bx.minY, bx.minZ, bx.maxX, bx.maxY, bx.maxZ)));
|
||||
}
|
||||
if (te == null) {
|
||||
return VoxelShapes.empty();
|
||||
} else {
|
||||
return te.getCableBus().getCollisionShape(context.getEntity());
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,18 +20,15 @@ package appeng.facade;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
|
||||
import appeng.api.parts.IBoxProvider;
|
||||
import appeng.api.parts.IFacadePart;
|
||||
import appeng.api.parts.IPartCollisionHelper;
|
||||
import appeng.api.util.AEPartLocation;
|
||||
|
||||
public class FacadePart implements IFacadePart, IBoxProvider {
|
||||
public class FacadePart implements IFacadePart {
|
||||
|
||||
private final ItemStack facade;
|
||||
private final AEPartLocation side;
|
||||
@@ -51,8 +48,8 @@ public class FacadePart implements IFacadePart, IBoxProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper ch, final Entity e) {
|
||||
if (e instanceof LivingEntity) {
|
||||
public void getBoxes(final IPartCollisionHelper ch, boolean livingEntity) {
|
||||
if (livingEntity) {
|
||||
// prevent weird snag behavior
|
||||
ch.addBox(0.0, 0.0, 14, 16.0, 16.0, 16.0);
|
||||
} else {
|
||||
@@ -108,8 +105,4 @@ public class FacadePart implements IFacadePart, IBoxProvider {
|
||||
return Blocks.GLASS.getDefaultState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBoxes(final IPartCollisionHelper bch) {
|
||||
this.getBoxes(bch, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ package appeng.parts;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
|
||||
@@ -35,23 +34,19 @@ public class BusCollisionHelper implements IPartCollisionHelper {
|
||||
private final Direction y;
|
||||
private final Direction z;
|
||||
|
||||
private final Entity entity;
|
||||
private final boolean isVisual;
|
||||
|
||||
public BusCollisionHelper(final List<AxisAlignedBB> boxes, final Direction x, final Direction y, final Direction z,
|
||||
final Entity e, final boolean visual) {
|
||||
final boolean visual) {
|
||||
this.boxes = boxes;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.entity = e;
|
||||
this.isVisual = visual;
|
||||
}
|
||||
|
||||
public BusCollisionHelper(final List<AxisAlignedBB> boxes, final AEPartLocation s, final Entity e,
|
||||
final boolean visual) {
|
||||
public BusCollisionHelper(final List<AxisAlignedBB> boxes, final AEPartLocation s, final boolean visual) {
|
||||
this.boxes = boxes;
|
||||
this.entity = e;
|
||||
this.isVisual = visual;
|
||||
|
||||
switch (s) {
|
||||
@@ -94,13 +89,6 @@ public class BusCollisionHelper implements IPartCollisionHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pretty much useless...
|
||||
*/
|
||||
public Entity getEntity() {
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBox(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
|
||||
minX /= 16.0;
|
||||
|
||||
@@ -37,6 +37,8 @@ import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
@@ -71,6 +73,11 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
// TODO 1.10.2-R - does somebody seriously want to make parts TESR??? Hope not.
|
||||
private boolean requiresDynamicRender = false;
|
||||
private boolean inWorld = false;
|
||||
// Cached collision shape for living entities
|
||||
private VoxelShape cachedCollisionShapeLiving;
|
||||
// Cached collision shape for anything but living entities
|
||||
private VoxelShape cachedCollisionShape;
|
||||
private VoxelShape cachedShape;
|
||||
|
||||
public CableBusContainer(final IPartHost host) {
|
||||
this.tcb = host;
|
||||
@@ -210,6 +217,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
}
|
||||
}
|
||||
|
||||
this.invalidateShapes();
|
||||
this.updateConnections();
|
||||
this.markForUpdate();
|
||||
this.markForSave();
|
||||
@@ -249,6 +257,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
}
|
||||
}
|
||||
|
||||
this.invalidateShapes();
|
||||
this.updateDynamicRender();
|
||||
this.updateConnections();
|
||||
this.markForUpdate();
|
||||
@@ -289,6 +298,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
}
|
||||
|
||||
if (!suppressUpdate) {
|
||||
this.invalidateShapes();
|
||||
this.updateDynamicRender();
|
||||
this.updateConnections();
|
||||
this.markForUpdate();
|
||||
@@ -338,7 +348,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
if (p != null) {
|
||||
final List<AxisAlignedBB> boxes = new ArrayList<>();
|
||||
|
||||
final IPartCollisionHelper bch = new BusCollisionHelper(boxes, side, null, true);
|
||||
final IPartCollisionHelper bch = new BusCollisionHelper(boxes, side, true);
|
||||
p.getBoxes(bch);
|
||||
for (AxisAlignedBB bb : boxes) {
|
||||
bb = bb.grow(0.002, 0.002, 0.002);
|
||||
@@ -356,8 +366,8 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
if (p != null) {
|
||||
final List<AxisAlignedBB> boxes = new ArrayList<>();
|
||||
|
||||
final IPartCollisionHelper bch = new BusCollisionHelper(boxes, side, null, true);
|
||||
p.getBoxes(bch, null);
|
||||
final IPartCollisionHelper bch = new BusCollisionHelper(boxes, side, true);
|
||||
p.getBoxes(bch, true);
|
||||
for (AxisAlignedBB bb : boxes) {
|
||||
bb = bb.grow(0.01, 0.01, 0.01);
|
||||
if (bb.contains(pos)) {
|
||||
@@ -545,6 +555,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
}
|
||||
}
|
||||
|
||||
this.invalidateShapes();
|
||||
this.partChanged();
|
||||
}
|
||||
|
||||
@@ -599,36 +610,6 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
}
|
||||
}
|
||||
|
||||
public Iterable<AxisAlignedBB> getSelectedBoundingBoxesFromPool(final boolean ignoreConnections,
|
||||
final boolean includeFacades, final Entity e, final boolean visual) {
|
||||
final List<AxisAlignedBB> boxes = new ArrayList<>();
|
||||
|
||||
final IFacadeContainer fc = this.getFacadeContainer();
|
||||
for (final AEPartLocation s : AEPartLocation.values()) {
|
||||
final IPartCollisionHelper bch = new BusCollisionHelper(boxes, s, e, visual);
|
||||
|
||||
final IPart part = this.getPart(s);
|
||||
if (part != null) {
|
||||
if (ignoreConnections && part instanceof ICablePart) {
|
||||
bch.addBox(6.0, 6.0, 6.0, 10.0, 10.0, 10.0);
|
||||
} else {
|
||||
part.getBoxes(bch);
|
||||
}
|
||||
}
|
||||
|
||||
if (AEApi.instance().partHelper().getCableRenderMode().opaqueFacades || !visual) {
|
||||
if (includeFacades && s != null && s != AEPartLocation.INTERNAL) {
|
||||
final IFacadePart fp = fc.getFacade(s);
|
||||
if (fp != null) {
|
||||
fp.getBoxes(bch, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return boxes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int isProvidingStrongPower(final Direction side) {
|
||||
final IPart part = this.getPart(side);
|
||||
@@ -699,6 +680,9 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
part.onNeighborChanged(w, pos, neighbor);
|
||||
}
|
||||
}
|
||||
|
||||
// Some parts will change their shape (connected texture style)
|
||||
invalidateShapes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -798,9 +782,10 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
}
|
||||
}
|
||||
|
||||
if (this.getFacadeContainer().readFromStream(data)) {
|
||||
return true;
|
||||
}
|
||||
updateBlock |= this.getFacadeContainer().readFromStream(data);
|
||||
|
||||
// Updating tiles may change the collision shape
|
||||
this.invalidateShapes();
|
||||
|
||||
return updateBlock;
|
||||
}
|
||||
@@ -841,6 +826,8 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
}
|
||||
|
||||
public void readFromNBT(final CompoundNBT data) {
|
||||
invalidateShapes();
|
||||
|
||||
if (data.contains("hasRedstone")) {
|
||||
this.hasRedstone = YesNo.values()[data.getInt("hasRedstone")];
|
||||
}
|
||||
@@ -1006,8 +993,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
// This will add the part's bounding boxes to the render state, which is
|
||||
// required for facades
|
||||
final AEPartLocation loc = AEPartLocation.fromFacing(facing);
|
||||
final IPartCollisionHelper bch = new BusCollisionHelper(renderState.getBoundingBoxes(), loc, null, true);
|
||||
|
||||
final IPartCollisionHelper bch = new BusCollisionHelper(renderState.getBoundingBoxes(), loc, true);
|
||||
part.getBoxes(bch);
|
||||
|
||||
if (part instanceof IGridHost) {
|
||||
@@ -1049,4 +1035,71 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link net.minecraft.block.Block#getShape}
|
||||
*/
|
||||
public VoxelShape getShape() {
|
||||
if (cachedShape == null) {
|
||||
cachedShape = createShape(false, false);
|
||||
}
|
||||
|
||||
return cachedShape;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link net.minecraft.block.Block#getCollisionShape}
|
||||
*/
|
||||
public VoxelShape getCollisionShape(Entity entity) {
|
||||
// This is a hack for facades
|
||||
boolean livingEntity = entity instanceof LivingEntity;
|
||||
|
||||
if (livingEntity) {
|
||||
if (cachedCollisionShapeLiving == null) {
|
||||
cachedCollisionShapeLiving = createShape(true, true);
|
||||
}
|
||||
return cachedCollisionShapeLiving;
|
||||
} else {
|
||||
if (cachedCollisionShape == null) {
|
||||
cachedCollisionShape = createShape(true, false);
|
||||
}
|
||||
return cachedCollisionShape;
|
||||
}
|
||||
}
|
||||
|
||||
private VoxelShape createShape(boolean forCollision, boolean forLivingEntity) {
|
||||
final List<AxisAlignedBB> boxes = new ArrayList<>();
|
||||
|
||||
final IFacadeContainer fc = this.getFacadeContainer();
|
||||
for (final AEPartLocation s : AEPartLocation.values()) {
|
||||
final IPartCollisionHelper bch = new BusCollisionHelper(boxes, s, !forCollision);
|
||||
|
||||
final IPart part = this.getPart(s);
|
||||
if (part != null) {
|
||||
part.getBoxes(bch);
|
||||
}
|
||||
|
||||
if (AEApi.instance().partHelper().getCableRenderMode().opaqueFacades || forCollision) {
|
||||
if (s != AEPartLocation.INTERNAL) {
|
||||
final IFacadePart fp = fc.getFacade(s);
|
||||
if (fp != null) {
|
||||
fp.getBoxes(bch, forLivingEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VoxelShape shape = VoxelShapes.empty();
|
||||
for (final AxisAlignedBB bx : boxes) {
|
||||
shape = VoxelShapes.or(shape, VoxelShapes.create(bx));
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
private void invalidateShapes() {
|
||||
cachedShape = null;
|
||||
cachedCollisionShape = null;
|
||||
cachedCollisionShapeLiving = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user