[Edge] Panda wire port

This commit is contained in:
Sotr
2018-06-14 03:31:01 +08:00
parent db54c87abd
commit 97798e18ce
6 changed files with 1288 additions and 3 deletions

View File

@@ -293,7 +293,7 @@ public abstract class MixinChunk implements IMixinChunk {
if (chunk == null) {
continue;
}
chunk.a(enumfacing.opposite()); // PAIL: checkLightSide
chunk.checkLightSide(enumfacing.opposite());
}
this.setSkylightUpdated();

View File

@@ -0,0 +1,493 @@
package io.akarin.server.mixin.optimization;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import org.apache.commons.lang3.ArrayUtils;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import net.minecraft.server.BaseBlockPosition;
import net.minecraft.server.Block;
import net.minecraft.server.BlockDiodeAbstract;
import net.minecraft.server.BlockObserver;
import net.minecraft.server.BlockPiston;
import net.minecraft.server.BlockPosition;
import net.minecraft.server.BlockRedstoneComparator;
import net.minecraft.server.BlockRedstoneTorch;
import net.minecraft.server.BlockRedstoneWire;
import net.minecraft.server.BlockRepeater;
import net.minecraft.server.Blocks;
import net.minecraft.server.EnumDirection;
import net.minecraft.server.IBlockAccess;
import net.minecraft.server.IBlockData;
import net.minecraft.server.Material;
import net.minecraft.server.World;
@Mixin(value = BlockRedstoneWire.class, remap = false)
public abstract class PandaRedstoneWire extends Block {
protected PandaRedstoneWire(Material material) {
super(material);
}
/** Positions that need to be turned off **/
private List<BlockPosition> turnOff = Lists.newArrayList();
/** Positions that need to be checked to be turned on **/
private List<BlockPosition> turnOn = Lists.newArrayList();
/** Positions of wire that was updated already (Ordering determines update order and is therefore required!) **/
private final Set<BlockPosition> updatedRedstoneWire = Sets.newLinkedHashSet();
/** Ordered arrays of the facings; Needed for the update order.
* I went with a vertical-first order here, but vertical last would work to.
* However it should be avoided to update the vertical axis between the horizontal ones as this would cause unneeded directional behavior. **/
private static final EnumDirection[] facingsHorizontal = {EnumDirection.WEST, EnumDirection.EAST, EnumDirection.NORTH, EnumDirection.SOUTH};
private static final EnumDirection[] facingsVertical = {EnumDirection.DOWN, EnumDirection.UP};
private static final EnumDirection[] facings = ArrayUtils.addAll(facingsVertical, facingsHorizontal);
/** Offsets for all surrounding blocks that need to receive updates **/
private static final BaseBlockPosition[] surroundingBlocksOffset;
static {
Set<BaseBlockPosition> set = Sets.newLinkedHashSet();
for (EnumDirection facing : facings) {
set.add(facing.getDirectionPosition());
}
for (EnumDirection facing1 : facings) {
BaseBlockPosition v1 = facing1.getDirectionPosition();
for (EnumDirection facing2 : facings) {
BaseBlockPosition v2 = facing2.getDirectionPosition();
set.add(new BaseBlockPosition(v1.getX() + v2.getX(), v1.getY() + v2.getY(), v1.getZ() + v2.getZ()));
}
}
set.remove(BaseBlockPosition.ZERO);
surroundingBlocksOffset = set.toArray(new BaseBlockPosition[set.size()]);
}
@Shadow(aliases = "g") private boolean canProvidePower;
@Shadow public abstract int getPower(World world, BlockPosition pos, int strength);
@Shadow(aliases = "b") public abstract boolean isPowerSourceAt(IBlockAccess worldIn, BlockPosition pos, EnumDirection side);
@Inject(method = "e", at = @At("HEAD"), cancellable = true)
private void onUpdateSurroundingRedstone(World worldIn, BlockPosition pos, IBlockData state, CallbackInfoReturnable<IBlockData> cir) {
this.updateSurroundingRedstone(worldIn, pos);
cir.setReturnValue(state);
}
@Inject(method = "a*", at = @At("HEAD"), cancellable = true)
private void onCalculateCurrentChanges(World worldIn, BlockPosition pos1, BlockPosition pos2, IBlockData state, CallbackInfoReturnable<IBlockData> cir) {
this.calculateCurrentChanges(worldIn, pos1);
cir.setReturnValue(state);
}
/**
* Recalculates all surrounding wires and causes all needed updates
*
* @author panda
*
* @param world World
* @param pos Position that needs updating
*/
private void updateSurroundingRedstone(World world, BlockPosition pos) {
// Recalculate the connected wires
this.calculateCurrentChanges(world, pos);
// Set to collect all the updates, to only execute them once. Ordering required.
Set<BlockPosition> blocksNeedingUpdate = Sets.newLinkedHashSet();
// Add the needed updates
for (BlockPosition posi : this.updatedRedstoneWire) {
this.addBlocksNeedingUpdate(world, posi, blocksNeedingUpdate);
}
// Add all other updates to keep known behaviors
// They are added in a backwards order because it preserves a commonly used behavior with the update order
Iterator<BlockPosition> it = Lists.newLinkedList(this.updatedRedstoneWire).descendingIterator();
while (it.hasNext()) {
this.addAllSurroundingBlocks(it.next(), blocksNeedingUpdate);
}
// Remove updates on the wires as they just were updated
blocksNeedingUpdate.removeAll(this.updatedRedstoneWire);
/*
* Avoid unnecessary updates on the just updated wires A huge scale test
* showed about 40% more ticks per second It's probably less in normal
* usage but likely still worth it
*/
this.updatedRedstoneWire.clear();
// Execute updates
for (BlockPosition posi : blocksNeedingUpdate) {
world.applyPhysics(posi, (BlockRedstoneWire) (Object) this, false);
}
}
/**
* Turns on or off all connected wires
*
* @param worldIn World
* @param position Position of the wire that received the update
*/
private void calculateCurrentChanges(World worldIn, BlockPosition position) {
// Turn off all connected wires first if needed
if (worldIn.getType(position).getBlock() == (BlockRedstoneWire) (Object) this) {
turnOff.add(position);
} else {
// In case this wire was removed, check the surrounding wires
this.checkSurroundingWires(worldIn, position);
}
while (!turnOff.isEmpty()) {
BlockPosition pos = turnOff.remove(0);
IBlockData state = worldIn.getType(pos);
int oldPower = state.get(BlockRedstoneWire.POWER).intValue();
this.canProvidePower = false;
int blockPower = worldIn.z(pos); // PAIL: isBlockIndirectlyGettingPowered
this.canProvidePower = true;
int wirePower = this.getSurroundingWirePower(worldIn, pos);
// Lower the strength as it moved a block
wirePower--;
int newPower = Math.max(blockPower, wirePower);
// Power lowered?
if (newPower < oldPower) {
// If it's still powered by a direct source (but weaker) mark for turn on
if (blockPower > 0 && !this.turnOn.contains(pos)) {
this.turnOn.add(pos);
}
// Set all the way to off for now, because wires that were powered by this need to update first
setWireState(worldIn, pos, state, 0);
// Power rose?
} else if (newPower > oldPower) {
// Set new Power
this.setWireState(worldIn, pos, state, newPower);
}
// Check if surrounding wires need to change based on the current/new state and add them to the lists
this.checkSurroundingWires(worldIn, pos);
}
// Now all needed wires are turned off. Time to turn them on again if there is a power source.
while (!this.turnOn.isEmpty()) {
BlockPosition pos = this.turnOn.remove(0);
IBlockData state = worldIn.getType(pos);
int oldPower = state.get(BlockRedstoneWire.POWER).intValue();
this.canProvidePower = false;
int blockPower = worldIn.z(pos); // PAIL: isBlockIndirectlyGettingPowered
this.canProvidePower = true;
int wirePower = this.getSurroundingWirePower(worldIn, pos);
// Lower the strength as it moved a block
wirePower--;
int newPower = Math.max(blockPower, wirePower);
if (newPower > oldPower) {
setWireState(worldIn, pos, state, newPower);
} else if (newPower < oldPower) {
// Add warning
}
// Check if surrounding wires need to change based on the current/new state and add them to the lists
this.checkSurroundingWires(worldIn, pos);
}
this.turnOff.clear();
this.turnOn.clear();
}
/**
* Checks if an wire needs to be marked for update depending on the power next to it
*
* @author panda
*
* @param worldIn World
* @param pos Position of the wire that might need to change
* @param otherPower Power of the wire next to it
*/
private void addWireToList(World worldIn, BlockPosition pos, int otherPower) {
IBlockData state = worldIn.getType(pos);
if (state.getBlock() == (BlockRedstoneWire) (Object) this) {
int power = state.get(BlockRedstoneWire.POWER).intValue();
// Could get powered stronger by the neighbor?
if (power < (otherPower - 1) && !this.turnOn.contains(pos)) {
// Mark for turn on check.
this.turnOn.add(pos);
}
// Should have powered the neighbor? Probably was powered by it and is in turn off phase.
if (power > otherPower && !this.turnOff.contains(pos)) {
// Mark for turn off check.
this.turnOff.add(pos);
}
}
}
/**
* Checks if the wires around need to get updated depending on this wires state.
* Checks all wires below before the same layer before on top to keep
* some more rotational symmetry around the y-axis.
*
* @author panda
*
* @param worldIn World
* @param pos Position of the wire
*/
private void checkSurroundingWires(World worldIn, BlockPosition pos) {
IBlockData state = worldIn.getType(pos);
int ownPower = 0;
if (state.getBlock() == (BlockRedstoneWire) (Object) this) {
ownPower = state.get(BlockRedstoneWire.POWER).intValue();
}
// Check wires on the same layer first as they appear closer to the wire
for (EnumDirection facing : facingsHorizontal) {
BlockPosition offsetPos = pos.shift(facing);
if (facing.getAxis().isHorizontal()) {
this.addWireToList(worldIn, offsetPos, ownPower);
}
}
for (EnumDirection facingVertical : facingsVertical) {
BlockPosition offsetPos = pos.shift(facingVertical);
boolean solidBlock = worldIn.getType(offsetPos).k(); // PAIL: isBlockNormalCube
for (EnumDirection facingHorizontal : facingsHorizontal) {
// wire can travel upwards if the block on top doesn't cut the wire (is non-solid)
// it can travel down if the block below is solid and the block "diagonal" doesn't cut off the wire (is non-solid)
if ((facingVertical == EnumDirection.UP && !solidBlock) || (facingVertical == EnumDirection.DOWN && solidBlock && !worldIn.getType(offsetPos.shift(facingHorizontal)).k())) { // PAIL: isBlockNormalCube
this.addWireToList(worldIn, offsetPos.shift(facingHorizontal), ownPower);
}
}
}
}
/**
* Gets the maximum power of the surrounding wires
*
* @author panda
*
* @param worldIn World
* @param pos Position of the asking wire
* @return The maximum power of the wires that could power the wire at pos
*/
private int getSurroundingWirePower(World worldIn, BlockPosition pos) {
int wirePower = 0;
for (EnumDirection enumfacing : EnumDirection.EnumDirectionLimit.HORIZONTAL) {
BlockPosition offsetPos = pos.shift(enumfacing);
// Wires on the same layer
wirePower = this.getPower(worldIn, offsetPos, wirePower);
// Block below the wire need to be solid (Upwards diode of slabs/stairs/glowstone) and no block should cut the wire
if(worldIn.getType(offsetPos).l() && !worldIn.getType(pos.up()).l()) { // PAIL: isNormalCube
wirePower = this.getPower(worldIn, offsetPos.up(), wirePower);
// Only get from power below if no block is cutting the wire
} else if (!worldIn.getType(offsetPos).l()) { // PAIL: isNormalCube
wirePower = this.getPower(worldIn, offsetPos.down(), wirePower);
}
}
return wirePower;
}
/**
* Adds all blocks that need to receive an update from a redstone change in this position.
* This means only blocks that actually could change.
*
* @author panda
*
* @param worldIn World
* @param pos Position of the wire
* @param set Set to add the update positions too
*/
private void addBlocksNeedingUpdate(World worldIn, BlockPosition pos, Set<BlockPosition> set) {
List<EnumDirection> connectedSides = this.getSidesToPower(worldIn, pos);
// Add the blocks next to the wire first (closest first order)
for (EnumDirection facing : facings) {
BlockPosition offsetPos = pos.shift(facing);
// canConnectTo() is not the nicest solution here as it returns true for e.g. the front of a repeater
// canBlockBePowereFromSide catches these cases
if (!connectedSides.contains(facing.opposite()) && facing != EnumDirection.DOWN
&& (!facing.getAxis().isHorizontal() || canConnectToBlock(worldIn.getType(offsetPos), facing))) continue;
if (this.canBlockBePoweredFromSide(worldIn.getType(offsetPos), facing, true))
set.add(offsetPos);
}
// Later add blocks around the surrounding blocks that get powered
for (EnumDirection facing : facings) {
BlockPosition offsetPos = pos.shift(facing);
if (!connectedSides.contains(facing.opposite()) && facing != EnumDirection.DOWN || !worldIn.getType(offsetPos).l()) continue; // PAIL: isNormalCube
for (EnumDirection facing1 : facings) {
if (this.canBlockBePoweredFromSide(worldIn.getType(offsetPos.shift(facing1)), facing1, false))
set.add(offsetPos.shift(facing1));
}
}
}
/**
* Checks if a block can get powered from a side.
* This behavior would better be implemented per block type as follows:
* - return false as default. (blocks that are not affected by redstone don't need to be updated, it doesn't really hurt if they are either)
* - return true for all blocks that can get powered from all side and change based on it (doors, fence gates, trap doors, note blocks, lamps, dropper, hopper, TNT, rails, possibly more)
* - implement own logic for pistons, repeaters, comparators and redstone torches
* The current implementation was chosen to keep everything in one class.
*
* Why is this extra check needed?
* 1. It makes sure that many old behaviors still work (QC + Pistons).
* 2. It prevents updates from "jumping".
* Or rather it prevents this wire to update a block that would get powered by the next one of the same line.
* This is to prefer as it makes understanding the update order of the wire really easy. The signal "travels" from the power source.
*
* @author panda
*
* @param state State of the block
* @param side Side from which it gets powered
* @param isWire True if it's powered by a wire directly, False if through a block
* @return True if the block can change based on the power level it gets on the given side, false otherwise
*/
private boolean canBlockBePoweredFromSide(IBlockData state, EnumDirection side, boolean isWire) {
if (state.getBlock() instanceof BlockPiston && state.get(BlockPiston.FACING) == side.opposite()) {
return false;
}
if (state.getBlock() instanceof BlockDiodeAbstract && state.get(BlockDiodeAbstract.FACING) != side.opposite()) {
if (isWire && state.getBlock() instanceof BlockRedstoneComparator
&& state.get(BlockRedstoneComparator.FACING).k() != side.getAxis() && side.getAxis().isHorizontal()) {
return true;
}
return false;
}
if (state.getBlock() instanceof BlockRedstoneTorch) {
if (isWire || state.get(BlockRedstoneTorch.FACING) != side) {
return false;
}
}
return true;
}
/**
* Creates a list of all horizontal sides that can get powered by a wire.
* The list is ordered the same as the facingsHorizontal.
*
* @param worldIn World
* @param pos Position of the wire
* @return List of all facings that can get powered by this wire
*/
private List<EnumDirection> getSidesToPower(World worldIn, BlockPosition pos) {
List<EnumDirection> retval = Lists.newArrayList();
for (EnumDirection facing : facingsHorizontal) {
if (isPowerSourceAt(worldIn, pos, facing))
retval.add(facing);
}
if (retval.isEmpty()) return Lists.newArrayList(facingsHorizontal);
boolean northsouth = retval.contains(EnumDirection.NORTH) || retval.contains(EnumDirection.SOUTH);
boolean eastwest = retval.contains(EnumDirection.EAST) || retval.contains(EnumDirection.WEST);
if (northsouth) {
retval.remove(EnumDirection.EAST);
retval.remove(EnumDirection.WEST);
}
if (eastwest) {
retval.remove(EnumDirection.NORTH);
retval.remove(EnumDirection.SOUTH);
}
return retval;
}
/**
* Adds all surrounding positions to a set.
* This is the neighbor blocks, as well as their neighbors
*
* @param pos
* @param set
*/
private void addAllSurroundingBlocks(BlockPosition pos, Set<BlockPosition> set) {
for (BaseBlockPosition vect : surroundingBlocksOffset) {
set.add(pos.add(vect));
}
}
/**
* Sets the block state of a wire with a new power level and marks for updates
*
* @author panda
*
* @param worldIn World
* @param pos Position at which the state needs to be set
* @param state Old state
* @param power Power it should get set to
*/
private void setWireState(World worldIn, BlockPosition pos, IBlockData state, int power) {
state = state.set(BlockRedstoneWire.POWER, Integer.valueOf(power));
worldIn.setTypeAndData(pos, state, 2);
updatedRedstoneWire.add(pos);
}
/**
* @author panda
* @reason Uses local surrounding block offset list for notifications.
*
* @param world The world
* @param pos The position
* @param state The block state
*/
@Override
@Overwrite
public void onPlace(World world, BlockPosition pos, IBlockData state) {
this.updateSurroundingRedstone(world, pos);
for (BaseBlockPosition vec : surroundingBlocksOffset) {
world.applyPhysics(pos.add(vec), this, false);
}
}
/**
* @author panda
* @reason Uses local surrounding block offset list for notifications.
*
* @param world The world
* @param pos The position
*/
@Override
@Overwrite
public void remove(World world, BlockPosition pos, IBlockData state) {
super.remove(world, pos, state);
this.updateSurroundingRedstone(world, pos);
for (BaseBlockPosition vec : surroundingBlocksOffset) {
world.applyPhysics(pos.add(vec), this, false);
}
}
/**
* @author panda
* @reason Changed to use getSidesToPower() to avoid duplicate implementation.
*
* @param blockState The block state
* @param blockAccess The block access
* @param pos The position
* @param side The side
*/
@Override
@Overwrite
public int b(IBlockData blockState, IBlockAccess blockAccess, BlockPosition pos, EnumDirection side) { // PAIL: getWeakPower
if (!this.canProvidePower) {
return 0;
} else {
if (side == EnumDirection.UP || this.getSidesToPower((World) blockAccess, pos).contains(side)) {
return blockState.get(BlockRedstoneWire.POWER).intValue();
} else {
return 0;
}
}
}
// Forge adds 2 params to canConnectTo so we need to copy method in order to access it
private static boolean canConnectToBlock(IBlockData blockState, @Nullable EnumDirection side) {
Block block = blockState.getBlock();
if (block == Blocks.REDSTONE_WIRE) {
return true;
} else if (Blocks.UNPOWERED_REPEATER.D(blockState)) { // PAIL: isSameDiode
EnumDirection enumdirection1 = blockState.get(BlockRepeater.FACING);
return enumdirection1 == side || enumdirection1.opposite() == side;
} else if (Blocks.dk == blockState.getBlock()) {
return side == blockState.get(BlockObserver.FACING); // PAIL: OBSERVER
} else {
return blockState.m() && side != null; // PAIL: canProvidePower
}
}
}

View File

@@ -0,0 +1,471 @@
package net.minecraft.server;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Lists;
import java.util.Iterator;
import java.util.List;
import javax.annotation.concurrent.Immutable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* <b>Akarin Changes Note</b><br>
* <br>
* 1) Add OBFHELPER<br>
* @author cakoyo
*/
@Immutable
public class BlockPosition extends BaseBlockPosition {
private static final Logger b = LogManager.getLogger();
public static final BlockPosition ZERO = new BlockPosition(0, 0, 0);
private static final int c = 1 + MathHelper.e(MathHelper.c(30000000));
private static final int d = BlockPosition.c;
private static final int f = 64 - BlockPosition.c - BlockPosition.d;
private static final int g = 0 + BlockPosition.d;
private static final int h = BlockPosition.g + BlockPosition.f;
private static final long i = (1L << BlockPosition.c) - 1L;
private static final long j = (1L << BlockPosition.f) - 1L;
private static final long k = (1L << BlockPosition.d) - 1L;
public BlockPosition(int i, int j, int k) {
super(i, j, k);
}
public BlockPosition(double d0, double d1, double d2) {
super(d0, d1, d2);
}
public BlockPosition(Entity entity) {
this(entity.locX, entity.locY, entity.locZ);
}
public BlockPosition(Vec3D vec3d) {
this(vec3d.x, vec3d.y, vec3d.z);
}
public BlockPosition(BaseBlockPosition baseblockposition) {
this(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ());
}
public BlockPosition add(double x, double y, double z) { return this.a(x, y, z); } // Paper - OBFHELPER
public BlockPosition a(double d0, double d1, double d2) {
return d0 == 0.0D && d1 == 0.0D && d2 == 0.0D ? this : new BlockPosition(this.getX() + d0, this.getY() + d1, this.getZ() + d2);
}
public BlockPosition a(int i, int j, int k) {
return i == 0 && j == 0 && k == 0 ? this : new BlockPosition(this.getX() + i, this.getY() + j, this.getZ() + k);
}
public BlockPosition add(BaseBlockPosition baseblockposition) { return this.a(baseblockposition); } // Akarin - OBFHELPER
public BlockPosition a(BaseBlockPosition baseblockposition) {
return this.a(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ());
}
public BlockPosition b(BaseBlockPosition baseblockposition) {
return this.a(-baseblockposition.getX(), -baseblockposition.getY(), -baseblockposition.getZ());
}
public BlockPosition up() {
return this.up(1);
}
public BlockPosition up(int i) {
return this.shift(EnumDirection.UP, i);
}
public BlockPosition down() {
return this.down(1);
}
public BlockPosition down(int i) {
return this.shift(EnumDirection.DOWN, i);
}
public BlockPosition north() {
return this.north(1);
}
public BlockPosition north(int i) {
return this.shift(EnumDirection.NORTH, i);
}
public BlockPosition south() {
return this.south(1);
}
public BlockPosition south(int i) {
return this.shift(EnumDirection.SOUTH, i);
}
public BlockPosition west() {
return this.west(1);
}
public BlockPosition west(int i) {
return this.shift(EnumDirection.WEST, i);
}
public BlockPosition east() {
return this.east(1);
}
public BlockPosition east(int i) {
return this.shift(EnumDirection.EAST, i);
}
public BlockPosition shift(EnumDirection enumdirection) {
return this.shift(enumdirection, 1);
}
public BlockPosition shift(EnumDirection enumdirection, int i) {
return i == 0 ? this : new BlockPosition(this.getX() + enumdirection.getAdjacentX() * i, this.getY() + enumdirection.getAdjacentY() * i, this.getZ() + enumdirection.getAdjacentZ() * i);
}
public BlockPosition a(EnumBlockRotation enumblockrotation) {
switch (enumblockrotation) {
case NONE:
default:
return this;
case CLOCKWISE_90:
return new BlockPosition(-this.getZ(), this.getY(), this.getX());
case CLOCKWISE_180:
return new BlockPosition(-this.getX(), this.getY(), -this.getZ());
case COUNTERCLOCKWISE_90:
return new BlockPosition(this.getZ(), this.getY(), -this.getX());
}
}
public BlockPosition c(BaseBlockPosition baseblockposition) {
return new BlockPosition(this.getY() * baseblockposition.getZ() - this.getZ() * baseblockposition.getY(), this.getZ() * baseblockposition.getX() - this.getX() * baseblockposition.getZ(), this.getX() * baseblockposition.getY() - this.getY() * baseblockposition.getX());
}
public long asLong() {
return (this.getX() & BlockPosition.i) << BlockPosition.h | (this.getY() & BlockPosition.j) << BlockPosition.g | (this.getZ() & BlockPosition.k) << 0;
}
public static BlockPosition fromLong(long i) {
int j = (int) (i << 64 - BlockPosition.h - BlockPosition.c >> 64 - BlockPosition.c);
int k = (int) (i << 64 - BlockPosition.g - BlockPosition.f >> 64 - BlockPosition.f);
int l = (int) (i << 64 - BlockPosition.d >> 64 - BlockPosition.d);
return new BlockPosition(j, k, l);
}
public static Iterable<BlockPosition> a(BlockPosition blockposition, BlockPosition blockposition1) {
return a(Math.min(blockposition.getX(), blockposition1.getX()), Math.min(blockposition.getY(), blockposition1.getY()), Math.min(blockposition.getZ(), blockposition1.getZ()), Math.max(blockposition.getX(), blockposition1.getX()), Math.max(blockposition.getY(), blockposition1.getY()), Math.max(blockposition.getZ(), blockposition1.getZ()));
}
public static Iterable<BlockPosition> a(final int i, final int j, final int k, final int l, final int i1, final int j1) {
return new Iterable() {
@Override
public Iterator<BlockPosition> iterator() {
return new AbstractIterator() {
private boolean b = true;
private int c;
private int d;
private int e;
protected BlockPosition a() {
if (this.b) {
this.b = false;
this.c = i;
this.d = j;
this.e = k;
return new BlockPosition(i, j, k);
} else if (this.c == l && this.d == i1 && this.e == j1) {
return (BlockPosition) this.endOfData();
} else {
if (this.c < l) {
++this.c;
} else if (this.d < i1) {
this.c = i;
++this.d;
} else if (this.e < j1) {
this.c = i;
this.d = j;
++this.e;
}
return new BlockPosition(this.c, this.d, this.e);
}
}
@Override
protected Object computeNext() {
return this.a();
}
};
}
};
}
public BlockPosition h() {
return this;
}
public static Iterable<BlockPosition.MutableBlockPosition> b(BlockPosition blockposition, BlockPosition blockposition1) {
return b(Math.min(blockposition.getX(), blockposition1.getX()), Math.min(blockposition.getY(), blockposition1.getY()), Math.min(blockposition.getZ(), blockposition1.getZ()), Math.max(blockposition.getX(), blockposition1.getX()), Math.max(blockposition.getY(), blockposition1.getY()), Math.max(blockposition.getZ(), blockposition1.getZ()));
}
public static Iterable<BlockPosition.MutableBlockPosition> b(final int i, final int j, final int k, final int l, final int i1, final int j1) {
return new Iterable() {
@Override
public Iterator<BlockPosition.MutableBlockPosition> iterator() {
return new AbstractIterator() {
private BlockPosition.MutableBlockPosition b;
protected BlockPosition.MutableBlockPosition a() {
if (this.b == null) {
this.b = new BlockPosition.MutableBlockPosition(i, j, k);
return this.b;
// Paper start - b, c, d, refer to x, y, z, and as such, a, b, c of BaseBlockPosition
} else if (((BaseBlockPosition)this.b).a == l && ((BaseBlockPosition)this.b).b == i1 && ((BaseBlockPosition)this.b).c == j1) {
return (BlockPosition.MutableBlockPosition) this.endOfData();
} else {
if (((BaseBlockPosition) this.b).a < l) {
++((BaseBlockPosition) this.b).a;
} else if (((BaseBlockPosition) this.b).b < i1) {
((BaseBlockPosition) this.b).a = i;
++((BaseBlockPosition) this.b).b;
} else if (((BaseBlockPosition) this.b).c < j1) {
((BaseBlockPosition) this.b).a = i;
((BaseBlockPosition) this.b).b = j;
++((BaseBlockPosition) this.b).c;
}
// Paper end
return this.b;
}
}
@Override
protected Object computeNext() {
return this.a();
}
};
}
};
}
@Override
public BaseBlockPosition d(BaseBlockPosition baseblockposition) {
return this.c(baseblockposition);
}
public static final class PooledBlockPosition extends BlockPosition.MutableBlockPosition {
private boolean f;
private static final List<BlockPosition.PooledBlockPosition> g = Lists.newArrayList();
private PooledBlockPosition(int i, int j, int k) {
super(i, j, k);
}
public static BlockPosition.PooledBlockPosition aquire() { return s(); } // Paper - OBFHELPER
public static BlockPosition.PooledBlockPosition s() {
return e(0, 0, 0);
}
public static BlockPosition.PooledBlockPosition d(double d0, double d1, double d2) {
return e(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2));
}
public static BlockPosition.PooledBlockPosition e(int i, int j, int k) {
List list = BlockPosition.PooledBlockPosition.g;
synchronized (BlockPosition.PooledBlockPosition.g) {
if (!BlockPosition.PooledBlockPosition.g.isEmpty()) {
BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.g.remove(BlockPosition.PooledBlockPosition.g.size() - 1);
if (blockposition_pooledblockposition != null && blockposition_pooledblockposition.f) {
blockposition_pooledblockposition.f = false;
blockposition_pooledblockposition.f(i, j, k);
return blockposition_pooledblockposition;
}
}
}
return new BlockPosition.PooledBlockPosition(i, j, k);
}
public void free() { t(); } // Paper - OBFHELPER
public void t() {
List list = BlockPosition.PooledBlockPosition.g;
synchronized (BlockPosition.PooledBlockPosition.g) {
if (BlockPosition.PooledBlockPosition.g.size() < 100) {
BlockPosition.PooledBlockPosition.g.add(this);
}
this.f = true;
}
}
public BlockPosition.PooledBlockPosition f(int i, int j, int k) {
if (this.f) {
BlockPosition.b.error("PooledMutableBlockPosition modified after it was released.", new Throwable());
this.f = false;
}
return (BlockPosition.PooledBlockPosition) super.c(i, j, k);
}
public BlockPosition.PooledBlockPosition e(double d0, double d1, double d2) {
return (BlockPosition.PooledBlockPosition) super.c(d0, d1, d2);
}
public BlockPosition.PooledBlockPosition j(BaseBlockPosition baseblockposition) {
return (BlockPosition.PooledBlockPosition) super.g(baseblockposition);
}
public BlockPosition.PooledBlockPosition d(EnumDirection enumdirection) {
return (BlockPosition.PooledBlockPosition) super.c(enumdirection);
}
public BlockPosition.PooledBlockPosition d(EnumDirection enumdirection, int i) {
return (BlockPosition.PooledBlockPosition) super.c(enumdirection, i);
}
@Override
public BlockPosition.MutableBlockPosition c(EnumDirection enumdirection, int i) {
return this.d(enumdirection, i);
}
@Override
public BlockPosition.MutableBlockPosition c(EnumDirection enumdirection) {
return this.d(enumdirection);
}
@Override
public BlockPosition.MutableBlockPosition g(BaseBlockPosition baseblockposition) {
return this.j(baseblockposition);
}
@Override
public BlockPosition.MutableBlockPosition c(double d0, double d1, double d2) {
return this.e(d0, d1, d2);
}
@Override
public BlockPosition.MutableBlockPosition c(int i, int j, int k) {
return this.f(i, j, k);
}
}
public static class MutableBlockPosition extends BlockPosition {
// Paper start - Remove variables
/*
protected int b;
protected int c;
protected int d;
// Paper start
@Override
public boolean isValidLocation() {
return b >= -30000000 && d >= -30000000 && b < 30000000 && d < 30000000 && c >= 0 && c < 256;
}
@Override
public boolean isInvalidYLocation() {
return c < 0 || c >= 256;
}
*/
// Paper end
public MutableBlockPosition() {
this(0, 0, 0);
}
public MutableBlockPosition(BlockPosition blockposition) {
this(blockposition.getX(), blockposition.getY(), blockposition.getZ());
}
public MutableBlockPosition(int i, int j, int k) {
super(0, 0, 0);
// Paper start - Modify base position variables
((BaseBlockPosition) this).a = i;
((BaseBlockPosition) this).b = j;
((BaseBlockPosition) this).c = k;
// Paper end
}
@Override
public BlockPosition a(double d0, double d1, double d2) {
return super.a(d0, d1, d2).h();
}
@Override
public BlockPosition a(int i, int j, int k) {
return super.a(i, j, k).h();
}
@Override
public BlockPosition shift(EnumDirection enumdirection, int i) {
return super.shift(enumdirection, i).h();
}
@Override
public BlockPosition a(EnumBlockRotation enumblockrotation) {
return super.a(enumblockrotation).h();
}
// Paper start - Use superclass methods
/*
public int getX() {
return this.b;
}
public int getY() {
return this.c;
}
public int getZ() {
return this.d;
}
*/
// Paper end
public void setValues(int x, int y, int z) { c(x, y, z); } // Paper - OBFHELPER
public BlockPosition.MutableBlockPosition c(int i, int j, int k) {
// Paper start - Modify base position variables
((BaseBlockPosition) this).a = i;
((BaseBlockPosition) this).b = j;
((BaseBlockPosition) this).c = k;
// Paper end
return this;
}
public BlockPosition.MutableBlockPosition c(double d0, double d1, double d2) {
return this.c(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2));
}
public BlockPosition.MutableBlockPosition g(BaseBlockPosition baseblockposition) {
return this.c(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ());
}
public BlockPosition.MutableBlockPosition c(EnumDirection enumdirection) {
return this.c(enumdirection, 1);
}
public BlockPosition.MutableBlockPosition c(EnumDirection enumdirection, int i) {
return this.c(this.getX() + enumdirection.getAdjacentX() * i, this.getY() + enumdirection.getAdjacentY() * i, this.getZ() + enumdirection.getAdjacentZ() * i); // Paper - USE THE BLEEPING GETTERS
}
public void p(int i) {
((BaseBlockPosition) this).b = i; // Paper - Modify base variable
}
@Override
public BlockPosition h() {
return new BlockPosition(this);
}
@Override
public BaseBlockPosition d(BaseBlockPosition baseblockposition) {
return super.c(baseblockposition);
}
}
}

View File

@@ -22,7 +22,7 @@ import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper
* <b>Akarin Changes Note</b><br>
* <br>
* 1) Add volatile to fields<br>
* 2) Expose private members<br>
* 2) Add OBFHELPER<br>
* @author cakoyo
*/
public class Chunk {
@@ -1305,7 +1305,8 @@ public class Chunk {
this.h(false);
}
public void a(EnumDirection enumdirection) { // Akarin - private -> public - PAIL: checkLightSide
public void checkLightSide(EnumDirection direction) { a(direction); } // Akarin - OBFHELPER
private void a(EnumDirection enumdirection) {
if (this.done) {
int i;

View File

@@ -0,0 +1,319 @@
package net.minecraft.server;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import javax.annotation.Nullable;
/**
* <b>Akarin Changes Note</b><br>
* <br>
* 1) Add public obfhelper<br>
* @author cakoyo
*/
public enum EnumDirection implements INamable {
DOWN(0, 1, -1, "down", EnumDirection.EnumAxisDirection.NEGATIVE, EnumDirection.EnumAxis.Y, new BaseBlockPosition(0, -1, 0)), UP(1, 0, -1, "up", EnumDirection.EnumAxisDirection.POSITIVE, EnumDirection.EnumAxis.Y, new BaseBlockPosition(0, 1, 0)), NORTH(2, 3, 2, "north", EnumDirection.EnumAxisDirection.NEGATIVE, EnumDirection.EnumAxis.Z, new BaseBlockPosition(0, 0, -1)), SOUTH(3, 2, 0, "south", EnumDirection.EnumAxisDirection.POSITIVE, EnumDirection.EnumAxis.Z, new BaseBlockPosition(0, 0, 1)), WEST(4, 5, 1, "west", EnumDirection.EnumAxisDirection.NEGATIVE, EnumDirection.EnumAxis.X, new BaseBlockPosition(-1, 0, 0)), EAST(5, 4, 3, "east", EnumDirection.EnumAxisDirection.POSITIVE, EnumDirection.EnumAxis.X, new BaseBlockPosition(1, 0, 0));
private final int g;
private final int h;
private final int i;
private final String j;
private final EnumDirection.EnumAxis k;
private final EnumDirection.EnumAxisDirection l;
private final BaseBlockPosition m; public BaseBlockPosition getDirectionPosition() { return m; } // Akarin - OBFHELPER
private static final EnumDirection[] n = new EnumDirection[6];
private static final EnumDirection[] o = new EnumDirection[4];
private static final Map<String, EnumDirection> p = Maps.newHashMap();
private EnumDirection(int i, int j, int k, String s, EnumDirection.EnumAxisDirection enumdirection_enumaxisdirection, EnumDirection.EnumAxis enumdirection_enumaxis, BaseBlockPosition baseblockposition) {
this.g = i;
this.i = k;
this.h = j;
this.j = s;
this.k = enumdirection_enumaxis;
this.l = enumdirection_enumaxisdirection;
this.m = baseblockposition;
}
public int a() {
return this.g;
}
public int get2DRotationValue() {
return this.i;
}
public EnumDirection.EnumAxisDirection c() {
return this.l;
}
public EnumDirection opposite() {
return fromType1(this.h);
}
public EnumDirection e() {
switch (this) {
case NORTH:
return EnumDirection.EAST;
case EAST:
return EnumDirection.SOUTH;
case SOUTH:
return EnumDirection.WEST;
case WEST:
return EnumDirection.NORTH;
default:
throw new IllegalStateException("Unable to get Y-rotated facing of " + this);
}
}
public EnumDirection f() {
switch (this) {
case NORTH:
return EnumDirection.WEST;
case EAST:
return EnumDirection.NORTH;
case SOUTH:
return EnumDirection.EAST;
case WEST:
return EnumDirection.SOUTH;
default:
throw new IllegalStateException("Unable to get CCW facing of " + this);
}
}
public int getAdjacentX() {
return this.k == EnumDirection.EnumAxis.X ? this.l.a() : 0;
}
public int getAdjacentY() {
return this.k == EnumDirection.EnumAxis.Y ? this.l.a() : 0;
}
public int getAdjacentZ() {
return this.k == EnumDirection.EnumAxis.Z ? this.l.a() : 0;
}
public String j() {
return this.j;
}
public EnumDirection.EnumAxis getAxis() { return k(); } // Akarin - OBFHELPER
public EnumDirection.EnumAxis k() {
return this.k;
}
public static EnumDirection fromType1(int i) {
return EnumDirection.n[MathHelper.a(i % EnumDirection.n.length)];
}
public static EnumDirection fromType2(int i) {
return EnumDirection.o[MathHelper.a(i % EnumDirection.o.length)];
}
public static EnumDirection fromAngle(double d0) {
return fromType2(MathHelper.floor(d0 / 90.0D + 0.5D) & 3);
}
public float l() {
return (this.i & 3) * 90;
}
public static EnumDirection a(Random random) {
return values()[random.nextInt(values().length)];
}
@Override
public String toString() {
return this.j;
}
@Override
public String getName() {
return this.j;
}
public static EnumDirection a(EnumDirection.EnumAxisDirection enumdirection_enumaxisdirection, EnumDirection.EnumAxis enumdirection_enumaxis) {
EnumDirection[] aenumdirection = values();
int i = aenumdirection.length;
for (int j = 0; j < i; ++j) {
EnumDirection enumdirection = aenumdirection[j];
if (enumdirection.c() == enumdirection_enumaxisdirection && enumdirection.k() == enumdirection_enumaxis) {
return enumdirection;
}
}
throw new IllegalArgumentException("No such direction: " + enumdirection_enumaxisdirection + " " + enumdirection_enumaxis);
}
public static EnumDirection a(BlockPosition blockposition, EntityLiving entityliving) {
if (Math.abs(entityliving.locX - (blockposition.getX() + 0.5F)) < 2.0D && Math.abs(entityliving.locZ - (blockposition.getZ() + 0.5F)) < 2.0D) {
double d0 = entityliving.locY + entityliving.getHeadHeight();
if (d0 - blockposition.getY() > 2.0D) {
return EnumDirection.UP;
}
if (blockposition.getY() - d0 > 0.0D) {
return EnumDirection.DOWN;
}
}
return entityliving.getDirection().opposite();
}
static {
EnumDirection[] aenumdirection = values();
int i = aenumdirection.length;
for (int j = 0; j < i; ++j) {
EnumDirection enumdirection = aenumdirection[j];
EnumDirection.n[enumdirection.g] = enumdirection;
if (enumdirection.k().c()) {
EnumDirection.o[enumdirection.i] = enumdirection;
}
EnumDirection.p.put(enumdirection.j().toLowerCase(Locale.ROOT), enumdirection);
}
}
public static enum EnumDirectionLimit implements Predicate<EnumDirection>, Iterable<EnumDirection> {
HORIZONTAL, VERTICAL;
private EnumDirectionLimit() {}
public EnumDirection[] a() {
switch (this) {
case HORIZONTAL:
return new EnumDirection[] { EnumDirection.NORTH, EnumDirection.EAST, EnumDirection.SOUTH, EnumDirection.WEST};
case VERTICAL:
return new EnumDirection[] { EnumDirection.UP, EnumDirection.DOWN};
default:
throw new Error("Someone\'s been tampering with the universe!");
}
}
public EnumDirection a(Random random) {
EnumDirection[] aenumdirection = this.a();
return aenumdirection[random.nextInt(aenumdirection.length)];
}
public boolean a(@Nullable EnumDirection enumdirection) {
return enumdirection != null && enumdirection.k().d() == this;
}
@Override
public Iterator<EnumDirection> iterator() {
return Iterators.forArray(this.a());
}
@Override
public boolean apply(@Nullable EnumDirection object) {
return this.a(object);
}
}
public static enum EnumAxisDirection {
POSITIVE(1, "Towards positive"), NEGATIVE(-1, "Towards negative");
private final int c;
private final String d;
private EnumAxisDirection(int i, String s) {
this.c = i;
this.d = s;
}
public int a() {
return this.c;
}
@Override
public String toString() {
return this.d;
}
}
public static enum EnumAxis implements Predicate<EnumDirection>, INamable {
X("x", EnumDirection.EnumDirectionLimit.HORIZONTAL), Y("y", EnumDirection.EnumDirectionLimit.VERTICAL), Z("z", EnumDirection.EnumDirectionLimit.HORIZONTAL);
private static final Map<String, EnumDirection.EnumAxis> d = Maps.newHashMap();
private final String e;
private final EnumDirection.EnumDirectionLimit f;
private EnumAxis(String s, EnumDirection.EnumDirectionLimit enumdirection_enumdirectionlimit) {
this.e = s;
this.f = enumdirection_enumdirectionlimit;
}
public String a() {
return this.e;
}
public boolean b() {
return this.f == EnumDirection.EnumDirectionLimit.VERTICAL;
}
public boolean isHorizontal() { return c(); } // Akarin - OBFHELPER
public boolean c() {
return this.f == EnumDirection.EnumDirectionLimit.HORIZONTAL;
}
@Override
public String toString() {
return this.e;
}
public boolean a(@Nullable EnumDirection enumdirection) {
return enumdirection != null && enumdirection.k() == this;
}
public EnumDirection.EnumDirectionLimit d() {
return this.f;
}
@Override
public String getName() {
return this.e;
}
@Override
public boolean apply(@Nullable EnumDirection object) {
return this.a(object);
}
static {
EnumDirection.EnumAxis[] aenumdirection_enumaxis = values();
int i = aenumdirection_enumaxis.length;
for (int j = 0; j < i; ++j) {
EnumDirection.EnumAxis enumdirection_enumaxis = aenumdirection_enumaxis[j];
EnumDirection.EnumAxis.d.put(enumdirection_enumaxis.a().toLowerCase(Locale.ROOT), enumdirection_enumaxis);
}
}
}
}

View File

@@ -39,6 +39,7 @@
"optimization.WeakBigTree",
"optimization.MixinPlayerChunk",
"optimization.PandaRedstoneWire",
"optimization.WeakEnchantmentManager",
"optimization.MixinEntityHorseAbstract",
"optimization.MixinEntityTameableAnimal",