[Edge] Panda wire port
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
471
sources/src/main/java/net/minecraft/server/BlockPosition.java
Normal file
471
sources/src/main/java/net/minecraft/server/BlockPosition.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
319
sources/src/main/java/net/minecraft/server/EnumDirection.java
Normal file
319
sources/src/main/java/net/minecraft/server/EnumDirection.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
"optimization.WeakBigTree",
|
||||
"optimization.MixinPlayerChunk",
|
||||
"optimization.PandaRedstoneWire",
|
||||
"optimization.WeakEnchantmentManager",
|
||||
"optimization.MixinEntityHorseAbstract",
|
||||
"optimization.MixinEntityTameableAnimal",
|
||||
|
||||
Reference in New Issue
Block a user