Moving to source sets

This commit is contained in:
Sebastian Hartte
2020-07-01 23:36:51 +02:00
parent f2e3d81fd7
commit 2642ced86b
2924 changed files with 794 additions and 796 deletions
+221
View File
@@ -0,0 +1,221 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block;
import javax.annotation.Nullable;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.block.Material;
import net.minecraft.block.MaterialColor;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.BlockView;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import appeng.api.util.IOrientable;
import appeng.api.util.IOrientableBlock;
import appeng.helpers.AEGlassMaterial;
import appeng.util.Platform;
public abstract class AEBaseBlock extends Block {
private boolean isInventory = false;
protected AEBaseBlock(final Settings props) {
super(props);
}
/**
* Utility function to create block properties with some sensible defaults for
* AE blocks.
*/
public static FabricBlockSettings defaultProps(Material material) {
return defaultProps(material, material.getColor());
}
/**
* Utility function to create block properties with some sensible defaults for
* AE blocks.
*/
public static FabricBlockSettings defaultProps(Material material, MaterialColor color) {
return FabricBlockSettings.of(material, color)
// These values previousls were encoded in AEBaseBlock
.strength(2.2f, 11.f)
.breakByTool(FabricToolTags.PICKAXES, 0)
.sounds(getDefaultSoundByMaterial(material));
}
private static BlockSoundGroup getDefaultSoundByMaterial(Material mat) {
if (mat == AEGlassMaterial.INSTANCE || mat == Material.GLASS) {
return BlockSoundGroup.GLASS;
} else if (mat == Material.STONE) {
return BlockSoundGroup.STONE;
} else if (mat == Material.WOOD) {
return BlockSoundGroup.WOOD;
} else {
return BlockSoundGroup.METAL;
}
}
@Override
public boolean hasComparatorOutput(BlockState state) {
return this.isInventory();
}
@Override
public int getComparatorOutput(BlockState state, final World worldIn, final BlockPos pos) {
return 0;
}
/**
* Rotates around the given Axis (usually the current up axis).
*/
public boolean rotateAroundFaceAxis(WorldAccess w, BlockPos pos, Direction face) {
final IOrientable rotatable = this.getOrientable(w, pos);
if (rotatable != null && rotatable.canBeRotated()) {
if (this.hasCustomRotation()) {
this.customRotateBlock(rotatable, face);
return true;
} else {
Direction forward = rotatable.getForward();
Direction up = rotatable.getUp();
for (int rs = 0; rs < 4; rs++) {
forward = Platform.rotateAround(forward, face);
up = Platform.rotateAround(up, face);
if (this.isValidOrientation(w, pos, forward, up)) {
rotatable.setOrientation(forward, up);
return true;
}
}
}
}
return false;
}
public final Direction mapRotation(final IOrientable ori, final Direction dir) {
// case DOWN: return bottomIcon;
// case UP: return blockIcon;
// case NORTH: return northIcon;
// case SOUTH: return southIcon;
// case WEST: return sideIcon;
// case EAST: return sideIcon;
final Direction forward = ori.getForward();
final Direction up = ori.getUp();
if (forward == null || up == null) {
return dir;
}
final int west_x = forward.getOffsetY() * up.getOffsetZ() - forward.getOffsetZ() * up.getOffsetY();
final int west_y = forward.getOffsetZ() * up.getOffsetX() - forward.getOffsetX() * up.getOffsetZ();
final int west_z = forward.getOffsetX() * up.getOffsetY() - forward.getOffsetY() * up.getOffsetX();
Direction west = null;
for (final Direction dx : Direction.values()) {
if (dx.getOffsetX() == west_x && dx.getOffsetY() == west_y && dx.getOffsetZ() == west_z) {
west = dx;
}
}
if (west == null) {
return dir;
}
if (dir == forward) {
return Direction.SOUTH;
}
if (dir == forward.getOpposite()) {
return Direction.NORTH;
}
if (dir == up) {
return Direction.UP;
}
if (dir == up.getOpposite()) {
return Direction.DOWN;
}
if (dir == west) {
return Direction.WEST;
}
if (dir == west.getOpposite()) {
return Direction.EAST;
}
return null;
}
@Override
public String toString() {
Identifier id = Registry.BLOCK.getId(this);
String regName = id == Registry.BLOCK.getDefaultId() ? "unregistered" : id.getPath();
return this.getClass().getSimpleName() + "[" + regName + "]";
}
protected String getUnlocalizedName(final ItemStack is) {
return this.getTranslationKey();
}
protected boolean hasCustomRotation() {
return false;
}
protected void customRotateBlock(final IOrientable rotatable, final Direction axis) {
}
protected IOrientable getOrientable(final BlockView w, final BlockPos pos) {
if (this instanceof IOrientableBlock) {
IOrientableBlock orientable = (IOrientableBlock) this;
return orientable.getOrientable(w, pos);
}
return null;
}
protected boolean isValidOrientation(final WorldAccess w, final BlockPos pos, final Direction forward,
final Direction up) {
return true;
}
protected boolean isInventory() {
return this.isInventory;
}
protected void setInventory(final boolean isInventory) {
this.isInventory = isInventory;
}
}
@@ -0,0 +1,154 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block;
import java.util.List;
import net.fabricmc.api.EnvType;
import net.minecraft.block.Block;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.Direction;
import net.minecraft.text.Text;
import net.minecraft.world.World;
import net.fabricmc.api.Environment;
import appeng.api.util.IOrientable;
import appeng.api.util.IOrientableBlock;
import appeng.block.misc.LightDetectorBlock;
import appeng.block.misc.SkyCompassBlock;
import appeng.me.helpers.IGridProxyable;
import appeng.tile.AEBaseBlockEntity;
public class AEBaseBlockItem extends BlockItem {
private final AEBaseBlock blockType;
public AEBaseBlockItem(final Block id, Settings props) {
super(id, props);
this.blockType = (AEBaseBlock) id;
}
@Override
@Environment(EnvType.CLIENT)
public final void appendTooltip(final ItemStack itemStack, final World world, final List<Text> toolTip,
final TooltipContext advancedTooltips) {
this.addCheckedInformation(itemStack, world, toolTip, advancedTooltips);
}
@Environment(EnvType.CLIENT)
public void addCheckedInformation(final ItemStack itemStack, final World world, final List<Text> toolTip,
final TooltipContext advancedTooltips) {
this.blockType.buildTooltip(itemStack, world, toolTip, advancedTooltips);
}
@Override
public String getTranslationKey(final ItemStack is) {
return this.blockType.getTranslationKey();
}
@Override
public ActionResult place(ItemPlacementContext context) {
Direction up = null;
Direction forward = null;
Direction side = context.getSide();
PlayerEntity player = context.getPlayer();
if (this.blockType instanceof AEBaseTileBlock) {
if (this.blockType instanceof LightDetectorBlock) {
up = side;
if (up == Direction.UP || up == Direction.DOWN) {
forward = Direction.SOUTH;
} else {
forward = Direction.UP;
}
} else if (/* FIXME FABRIC this.blockType instanceof WirelessBlock || */ this.blockType instanceof SkyCompassBlock) {
forward = side;
if (forward == Direction.UP || forward == Direction.DOWN) {
up = Direction.SOUTH;
} else {
up = Direction.UP;
}
} else {
up = Direction.UP;
forward = context.getPlayerFacing().getOpposite();
if (player != null) {
if (player.pitch > 65) {
up = forward.getOpposite();
forward = Direction.UP;
} else if (player.pitch < -65) {
up = forward.getOpposite();
forward = Direction.DOWN;
}
}
}
}
IOrientable ori = null;
if (this.blockType instanceof IOrientableBlock) {
ori = ((IOrientableBlock) this.blockType).getOrientable(context.getWorld(), context.getBlockPos());
up = side;
forward = Direction.SOUTH;
if (up.getOffsetY() == 0) {
forward = Direction.UP;
}
}
if (!this.blockType.isValidOrientation(context.getWorld(), context.getBlockPos(), forward, up)) {
return ActionResult.FAIL;
}
ActionResult result = super.place(context);
if (result != ActionResult.SUCCESS) {
return result;
}
if (this.blockType instanceof AEBaseTileBlock && !(this.blockType instanceof LightDetectorBlock)) {
final AEBaseBlockEntity tile = ((AEBaseTileBlock<?>) this.blockType).getBlockEntity(context.getWorld(),
context.getBlockPos());
ori = tile;
if (tile == null) {
return ActionResult.SUCCESS;
}
if (ori.canBeRotated() && !this.blockType.hasCustomRotation()) {
ori.setOrientation(forward, up);
}
if (tile instanceof IGridProxyable) {
// FIXME FABRIC ((IGridProxyable) tile).getProxy().setOwner(player);
}
tile.onPlacement(context);
} else if (this.blockType instanceof IOrientableBlock) {
ori.setOrientation(forward, up);
}
return ActionResult.SUCCESS;
}
}
@@ -0,0 +1,153 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block;
import appeng.api.AEApi;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
import appeng.api.config.PowerUnits;
import appeng.api.definitions.IBlockDefinition;
import appeng.api.implementations.items.IAEItemPowerStorage;
import appeng.core.AppEng;
import appeng.core.localization.GuiText;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry;
import net.minecraft.block.Block;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
import java.text.MessageFormat;
import java.util.List;
public class AEBaseBlockItemChargeable extends AEBaseBlockItem implements IAEItemPowerStorage {
public AEBaseBlockItemChargeable(Block id, Settings props) {
super(id, props);
FabricModelPredicateProviderRegistry.register(
this,
new Identifier(AppEng.MOD_ID, "fill_level"),
(is, world, entity) -> {
double curPower = getAECurrentPower(is);
double maxPower = getAEMaxPower(is);
return (int) Math.round(100 * curPower / maxPower);
}
);
}
@Override
@Environment(EnvType.CLIENT)
public void addCheckedInformation(final ItemStack stack, final World world, final List<Text> lines,
final TooltipContext advancedTooltips) {
double internalCurrentPower = 0;
final double internalMaxPower = this.getMaxEnergyCapacity();
if (internalMaxPower > 0) {
final CompoundTag tag = stack.getTag();
if (tag != null) {
internalCurrentPower = tag.getDouble("internalCurrentPower");
}
final double percent = internalCurrentPower / internalMaxPower;
lines.add(GuiText.StoredEnergy.textComponent()
.copy()
.append(':' + MessageFormat.format(" {0,number,#} ", internalCurrentPower))
.append(new TranslatableText(PowerUnits.AE.unlocalizedName))
.append(" - " + MessageFormat.format("{0,number,#.##%}", percent)));
}
}
@Override
public double injectAEPower(final ItemStack is, double amount, Actionable mode) {
final double internalCurrentPower = this.getInternal(is);
final double internalMaxPower = this.getAEMaxPower(is);
final double required = internalMaxPower - internalCurrentPower;
final double overflow = Math.max(0, amount - required);
if (mode == Actionable.MODULATE) {
final double toAdd = Math.min(required, amount);
final double newPowerStored = internalCurrentPower + toAdd;
this.setInternal(is, newPowerStored);
}
return overflow;
}
@Override
public double extractAEPower(final ItemStack is, double amount, Actionable mode) {
final double internalCurrentPower = this.getInternal(is);
final double fulfillable = Math.min(amount, internalCurrentPower);
if (mode == Actionable.MODULATE) {
final double newPowerStored = internalCurrentPower - fulfillable;
this.setInternal(is, newPowerStored);
}
return fulfillable;
}
@Override
public double getAEMaxPower(final ItemStack is) {
return this.getMaxEnergyCapacity();
}
@Override
public double getAECurrentPower(final ItemStack is) {
return this.getInternal(is);
}
@Override
public AccessRestriction getPowerFlow(final ItemStack is) {
return AccessRestriction.WRITE;
}
private double getMaxEnergyCapacity() {
final Block blockID = Block.getBlockFromItem(this);
final IBlockDefinition energyCell = AEApi.instance().definitions().blocks().energyCell();
return energyCell.maybeBlock().map(block -> {
if (blockID == block) {
return 200000;
} else {
return 8 * 200000;
}
}).orElse(0);
}
private double getInternal(final ItemStack is) {
final CompoundTag nbt = is.getOrCreateTag();
return nbt.getDouble("internalCurrentPower");
}
private void setInternal(final ItemStack is, final double amt) {
final CompoundTag nbt = is.getOrCreateTag();
nbt.putDouble("internalCurrentPower", amt);
}
}
@@ -0,0 +1,317 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import alexiil.mc.lib.attributes.AttributeList;
import alexiil.mc.lib.attributes.AttributeProvider;
import alexiil.mc.lib.attributes.item.FixedItemInv;
import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.ActionResult;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.text.Text;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import appeng.api.implementations.items.IMemoryCard;
import appeng.api.implementations.items.MemoryCardMessages;
import appeng.api.util.IOrientable;
import appeng.tile.AEBaseInvBlockEntity;
import appeng.tile.AEBaseBlockEntity;
import appeng.tile.storage.SkyChestBlockEntity;
import appeng.util.Platform;
import appeng.util.SettingsFrom;
public abstract class AEBaseTileBlock<T extends AEBaseBlockEntity> extends AEBaseBlock implements BlockEntityProvider, AttributeProvider {
@Nonnull
private Class<T> blockEntityClass;
@Nonnull
private Supplier<T> tileEntityFactory;
public AEBaseTileBlock(final Settings props) {
super(props);
}
// TODO : Was this change needed?
public void setTileEntity(final Class<T> tileEntityClass, Supplier<T> factory) {
this.blockEntityClass = tileEntityClass;
this.tileEntityFactory = factory;
this.setInventory(AEBaseInvBlockEntity.class.isAssignableFrom(tileEntityClass));
}
public Class<T> getBlockEntityClass() {
return this.blockEntityClass;
}
@Nullable
public T getBlockEntity(final BlockView w, final int x, final int y, final int z) {
return this.getBlockEntity(w, new BlockPos(x, y, z));
}
@Nullable
public T getBlockEntity(final BlockView w, final BlockPos pos) {
final BlockEntity te = w.getBlockEntity(pos);
// FIXME: This gets called as part of building the block state cache
if (this.blockEntityClass != null && this.blockEntityClass.isInstance(te)) {
return this.blockEntityClass.cast(te);
}
return null;
}
@Nullable
@Override
public BlockEntity createBlockEntity(BlockView world) {
return this.tileEntityFactory.get();
}
@Override
public void onStateReplaced(BlockState state, World w, BlockPos pos, BlockState newState, boolean isMoving) {
if (newState.getBlock() == state.getBlock()) {
return; // Just a block state change
}
final AEBaseBlockEntity te = this.getBlockEntity(w, pos);
if (te != null) {
final ArrayList<ItemStack> drops = new ArrayList<>();
if (te.dropItems()) {
te.getDrops(w, pos, drops);
} else {
te.getNoDrops(w, pos, drops);
}
// Cry ;_; ...
Platform.spawnDrops(w, pos, drops);
}
// super will remove the TE, as it is not an instance of BlockContainer
super.onStateReplaced(state, w, pos, newState, isMoving);
}
@Override
public int getComparatorOutput(BlockState state, final World w, final BlockPos pos) {
final BlockEntity te = this.getBlockEntity(w, pos);
if (te instanceof AEBaseInvBlockEntity) {
AEBaseInvBlockEntity invTile = (AEBaseInvBlockEntity) te;
if (invTile.getInternalInventory().getSlotCount() > 0) {
return getRedstoneFromFixedItemInv(invTile.getInternalInventory());
}
}
return 0;
}
/**
* Calculate redstone output level.
* 0 if completely empty, 1 if _any_ item is present, up to 15 if all slots are full.
*/
private int getRedstoneFromFixedItemInv(FixedItemInv inv) {
boolean foundAnything = false; // ANY slots non-empty?
float fillRatio = 0;
for (int i = 0; i < inv.getSlotCount(); ++i)
{
ItemStack stack = inv.getInvStack(i);
if (stack.isEmpty()) {
continue;
}
int slotMaxCount = inv.getMaxAmount(i, stack);
fillRatio += stack.getCount() / (float)Math.min(slotMaxCount, stack.getMaxCount());
foundAnything = true;
}
// Average the ratio across all slots
fillRatio /= inv.getSlotCount();
// Always return at least non-zero if _any_ slots are non-empty
return (foundAnything ? 1 : 0) + MathHelper.floor(fillRatio * 14.0f);
}
@Override
public boolean onSyncedBlockEvent(BlockState state, World world, BlockPos pos, int type, int data) {
super.onSyncedBlockEvent(state, world, pos, type, data);
final BlockEntity tileentity = world.getBlockEntity(pos);
return tileentity != null && tileentity.onSyncedBlockEvent(type, data);
}
@Override
public void onPlaced(final World w, final BlockPos pos, final BlockState state, final LivingEntity placer,
final ItemStack is) {
// Inherit the item stack's display name, but only if it's a user defined string
// rather
// than a translation component, since our custom naming cannot handle
// untranslated
// I18N strings and we would translate it using the server's locale :-(
AEBaseBlockEntity te = this.getBlockEntity(w, pos);
if (te != null && is.hasCustomName()) {
Text displayName = is.getName();
if (displayName instanceof LiteralText) {
te.setName(((LiteralText) displayName).getRawString());
}
}
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player,
Hand hand, BlockHitResult hit) {
ItemStack heldItem;
if (player != null && !player.getStackInHand(hand).isEmpty()) {
heldItem = player.getStackInHand(hand);
if (Platform.isWrench(player, heldItem, pos) && player.isInSneakingPose()) {
final BlockState blockState = world.getBlockState(pos);
final Block block = blockState.getBlock();
final AEBaseBlockEntity tile = this.getBlockEntity(world, pos);
if (tile == null) {
return ActionResult.FAIL;
}
if (/* FIXME FABRIC tile instanceof CableBusBlockEntity || */ tile instanceof SkyChestBlockEntity) {
return ActionResult.FAIL;
}
final ItemStack[] itemDropCandidates = Platform.getBlockDrops(world, pos);
final ItemStack op = new ItemStack(this);
for (final ItemStack ol : itemDropCandidates) {
if (Platform.itemComparisons().isEqualItemType(ol, op)) {
final CompoundTag tag = tile.downloadSettings(SettingsFrom.DISMANTLE_ITEM);
if (tag != null) {
ol.setTag(tag);
}
}
}
block.onBreak(world, pos, blockState, player);
boolean bl = world.removeBlock(pos, false);
if (bl) {
block.onBroken(world, pos, blockState);
final List<ItemStack> itemsToDrop = Lists.newArrayList(itemDropCandidates);
Platform.spawnDrops(world, pos, itemsToDrop);
}
return ActionResult.FAIL;
}
if (heldItem.getItem() instanceof IMemoryCard /* FIXME FABRIC && !(this instanceof CableBusBlock)*/) {
final IMemoryCard memoryCard = (IMemoryCard) heldItem.getItem();
final AEBaseBlockEntity tileEntity = this.getBlockEntity(world, pos);
if (tileEntity == null) {
return ActionResult.FAIL;
}
final String name = this.getTranslationKey();
if (player.isInSneakingPose()) {
final CompoundTag data = tileEntity.downloadSettings(SettingsFrom.MEMORY_CARD);
if (data != null) {
memoryCard.setMemoryCardContents(heldItem, name, data);
memoryCard.notifyUser(player, MemoryCardMessages.SETTINGS_SAVED);
}
} else {
final String savedName = memoryCard.getSettingsName(heldItem);
final CompoundTag data = memoryCard.getData(heldItem);
if (this.getTranslationKey().equals(savedName)) {
tileEntity.uploadSettings(SettingsFrom.MEMORY_CARD, data);
memoryCard.notifyUser(player, MemoryCardMessages.SETTINGS_LOADED);
} else {
memoryCard.notifyUser(player, MemoryCardMessages.INVALID_MACHINE);
}
}
return ActionResult.SUCCESS;
}
}
return this.onActivated(world, pos, player, hand, player.getStackInHand(hand), hit);
}
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity player, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
return ActionResult.PASS;
}
@Override
public IOrientable getOrientable(final BlockView w, final BlockPos pos) {
return this.getBlockEntity(w, pos);
}
/**
* Returns the BlockState based on the given BlockState while considering the
* state of the given TileEntity.
*
* If the given TileEntity is not of the right type for this block, the state is
* returned unchanged, this is also the case if the given block state does not
* belong to this block.
*/
public final BlockState getBlockEntityBlockState(BlockState current, BlockEntity te) {
if (current.getBlock() != this || !blockEntityClass.isInstance(te)) {
return current;
}
return updateBlockStateFromTileEntity(current, blockEntityClass.cast(te));
}
/**
* Reimplement this in subclasses to allow tile-entities to update the state of
* their block when their own state changes.
*
* It is guaranteed that te is not-null and the block of the given block state
* is this exact block instance.
*/
protected BlockState updateBlockStateFromTileEntity(BlockState currentState, T te) {
return currentState;
}
// Gives our tile entity a chance to provide it's attributes
@Override
public void addAllAttributes(World world, BlockPos pos, BlockState state, AttributeList<?> to) {
T te = getBlockEntity(world, pos);
if (te != null) {
te.addAllAttributes(world, pos, state, to);
}
}
}
@@ -1,100 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.crafting;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.CraftingCPUContainer;
import appeng.tile.crafting.CraftingBlockEntity;
public abstract class AbstractCraftingUnitBlock<T extends CraftingBlockEntity> extends AEBaseTileBlock<T> {
public static final BooleanProperty FORMED = BooleanProperty.of("formed");
public static final BooleanProperty POWERED = BooleanProperty.of("powered");
public final CraftingUnitType type;
public AbstractCraftingUnitBlock(Settings props, final CraftingUnitType type) {
super(props);
this.type = type;
this.setDefaultState(getDefaultState().with(FORMED, false).with(POWERED, false));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(POWERED);
builder.add(FORMED);
}
@Override
public void neighborUpdate(final BlockState state, final World worldIn, final BlockPos pos, final Block blockIn,
final BlockPos fromPos, boolean isMoving) {
final CraftingBlockEntity cp = this.getBlockEntity(worldIn, pos);
if (cp != null) {
cp.updateMultiBlock();
}
}
@Override
public void onStateReplaced(BlockState state, World w, BlockPos pos, BlockState newState, boolean isMoving) {
if (newState.getBlock() == state.getBlock()) {
return; // Just a block state change
}
final CraftingBlockEntity cp = this.getBlockEntity(w, pos);
if (cp != null) {
cp.breakCluster();
}
super.onStateReplaced(state, w, pos, newState, isMoving);
}
@Override
public ActionResult onUse(BlockState state, World w, BlockPos pos, PlayerEntity p, Hand hand,
BlockHitResult hit) {
final CraftingBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null && !p.isInSneakingPose() && tg.isFormed() && tg.isActive()) {
if (!w.isClient()) {
ContainerOpener.openContainer(CraftingCPUContainer.TYPE, p,
ContainerLocator.forTileEntitySide(tg, hit.getSide()));
}
return ActionResult.SUCCESS;
}
return super.onUse(state, w, pos, p, hand, hit);
}
public enum CraftingUnitType {
UNIT, ACCELERATOR, STORAGE_1K, STORAGE_4K, STORAGE_16K, STORAGE_64K, MONITOR
}
}
@@ -1,27 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.crafting;
import appeng.tile.crafting.CraftingMonitorBlockEntity;
public class CraftingMonitorBlock extends AbstractCraftingUnitBlock<CraftingMonitorBlockEntity> {
public CraftingMonitorBlock(Settings props) {
super(props, CraftingUnitType.MONITOR);
}
}
@@ -1,29 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.crafting;
import appeng.tile.crafting.CraftingStorageBlockEntity;
public class CraftingStorageBlock extends AbstractCraftingUnitBlock<CraftingStorageBlockEntity> {
public CraftingStorageBlock(Settings props, CraftingUnitType type) {
super(props, type);
}
}
@@ -1,44 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.crafting;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
import appeng.api.AEApi;
import appeng.api.features.AEFeature;
import appeng.block.AEBaseBlockItem;
import appeng.core.AEConfig;
public class CraftingStorageItem extends AEBaseBlockItem {
public CraftingStorageItem(Block id, Settings props) {
super(id, props);
}
@Override
public ItemStack getRecipeRemainder(final ItemStack itemStack) {
return AEApi.instance().definitions().blocks().craftingUnit().maybeStack(1).orElse(ItemStack.EMPTY);
}
@Override
public boolean hasRecipeRemainder(final ItemStack stack) {
return AEConfig.instance().isFeatureEnabled(AEFeature.ENABLE_DISASSEMBLY_CRAFTING);
}
}
@@ -1,29 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.crafting;
import appeng.tile.crafting.CraftingBlockEntity;
public class CraftingUnitBlock extends AbstractCraftingUnitBlock<CraftingBlockEntity> {
public CraftingUnitBlock(Settings props, CraftingUnitType type) {
super(props, type);
}
}
@@ -1,73 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.crafting;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.MolecularAssemblerContainer;
import appeng.tile.crafting.MolecularAssemblerBlockEntity;
public class MolecularAssemblerBlock extends AEBaseTileBlock<MolecularAssemblerBlockEntity> {
public static final BooleanProperty POWERED = BooleanProperty.of("powered");
public MolecularAssemblerBlock(Settings props) {
super(props);
setDefaultState(getDefaultState().with(POWERED, false));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(POWERED);
}
@Override
protected BlockState updateBlockStateFromTileEntity(BlockState currentState, MolecularAssemblerBlockEntity te) {
return currentState.with(POWERED, te.isPowered());
}
@Override
public ActionResult onUse(BlockState state, World w, BlockPos pos, PlayerEntity p, Hand hand,
BlockHitResult hit) {
final MolecularAssemblerBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null && !p.isInSneakingPose()) {
if (!tg.isClient()) {
ContainerOpener.openContainer(MolecularAssemblerContainer.TYPE, p,
ContainerLocator.forTileEntitySide(tg, hit.getSide()));
}
return ActionResult.SUCCESS;
}
return super.onUse(state, w, pos, p, hand, hit);
}
}
@@ -1,163 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.grindstone;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer;
import appeng.api.implementations.tiles.ICrankable;
import appeng.block.AEBaseTileBlock;
import appeng.core.stats.AeStats;
import appeng.tile.AEBaseBlockEntity;
import appeng.tile.grindstone.CrankBlockEntity;
public class CrankBlock extends AEBaseTileBlock<CrankBlockEntity> {
public CrankBlock(Settings props) {
super(props);
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity player, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (player instanceof FakePlayer || player == null) {
this.dropCrank(w, pos);
return ActionResult.SUCCESS;
}
final CrankBlockEntity tile = this.getBlockEntity(w, pos);
if (tile != null) {
if (tile.power()) {
AeStats.TurnedCranks.addToPlayer(player, 1);
}
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
private void dropCrank(final World world, final BlockPos pos) {
world.breakBlock(pos, true);
world.updateListeners(pos, this.getDefaultState(), world.getBlockState(pos), 3);
}
@Override
public void onPlaced(final World world, final BlockPos pos, final BlockState state,
final LivingEntity placer, final ItemStack stack) {
final AEBaseBlockEntity tile = this.getBlockEntity(world, pos);
if (tile != null) {
final Direction mnt = this.findCrankable(world, pos);
Direction forward = Direction.UP;
if (mnt == Direction.UP || mnt == Direction.DOWN) {
forward = Direction.SOUTH;
}
tile.setOrientation(forward, mnt.getOpposite());
} else {
this.dropCrank(world, pos);
}
}
@Override
public boolean isValidOrientation(final WorldAccess w, final BlockPos pos, final Direction forward, final Direction up) {
final BlockEntity te = w.getBlockEntity(pos);
return !(te instanceof CrankBlockEntity) || this.isCrankable(w, pos, up.getOpposite());
}
private Direction findCrankable(final BlockView world, final BlockPos pos) {
for (final Direction dir : Direction.values()) {
if (this.isCrankable(world, pos, dir)) {
return dir;
}
}
return null;
}
private boolean isCrankable(final BlockView world, final BlockPos pos, final Direction offset) {
final BlockPos o = pos.offset(offset);
final BlockEntity te = world.getBlockEntity(o);
return te instanceof ICrankable && ((ICrankable) te).canCrankAttach(offset.getOpposite());
}
@Override
public BlockRenderType getRenderType(BlockState state) {
return BlockRenderType.ENTITYBLOCK_ANIMATED;
}
@Override
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
final AEBaseBlockEntity tile = this.getBlockEntity(world, pos);
if (tile != null) {
if (!this.isCrankable(world, pos, tile.getUp().getOpposite())) {
this.dropCrank(world, pos);
}
} else {
this.dropCrank(world, pos);
}
}
@Override
public boolean canPlaceAt(BlockState state, WorldView w, BlockPos pos) {
return this.findCrankable(w, pos) != null;
}
private Direction getUp(BlockView world, BlockPos pos) {
CrankBlockEntity crank = getBlockEntity(world, pos);
return crank != null ? crank.getUp() : null;
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
Direction up = getUp(world, pos);
if (up == null) {
return VoxelShapes.empty();
} else {
// FIXME: Cache per direction, and build it 'precise', not just from AABB
final double xOff = -0.15 * up.getOffsetX();
final double yOff = -0.15 * up.getOffsetY();
final double zOff = -0.15 * up.getOffsetZ();
return VoxelShapes.cuboid(
new Box(xOff + 0.15, yOff + 0.15, zOff + 0.15, xOff + 0.85, yOff + 0.85, zOff + 0.85));
}
}
}
@@ -1,57 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.grindstone;
import javax.annotation.Nullable;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.GrinderContainer;
import appeng.tile.grindstone.GrinderBlockEntity;
public class GrinderBlock extends AEBaseTileBlock<GrinderBlockEntity> {
public GrinderBlock(Settings props) {
super(props);
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity p, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
final GrinderBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null && !p.isInSneakingPose()) {
if (p instanceof ServerPlayerEntity) {
ContainerOpener.openContainer(GrinderContainer.TYPE, p,
ContainerLocator.forTileEntitySide(tg, hit.getSide()));
}
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
}
@@ -1,60 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
import javax.annotation.Nullable;
import net.minecraft.block.Material;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.implementations.CellWorkbenchContainer;
import appeng.tile.misc.CellWorkbenchBlockEntity;
import appeng.util.Platform;
public class CellWorkbenchBlock extends AEBaseTileBlock<CellWorkbenchBlockEntity> {
public CellWorkbenchBlock() {
super(defaultProps(Material.METAL));
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity p, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (p.isInSneakingPose()) {
return ActionResult.PASS;
}
final CellWorkbenchBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null) {
if (Platform.isServer()) {
CellWorkbenchContainer.open(p, ContainerLocator.forTileEntity(tg));
}
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
}
@@ -1,190 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
import java.util.Random;
import java.util.function.Function;
import javax.annotation.Nullable;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.model.json.Transformation;
import net.minecraft.client.util.math.AffineTransformation;
import net.minecraft.util.math.Box;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import appeng.api.AEApi;
import appeng.api.util.AEAxisAlignedBB;
import appeng.block.AEBaseTileBlock;
import appeng.client.render.effects.ParticleTypes;
import appeng.client.render.renderable.ItemRenderable;
import appeng.client.render.tesr.ModularTESR;
import appeng.core.AEConfig;
import appeng.core.AppEng;
import appeng.tile.misc.ChargerBlockEntity;
import appeng.util.Platform;
public class ChargerBlock extends AEBaseTileBlock<ChargerBlockEntity> {
public ChargerBlock() {
super(defaultProps(Material.METAL));
}
@Override
public int getOpacity(BlockState state, BlockView worldIn, BlockPos pos) {
return 2; // FIXME Double check this (esp. value range)
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity player, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (player.isInSneakingPose()) {
return ActionResult.PASS;
}
if (Platform.isServer()) {
final ChargerBlockEntity tc = this.getBlockEntity(w, pos);
if (tc != null) {
tc.activate(player);
}
}
return ActionResult.SUCCESS;
}
@Override
@Environment(EnvType.CLIENT)
public void randomDisplayTick(final BlockState state, final World w, final BlockPos pos, final Random r) {
if (!AEConfig.instance().isEnableEffects()) {
return;
}
if (r.nextFloat() < 0.98) {
return;
}
final ChargerBlockEntity tile = this.getBlockEntity(w, pos);
if (tile != null) {
if (AEApi.instance().definitions().materials().certusQuartzCrystalCharged()
.isSameAs(tile.getInternalInventory().getInvStack(0))) {
final double xOff = 0.0;
final double yOff = 0.0;
final double zOff = 0.0;
for (int bolts = 0; bolts < 3; bolts++) {
if (AppEng.instance().shouldAddParticles(r)) {
MinecraftClient.getInstance().particleManager.addParticle(ParticleTypes.LIGHTNING, xOff + 0.5 + pos.getX(),
yOff + 0.5 + pos.getY(), zOff + 0.5 + pos.getZ(), 0.0, 0.0, 0.0);
}
}
}
}
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView w, BlockPos pos, ShapeContext context) {
final ChargerBlockEntity tile = this.getBlockEntity(w, pos);
if (tile != null) {
final double twoPixels = 2.0 / 16.0;
final Direction up = tile.getUp();
final Direction forward = tile.getForward();
final AEAxisAlignedBB bb = new AEAxisAlignedBB(twoPixels, twoPixels, twoPixels, 1.0 - twoPixels,
1.0 - twoPixels, 1.0 - twoPixels);
if (up.getOffsetX() != 0) {
bb.minX = 0;
bb.maxX = 1;
}
if (up.getOffsetY() != 0) {
bb.minY = 0;
bb.maxY = 1;
}
if (up.getOffsetZ() != 0) {
bb.minZ = 0;
bb.maxZ = 1;
}
switch (forward) {
case DOWN:
bb.maxY = 1;
break;
case UP:
bb.minY = 0;
break;
case NORTH:
bb.maxZ = 1;
break;
case SOUTH:
bb.minZ = 0;
break;
case EAST:
bb.minX = 0;
break;
case WEST:
bb.maxX = 1;
break;
default:
break;
}
return VoxelShapes.cuboid(bb.getBoundingBox());
}
return VoxelShapes.cuboid(new Box(0.0, 0, 0.0, 1.0, 1.0, 1.0));
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView worldIn, BlockPos pos,
ShapeContext context) {
return VoxelShapes.cuboid(new Box(0.0, 0.0, 0.0, 1.0, 1.0, 1.0));
}
@Environment(EnvType.CLIENT)
public static Function<BlockEntityRenderDispatcher, BlockEntityRenderer<ChargerBlockEntity>> createTesr() {
return dispatcher -> new ModularTESR<>(dispatcher, new ItemRenderable<>(ChargerBlock::getRenderedItem));
}
@Environment(EnvType.CLIENT)
private static Pair<ItemStack, Transformation> getRenderedItem(ChargerBlockEntity tile) {
Transformation transform = new Transformation(new Vector3f(), new Vector3f(0.5f, 0.375f, 0.5f), new Vector3f(1f, 1f, 1f));
return new ImmutablePair<>(tile.getInternalInventory().getInvStack(0), transform);
}
}
@@ -1,63 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
import javax.annotation.Nullable;
import net.minecraft.block.Material;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.CondenserContainer;
import appeng.tile.misc.CondenserBlockEntity;
import appeng.util.Platform;
public class CondenserBlock extends AEBaseTileBlock<CondenserBlockEntity> {
public CondenserBlock() {
super(defaultProps(Material.METAL));
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity player, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (player.isInSneakingPose()) {
return ActionResult.PASS;
}
if (Platform.isServer()) {
final CondenserBlockEntity tc = this.getBlockEntity(w, pos);
if (tc != null && !player.isInSneakingPose()) {
ContainerOpener.openContainer(CondenserContainer.TYPE, player,
ContainerLocator.forTileEntitySide(tc, hit.getSide()));
return ActionResult.SUCCESS;
}
}
return ActionResult.SUCCESS;
}
}
@@ -1,68 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.InscriberContainer;
import appeng.tile.misc.InscriberBlockEntity;
public class InscriberBlock extends AEBaseTileBlock<InscriberBlockEntity> {
public InscriberBlock(Settings props) {
super(props);
}
@Override
public int getOpacity(BlockState state, BlockView worldIn, BlockPos pos) {
return 2; // FIXME validate this. a) possibly not required because of getShape b) value
// range. was 2 in 1.10
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity p, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (!p.isInSneakingPose()) {
final InscriberBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null) {
if (!tg.isClient()) {
ContainerOpener.openContainer(InscriberContainer.TYPE, p,
ContainerLocator.forTileEntitySide(tg, hit.getSide()));
}
return ActionResult.SUCCESS;
}
}
return ActionResult.PASS;
}
}
@@ -1,20 +0,0 @@
package appeng.block.misc;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.bootstrap.TileEntityRendering;
import appeng.bootstrap.TileEntityRenderingCustomizer;
import appeng.client.render.tesr.InscriberTESR;
import appeng.tile.misc.InscriberBlockEntity;
public class InscriberRendering implements TileEntityRenderingCustomizer<InscriberBlockEntity> {
@Environment(EnvType.CLIENT)
@Override
public void customize(TileEntityRendering<InscriberBlockEntity> rendering) {
rendering.tileEntityRenderer(InscriberTESR::new);
}
}
@@ -1,93 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.api.util.IOrientable;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.InterfaceContainer;
import appeng.tile.misc.InterfaceBlockEntity;
import appeng.util.Platform;
public class InterfaceBlock extends AEBaseTileBlock<InterfaceBlockEntity> {
private static final BooleanProperty OMNIDIRECTIONAL = BooleanProperty.of("omnidirectional");
public InterfaceBlock() {
super(defaultProps(Material.METAL));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(OMNIDIRECTIONAL);
}
@Override
protected BlockState updateBlockStateFromTileEntity(BlockState currentState, InterfaceBlockEntity te) {
return currentState.with(OMNIDIRECTIONAL, te.isOmniDirectional());
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity p, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (p.isInSneakingPose()) {
return ActionResult.PASS;
}
final InterfaceBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null) {
if (Platform.isServer()) {
ContainerOpener.openContainer(InterfaceContainer.TYPE, p,
ContainerLocator.forTileEntitySide(tg, hit.getSide()));
}
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
@Override
protected boolean hasCustomRotation() {
return true;
}
@Override
protected void customRotateBlock(final IOrientable rotatable, final Direction axis) {
if (rotatable instanceof InterfaceBlockEntity) {
((InterfaceBlockEntity) rotatable).setSide(axis);
}
}
}
@@ -0,0 +1,134 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
import net.minecraft.block.*;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.Properties;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
import net.minecraft.world.World;
import appeng.api.util.IOrientable;
import appeng.api.util.IOrientableBlock;
import appeng.block.AEBaseTileBlock;
import appeng.helpers.MetaRotation;
import appeng.tile.misc.LightDetectorBlockEntity;
public class LightDetectorBlock extends AEBaseTileBlock<LightDetectorBlockEntity> implements IOrientableBlock {
// Used to alternate between two variants of the fixture on adjacent blocks
public static final BooleanProperty ODD = BooleanProperty.of("odd");
public LightDetectorBlock() {
super(defaultProps(Material.SUPPORTED));
this.setDefaultState(this.getDefaultState().with(Properties.FACING, Direction.UP).with(ODD, false));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(Properties.FACING);
builder.add(ODD);
}
@Override
public int getWeakRedstonePower(final BlockState state, final BlockView w, final BlockPos pos, final Direction side) {
if (w instanceof World && this.getBlockEntity(w, pos).isReady()) {
// FIXME: This is ... uhm... fishy
return ((World) w).getLightLevel(pos) - 6;
}
return 0;
}
@Override
public boolean emitsRedstonePower(BlockState state) {
return true;
}
public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState newState, WorldAccess world, BlockPos pos, BlockPos posFrom) {
final Direction up = this.getOrientable(world, pos).getUp();
if (!this.canPlaceAt(world, pos, up.getOpposite())) {
// FIXME: Double check that this actually updates neighbors
return Blocks.AIR.getDefaultState();
}
final LightDetectorBlockEntity tld = this.getBlockEntity(world, pos);
if (tld != null) {
tld.updateLight();
}
return state;
}
@Override
public boolean isValidOrientation(final WorldAccess w, final BlockPos pos, final Direction forward, final Direction up) {
return this.canPlaceAt(w, pos, up.getOpposite());
}
private boolean canPlaceAt(final BlockView w, final BlockPos pos, final Direction dir) {
final BlockPos test = pos.offset(dir);
BlockState blockstate = w.getBlockState(test);
return blockstate.isSideSolidFullSquare(w, test, dir.getOpposite());
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView w, BlockPos pos, ShapeContext context) {
// FIXME: We should / rather MUST use state here because at startup, this gets
// called without a world
final Direction up = this.getOrientable(w, pos).getUp();
final double xOff = -0.3 * up.getOffsetX();
final double yOff = -0.3 * up.getOffsetY();
final double zOff = -0.3 * up.getOffsetZ();
return VoxelShapes
.cuboid(new Box(xOff + 0.3, yOff + 0.3, zOff + 0.3, xOff + 0.7, yOff + 0.7, zOff + 0.7));
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView worldIn, BlockPos pos,
ShapeContext context) {
return VoxelShapes.empty();
}
@Override
public boolean canPlaceAt(BlockState state, WorldView w, BlockPos pos) {
for (final Direction dir : Direction.values()) {
if (this.canPlaceAt(w, pos, dir)) {
return true;
}
}
return false;
}
@Override
public IOrientable getOrientable(final BlockView w, final BlockPos pos) {
return new MetaRotation(w, pos, Properties.FACING);
}
}
@@ -0,0 +1,202 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
import java.util.EnumMap;
import java.util.Map;
import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.block.Material;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.property.DirectionProperty;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.Properties;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
import net.minecraft.world.World;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.api.util.IOrientable;
import appeng.api.util.IOrientableBlock;
import appeng.block.AEBaseBlock;
import appeng.client.render.effects.ParticleTypes;
import appeng.core.AEConfig;
import appeng.core.AppEng;
import appeng.helpers.MetaRotation;
public class QuartzFixtureBlock extends AEBaseBlock implements IOrientableBlock {
// Cache VoxelShapes for each facing
private static final Map<Direction, VoxelShape> SHAPES;
static {
SHAPES = new EnumMap<>(Direction.class);
for (Direction facing : Direction.values()) {
final double xOff = -0.3 * facing.getOffsetX();
final double yOff = -0.3 * facing.getOffsetY();
final double zOff = -0.3 * facing.getOffsetZ();
VoxelShape shape = VoxelShapes
.cuboid(new Box(xOff + 0.3, yOff + 0.3, zOff + 0.3, xOff + 0.7, yOff + 0.7, zOff + 0.7));
SHAPES.put(facing, shape);
}
}
// Cannot use the vanilla FACING property here because it excludes facing DOWN
public static final DirectionProperty FACING = Properties.FACING;
// Used to alternate between two variants of the fixture on adjacent blocks
public static final BooleanProperty ODD = BooleanProperty.of("odd");
public QuartzFixtureBlock() {
super(defaultProps(Material.SUPPORTED).noCollision().strength(0).lightLevel(14)
.sounds(BlockSoundGroup.GLASS));
this.setDefaultState(getDefaultState().with(FACING, Direction.UP).with(ODD, false));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(FACING, ODD);
}
// For reference, see WallTorchBlock
@Override
@Nullable
public BlockState getPlacementState(ItemPlacementContext context) {
BlockState blockstate = super.getPlacementState(context);
BlockPos pos = context.getBlockPos();
// Set the even/odd property
boolean oddPlacement = ((pos.getX() + pos.getY() + pos.getZ()) % 2) != 0;
blockstate = blockstate.with(ODD, oddPlacement);
WorldView iworldreader = context.getWorld();
Direction[] adirection = context.getPlacementDirections();
for (Direction direction : adirection) {
if (canPlaceAt(iworldreader, pos, direction)) {
return blockstate.with(FACING, direction.getOpposite());
}
}
return null;
}
// Break the fixture if the block it is attached to is changed so that it could
// no longer be placed
@Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction facing, BlockState facingState, WorldAccess worldIn,
BlockPos pos, BlockPos facingPos) {
Direction fixtureFacing = state.get(FACING);
if (facing.getOpposite() == fixtureFacing && !canPlaceAt(worldIn, pos, facing)) {
return Blocks.AIR.getDefaultState();
}
return state;
}
@Override
public boolean isValidOrientation(final WorldAccess w, final BlockPos pos, final Direction forward, final Direction up) {
// FIXME: I think this entire method -> not required, but not sure... are quartz
// fixtures rotateable???
return this.canPlaceAt(w, pos, up.getOpposite());
}
private boolean canPlaceAt(final WorldView w, final BlockPos pos, final Direction dir) {
final BlockPos test = pos.offset(dir);
BlockState blockstate = w.getBlockState(test);
return blockstate.isSideSolidFullSquare(w, test, dir.getOpposite());
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView worldIn, BlockPos pos, ShapeContext context) {
Direction facing = state.get(FACING);
return SHAPES.get(facing);
}
@Override
@Environment(EnvType.CLIENT)
public void randomDisplayTick(final BlockState state, final World w, final BlockPos pos, final Random r) {
if (!AEConfig.instance().isEnableEffects()) {
return;
}
if (r.nextFloat() < 0.98) {
return;
}
final Direction up = this.getOrientable(w, pos).getUp();
final double xOff = -0.3 * up.getOffsetX();
final double yOff = -0.3 * up.getOffsetY();
final double zOff = -0.3 * up.getOffsetZ();
for (int bolts = 0; bolts < 3; bolts++) {
if (AppEng.instance().shouldAddParticles(r)) {
w.addParticle(ParticleTypes.LIGHTNING, xOff + 0.5 + pos.getX(), yOff + 0.5 + pos.getY(),
zOff + 0.5 + pos.getZ(), 0, 0, 0);
}
}
}
// FIXME: Replaced by the postPlaceupdate stuff above, but check item drops!
@Override
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
final Direction up = this.getOrientable(world, pos).getUp();
if (!this.canPlaceAt(world, pos, up.getOpposite())) {
this.dropTorch(world, pos);
}
}
private void dropTorch(final World w, final BlockPos pos) {
final BlockState prev = w.getBlockState(pos);
w.breakBlock(pos, true);
w.updateListeners(pos, prev, w.getBlockState(pos), 3);
}
@Override
public boolean canPlaceAt(BlockState state, WorldView w, BlockPos pos) {
for (final Direction dir : Direction.values()) {
if (this.canPlaceAt(w, pos, dir)) {
return true;
}
}
return false;
}
@Override
public IOrientable getOrientable(final BlockView w, final BlockPos pos) {
return new MetaRotation(w, pos, FACING);
}
}
@@ -1,141 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
import java.util.Random;
import net.fabricmc.api.EnvType;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.block.Material;
import net.minecraft.client.MinecraftClient;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.StateManager;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.fabricmc.api.Environment;
import appeng.api.util.IOrientableBlock;
import appeng.block.AEBaseTileBlock;
import appeng.client.render.effects.ParticleTypes;
import appeng.core.AEConfig;
import appeng.core.AppEng;
import appeng.tile.misc.QuartzGrowthAcceleratorBlockEntity;
import appeng.util.Platform;
public class QuartzGrowthAcceleratorBlock extends AEBaseTileBlock<QuartzGrowthAcceleratorBlockEntity>
implements IOrientableBlock {
private static final BooleanProperty POWERED = BooleanProperty.of("powered");
public QuartzGrowthAcceleratorBlock() {
super(defaultProps(Material.STONE).sounds(BlockSoundGroup.METAL));
this.setDefaultState(this.getDefaultState().with(POWERED, false));
}
@Override
protected BlockState updateBlockStateFromTileEntity(BlockState currentState, QuartzGrowthAcceleratorBlockEntity te) {
return currentState.with(POWERED, te.isPowered());
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(POWERED);
}
@Environment(EnvType.CLIENT)
@Override
public void randomDisplayTick(final BlockState state, final World w, final BlockPos pos, final Random r) {
if (!AEConfig.instance().isEnableEffects()) {
return;
}
final QuartzGrowthAcceleratorBlockEntity cga = this.getBlockEntity(w, pos);
if (cga != null && cga.isPowered() && AppEng.instance().shouldAddParticles(r)) {
final double d0 = r.nextFloat() - 0.5F;
final double d1 = r.nextFloat() - 0.5F;
final Direction up = cga.getUp();
final Direction forward = cga.getForward();
final Direction west = Platform.crossProduct(forward, up);
double rx = 0.5 + pos.getX();
double ry = 0.5 + pos.getY();
double rz = 0.5 + pos.getZ();
rx += up.getOffsetX() * d0;
ry += up.getOffsetY() * d0;
rz += up.getOffsetZ() * d0;
final int x = pos.getX();
final int y = pos.getY();
final int z = pos.getZ();
double dz = 0;
double dx = 0;
BlockPos pt = null;
switch (r.nextInt(4)) {
case 0:
dx = 0.6;
dz = d1;
pt = new BlockPos(x + west.getOffsetX(), y + west.getOffsetY(), z + west.getOffsetZ());
break;
case 1:
dx = d1;
dz += 0.6;
pt = new BlockPos(x + forward.getOffsetX(), y + forward.getOffsetY(), z + forward.getOffsetZ());
break;
case 2:
dx = d1;
dz = -0.6;
pt = new BlockPos(x - forward.getOffsetX(), y - forward.getOffsetY(), z - forward.getOffsetZ());
break;
case 3:
dx = -0.6;
dz = d1;
pt = new BlockPos(x - west.getOffsetX(), y - west.getOffsetY(), z - west.getOffsetZ());
break;
}
if (!w.getBlockState(pt).isAir()) {
return;
}
rx += dx * west.getOffsetX();
ry += dx * west.getOffsetY();
rz += dx * west.getOffsetZ();
rx += dz * forward.getOffsetX();
ry += dz * forward.getOffsetY();
rz += dz * forward.getOffsetZ();
MinecraftClient.getInstance().particleManager.addParticle(ParticleTypes.LIGHTNING, rx, ry, rz, 0.0D, 0.0D, 0.0D);
}
}
}
@@ -1,82 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.SecurityStationContainer;
import appeng.tile.misc.SecurityStationBlockEntity;
public class SecurityStationBlock extends AEBaseTileBlock<SecurityStationBlockEntity> {
private static final BooleanProperty POWERED = BooleanProperty.of("powered");
public SecurityStationBlock() {
super(defaultProps(Material.METAL));
this.setDefaultState(this.getDefaultState().with(POWERED, false));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(POWERED);
}
@Override
protected BlockState updateBlockStateFromTileEntity(BlockState currentState, SecurityStationBlockEntity te) {
return currentState.with(POWERED, te.isActive());
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity p, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (p.isInSneakingPose()) {
return ActionResult.PASS;
}
final SecurityStationBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null) {
if (w.isClient()) {
return ActionResult.SUCCESS;
}
ContainerOpener.openContainer(SecurityStationContainer.TYPE, p,
ContainerLocator.forTileEntitySide(tg, hit.getSide()));
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
}
@@ -0,0 +1,158 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.tile.misc.SkyCompassBlockEntity;
public class SkyCompassBlock extends AEBaseTileBlock<SkyCompassBlockEntity> {
public SkyCompassBlock(Settings props) {
super(props);
}
@Override
public boolean isValidOrientation(final WorldAccess w, final BlockPos pos, final Direction forward, final Direction up) {
final SkyCompassBlockEntity sc = this.getBlockEntity(w, pos);
if (sc != null) {
return false;
}
return this.canPlaceAt(w, pos, forward.getOpposite());
}
private boolean canPlaceAt(final BlockView w, final BlockPos pos, final Direction dir) {
final BlockPos test = pos.offset(dir);
BlockState blockstate = w.getBlockState(test);
return blockstate.isSideSolidFullSquare(w, test, dir.getOpposite());
}
@Override
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
final SkyCompassBlockEntity sc = this.getBlockEntity(world, pos);
final Direction forward = sc.getForward();
if (!this.canPlaceAt(world, pos, forward.getOpposite())) {
this.dropTorch(world, pos);
}
}
private void dropTorch(final World w, final BlockPos pos) {
final BlockState prev = w.getBlockState(pos);
w.breakBlock(pos, true);
w.updateListeners(pos, prev, w.getBlockState(pos), 3);
}
@Override
public boolean canPlaceAt(BlockState state, WorldView w, BlockPos pos) {
for (final Direction dir : Direction.values()) {
if (this.canPlaceAt(w, pos, dir)) {
return true;
}
}
return false;
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView w, BlockPos pos, ShapeContext context) {
// TODO: This definitely needs to be memoized
final SkyCompassBlockEntity tile = this.getBlockEntity(w, pos);
if (tile != null) {
final Direction forward = tile.getForward();
double minX = 0;
double minY = 0;
double minZ = 0;
double maxX = 1;
double maxY = 1;
double maxZ = 1;
switch (forward) {
case DOWN:
minZ = minX = 5.0 / 16.0;
maxZ = maxX = 11.0 / 16.0;
maxY = 1.0;
minY = 14.0 / 16.0;
break;
case EAST:
minZ = minY = 5.0 / 16.0;
maxZ = maxY = 11.0 / 16.0;
maxX = 2.0 / 16.0;
minX = 0.0;
break;
case NORTH:
minY = minX = 5.0 / 16.0;
maxY = maxX = 11.0 / 16.0;
maxZ = 1.0;
minZ = 14.0 / 16.0;
break;
case SOUTH:
minY = minX = 5.0 / 16.0;
maxY = maxX = 11.0 / 16.0;
maxZ = 2.0 / 16.0;
minZ = 0.0;
break;
case UP:
minZ = minX = 5.0 / 16.0;
maxZ = maxX = 11.0 / 16.0;
maxY = 2.0 / 16.0;
minY = 0.0;
break;
case WEST:
minZ = minY = 5.0 / 16.0;
maxZ = maxY = 11.0 / 16.0;
maxX = 1.0;
minX = 14.0 / 16.0;
break;
default:
break;
}
return VoxelShapes.cuboid(new Box(minX, minY, minZ, maxX, maxY, maxZ));
}
return VoxelShapes.empty();
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView worldIn, BlockPos pos,
ShapeContext context) {
return VoxelShapes.empty();
}
@Override
public BlockRenderType getRenderType(BlockState state) {
return BlockRenderType.ENTITYBLOCK_ANIMATED;
}
}
@@ -16,30 +16,22 @@
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.storage;
package appeng.block.misc;
import net.minecraft.util.StringIdentifiable;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
/**
* Describes the type of cell present in a slot.
*/
public enum DriveSlotCellType implements StringIdentifiable {
import appeng.bootstrap.TileEntityRendering;
import appeng.bootstrap.TileEntityRenderingCustomizer;
import appeng.client.render.tesr.SkyCompassTESR;
import appeng.tile.misc.SkyCompassBlockEntity;
EMPTY("empty"),
ITEM("item"),
FLUID("fluid");
private final String name;
DriveSlotCellType(String name) {
this.name = name;
}
public class SkyCompassRendering implements TileEntityRenderingCustomizer<SkyCompassBlockEntity> {
@Override
public String asString() {
return this.name;
@Environment(EnvType.CLIENT)
public void customize(TileEntityRendering<SkyCompassBlockEntity> rendering) {
rendering.tileEntityRenderer(SkyCompassTESR::new);
}
}
@@ -0,0 +1,146 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.explosion.Explosion;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import appeng.block.AEBaseBlock;
import appeng.entity.TinyTNTPrimedEntity;
public class TinyTNTBlock extends AEBaseBlock {
private static final VoxelShape SHAPE = VoxelShapes
.cuboid(new Box(0.25f, 0.0f, 0.25f, 0.75f, 0.5f, 0.75f));
public TinyTNTBlock(Settings props) {
super(props);
}
@Override
public int getOpacity(BlockState state, BlockView worldIn, BlockPos pos) {
return 2; // FIXME: Validate that this is the correct value range
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView worldIn, BlockPos pos, ShapeContext context) {
return SHAPE;
}
@Override
public ActionResult onUse(BlockState state, World w, BlockPos pos, PlayerEntity player, Hand hand,
final BlockHitResult hit) {
ItemStack heldItem = player.getStackInHand(hand);
if (heldItem.getItem() == Items.FLINT_AND_STEEL) {
this.startFuse(w, pos, player);
w.removeBlock(pos, false);
heldItem.damage(1, player, p -> {
p.sendToolBreakStatus(hand);
}); // FIXME Check if onBroken is equivalent
return ActionResult.SUCCESS;
} else {
return super.onUse(state, w, pos, player, hand, hit);
}
}
public void startFuse(final World w, final BlockPos pos, final LivingEntity igniter) {
if (!w.isClient) {
final TinyTNTPrimedEntity primedTinyTNTEntity = new TinyTNTPrimedEntity(w, pos.getX() + 0.5F,
pos.getY(), pos.getZ() + 0.5F, igniter);
w.spawnEntity(primedTinyTNTEntity);
w.playSound(null, primedTinyTNTEntity.getX(), primedTinyTNTEntity.getY(),
primedTinyTNTEntity.getZ(), SoundEvents.ENTITY_TNT_PRIMED, SoundCategory.BLOCKS, 1, 1);
}
}
@Override
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) {
if (world.isReceivingRedstonePower(pos)) {
this.startFuse(world, pos, null);
world.removeBlock(pos, false);
}
}
@Override
public void onBlockAdded(BlockState state, World w, BlockPos pos, BlockState oldState, boolean isMoving) {
super.onBlockAdded(state, w, pos, oldState, isMoving);
if (w.getReceivedStrongRedstonePower(pos) > 0) {
this.startFuse(w, pos, null);
w.removeBlock(pos, false);
}
}
@Override
public void onSteppedOn(final World w, final BlockPos pos, final Entity entity) {
if (entity instanceof PersistentProjectileEntity && !w.isClient) {
final PersistentProjectileEntity entityarrow = (PersistentProjectileEntity) entity;
if (entityarrow.isOnFire()) {
LivingEntity igniter = null;
// Check if the shooter still exists
Entity shooter = entityarrow.getOwner();
if (shooter instanceof LivingEntity) {
igniter = (LivingEntity) shooter;
}
this.startFuse(w, pos, igniter);
w.removeBlock(pos, false);
}
}
}
@Override
public boolean shouldDropItemsOnExplosion(final Explosion exp) {
return false;
}
@Override
public void onDestroyedByExplosion(final World w, final BlockPos pos, final Explosion exp) {
super.onDestroyedByExplosion(w, pos, exp);
if (!w.isClient) {
final TinyTNTPrimedEntity primedTinyTNTEntity = new TinyTNTPrimedEntity(w, pos.getX() + 0.5F,
pos.getY() + 0.5F, pos.getZ() + 0.5F, exp.getCausingEntity());
primedTinyTNTEntity
.setFuse(w.random.nextInt(primedTinyTNTEntity.getFuse() / 4) + primedTinyTNTEntity.getFuse() / 8);
w.spawnEntity(primedTinyTNTEntity);
}
}
}
@@ -1,126 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.VibrationChamberContainer;
import appeng.core.AEConfig;
import appeng.tile.misc.VibrationChamberBlockEntity;
import appeng.util.Platform;
public final class VibrationChamberBlock extends AEBaseTileBlock<VibrationChamberBlockEntity> {
// Indicates that the vibration chamber is currently working
private static final BooleanProperty ACTIVE = BooleanProperty.of("active");
public VibrationChamberBlock() {
super(defaultProps(Material.METAL).strength(4.2F));
this.setDefaultState(this.getDefaultState().with(ACTIVE, false));
}
@Override
protected BlockState updateBlockStateFromTileEntity(BlockState currentState, VibrationChamberBlockEntity te) {
return currentState.with(ACTIVE, te.isOn);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(ACTIVE);
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity player, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (player.isInSneakingPose()) {
return ActionResult.PASS;
}
if (Platform.isServer()) {
final VibrationChamberBlockEntity tc = this.getBlockEntity(w, pos);
if (tc != null && !player.isInSneakingPose()) {
ContainerOpener.openContainer(VibrationChamberContainer.TYPE, player,
ContainerLocator.forTileEntitySide(tc, hit.getSide()));
return ActionResult.SUCCESS;
}
}
return ActionResult.SUCCESS;
}
@Override
public void randomDisplayTick(final BlockState state, final World w, final BlockPos pos, final Random r) {
if (!AEConfig.instance().isEnableEffects()) {
return;
}
final VibrationChamberBlockEntity tile = this.getBlockEntity(w, pos);
if (tile != null && tile.isOn) {
double f1 = pos.getX() + 0.5F;
double f2 = pos.getY() + 0.5F;
double f3 = pos.getZ() + 0.5F;
final Direction forward = tile.getForward();
final Direction up = tile.getUp();
final int west_x = forward.getOffsetY() * up.getOffsetZ() - forward.getOffsetZ() * up.getOffsetY();
final int west_y = forward.getOffsetZ() * up.getOffsetX() - forward.getOffsetX() * up.getOffsetZ();
final int west_z = forward.getOffsetX() * up.getOffsetY() - forward.getOffsetY() * up.getOffsetX();
f1 += forward.getOffsetX() * 0.6;
f2 += forward.getOffsetY() * 0.6;
f3 += forward.getOffsetZ() * 0.6;
final double ox = r.nextDouble();
final double oy = r.nextDouble() * 0.2f;
f1 += up.getOffsetX() * (-0.3 + oy);
f2 += up.getOffsetY() * (-0.3 + oy);
f3 += up.getOffsetZ() * (-0.3 + oy);
f1 += west_x * (0.3 * ox - 0.15);
f2 += west_y * (0.3 * ox - 0.15);
f3 += west_z * (0.3 * ox - 0.15);
w.addParticle(ParticleTypes.SMOKE, f1, f2, f3, 0.0D, 0.0D, 0.0D);
w.addParticle(ParticleTypes.FLAME, f1, f2, f3, 0.0D, 0.0D, 0.0D);
}
}
}
@@ -0,0 +1,398 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.networking;
import appeng.api.parts.IFacadeContainer;
import appeng.api.parts.IFacadePart;
import appeng.api.parts.PartItemStack;
import appeng.api.parts.SelectedPart;
import appeng.api.util.AEColor;
import appeng.api.util.AEPartLocation;
import appeng.block.AEBaseTileBlock;
import appeng.client.render.cablebus.CableBusBakedModel;
import appeng.client.render.cablebus.CableBusBreakingParticle;
import appeng.client.render.cablebus.CableBusRenderState;
import appeng.core.AppEng;
import appeng.helpers.AEGlassMaterial;
import appeng.integration.abstraction.IAEFacade;
import appeng.parts.ICableBusContainer;
import appeng.parts.NullCableBusContainer;
import appeng.tile.networking.CableBusBlockEntity;
import appeng.util.Platform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.event.client.player.ClientPickBlockGatherCallback;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.DyeColor;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.hit.HitResult.Type;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Random;
public class CableBusBlock extends AEBaseTileBlock<CableBusBlockEntity> implements IAEFacade {
private static final ICableBusContainer NULL_CABLE_BUS = new NullCableBusContainer();
public CableBusBlock() {
super(defaultProps(AEGlassMaterial.INSTANCE)
.nonOpaque()
.dropsNothing()
.dynamicBounds());
}
static {
ClientPickBlockGatherCallback.EVENT.register((player, result) -> {
if (result instanceof BlockHitResult) {
BlockHitResult blockResult = (BlockHitResult) result;
BlockState blockState = player.world.getBlockState(((BlockHitResult) result).getBlockPos());
if (blockState.getBlock() instanceof CableBusBlock) {
CableBusBlock cableBus = (CableBusBlock) blockState.getBlock();
return cableBus.getPickBlock(blockState,
result, player.world, blockResult.getBlockPos(), player);
}
}
return ItemStack.EMPTY;
});
}
@Override
public boolean isTranslucent(BlockState state, BlockView reader, BlockPos pos) {
return true;
}
@Override
@Environment(EnvType.CLIENT)
public void randomDisplayTick(final BlockState state, final World worldIn, final BlockPos pos, final Random rand) {
this.cb(worldIn, pos).randomDisplayTick(worldIn, pos, rand);
}
@Override
public int getWeakRedstonePower(final BlockState state, final BlockView w, final BlockPos pos, final Direction side) {
return this.cb(w, pos).isProvidingWeakPower(side.getOpposite()); // TODO:
// IS
// OPPOSITE!?
}
@Override
public boolean emitsRedstonePower(final BlockState state) {
return true;
}
@Override
public void onEntityCollision(BlockState state, World w, BlockPos pos, Entity entityIn) {
this.cb(w, pos).onEntityCollision(entityIn);
}
@Override
public int getStrongRedstonePower(BlockState state, BlockView world, BlockPos pos, Direction direction) {
return this.cb(world, pos).isProvidingStrongPower(direction.getOpposite()); // TODO:
// IS
// OPPOSITE!?
}
// FIXME Dynamic light seems unsupported (?) Must maybe use blockstates... :|
// FIXME FABRIC @Override
// FIXME FABRIC public int getLightValue(final BlockState state, final BlockView world, final BlockPos pos) {
// FIXME FABRIC if (state.getBlock() != this) {
// FIXME FABRIC return state.getLuminance();
// FIXME FABRIC }
// FIXME FABRIC return this.cb(world, pos).getLightValue();
// FIXME FABRIC }
// FIXME: Must hook isClimbing ourselves
// FIXME FABRIC @Override
// FIXME FABRIC public boolean isLadder(BlockState state, WorldView world, BlockPos pos, LivingEntity entity) {
// FIXME FABRIC return this.cb(world, pos).isLadder(entity);
// FIXME FABRIC }
@Override
public boolean canReplace(BlockState state, ItemPlacementContext context) {
// FIXME: Potentially check the fluid one too
return super.canReplace(state, context) && this.cb(context.getWorld(), context.getBlockPos()).isEmpty();
}
// FIXME FABRIC Hook does not exist
// FIXME FABRIC @Override
// FIXME FABRIC public boolean removedByPlayer(BlockState state, World world, BlockPos pos, PlayerEntity player,
// FIXME FABRIC boolean willHarvest, IFluidState fluid) {
// FIXME FABRIC if (player.abilities.isCreativeMode) {
// FIXME FABRIC final AEBaseBlockEntity tile = this.getBlockEntity(world, pos);
// FIXME FABRIC if (tile != null) {
// FIXME FABRIC tile.disableDrops();
// FIXME FABRIC }
// FIXME FABRIC // maybe ray trace?
// FIXME FABRIC }
// FIXME FABRIC return super.removedByPlayer(state, world, pos, player, willHarvest, fluid);
// FIXME FABRIC }
// FIXME FABRIC @Override
// FIXME FABRIC public boolean canConnectRedstone(final BlockState state, final BlockView w, final BlockPos pos,
// FIXME FABRIC Direction side) {
// FIXME FABRIC if (side == null) {
// FIXME FABRIC side = Direction.UP;
// FIXME FABRIC }
// FIXME FABRIC
// FIXME FABRIC return this.cb(w, pos).canConnectRedstone(EnumSet.of(side));
// FIXME FABRIC }
public ItemStack getPickBlock(BlockState state, HitResult target, BlockView world, BlockPos pos,
PlayerEntity player) {
final Vec3d v3 = target.getPos().subtract(pos.getX(), pos.getY(), pos.getZ());
final SelectedPart sp = this.cb(world, pos).selectPart(v3);
if (sp.part != null) {
return sp.part.getItemStack(PartItemStack.PICK);
} else if (sp.facade != null) {
return sp.facade.getItemStack();
}
return ItemStack.EMPTY;
}
// FIXME FABRIC MIXIN net.minecraft.client.particle.ParticleManager.addBlockBreakingParticles
@Environment(EnvType.CLIENT)
public boolean addHitEffects(final BlockState state, final World world, final HitResult target,
final ParticleManager effectRenderer) {
// Half the particle rate. Since we're spawning concentrated on a specific spot,
// our particle effect otherwise looks too strong
if (Platform.getRandom().nextBoolean()) {
return true;
}
if (target.getType() != Type.BLOCK) {
return false;
}
BlockPos blockPos = new BlockPos(target.getPos().x, target.getPos().y, target.getPos().z);
ICableBusContainer cb = this.cb(world, blockPos);
// Our built-in model has the actual baked sprites we need
BakedModel model = MinecraftClient.getInstance().getBlockRenderManager()
.getModel(this.getDefaultState());
// We cannot add the effect if we don't have the model
if (!(model instanceof CableBusBakedModel)) {
return true;
}
CableBusBakedModel cableBusModel = (CableBusBakedModel) model;
CableBusRenderState renderState = cb.getRenderState();
// Spawn a particle for one of the particle textures
Sprite texture = Platform.pickRandom(cableBusModel.getParticleTextures(renderState));
if (texture != null) {
double x = target.getPos().x;
double y = target.getPos().y;
double z = target.getPos().z;
// FIXME: Check how this looks, probably like shit, maybe provide parts the
// ability to supply particle textures???
effectRenderer
.addParticle(new CableBusBreakingParticle((ClientWorld) world, x, y, z, texture).scale(0.8F));
}
return true;
}
// FIXME FABRIC: Mixin to net.minecraft.client.particle.ParticleManager.addBlockBreakParticles
@Environment(EnvType.CLIENT)
public boolean addDestroyEffects(BlockState state, World world, BlockPos pos, ParticleManager effectRenderer) {
ICableBusContainer cb = this.cb(world, pos);
// Our built-in model has the actual baked sprites we need
BakedModel model = MinecraftClient.getInstance().getBlockRenderManager()
.getModel(this.getDefaultState());
// We cannot add the effect if we dont have the model
if (!(model instanceof CableBusBakedModel)) {
return true;
}
CableBusBakedModel cableBusModel = (CableBusBakedModel) model;
CableBusRenderState renderState = cb.getRenderState();
List<Sprite> textures = cableBusModel.getParticleTextures(renderState);
if (!textures.isEmpty()) {
// Shamelessly inspired by ParticleManager.addBlockDestroyEffects
for (int j = 0; j < 4; ++j) {
for (int k = 0; k < 4; ++k) {
for (int l = 0; l < 4; ++l) {
// Randomly select one of the textures if the cable bus has more than just one
// possibility here
final Sprite texture = Platform.pickRandom(textures);
final double x = pos.getX() + (j + 0.5D) / 4.0D;
final double y = pos.getY() + (k + 0.5D) / 4.0D;
final double z = pos.getZ() + (l + 0.5D) / 4.0D;
// FIXME: Check how this looks, probably like shit, maybe provide parts the
// ability to supply particle textures???
Particle effect = new CableBusBreakingParticle((ClientWorld) world, x, y, z, x - pos.getX() - 0.5D,
y - pos.getY() - 0.5D, z - pos.getZ() - 0.5D, texture);
effectRenderer.addParticle(effect);
}
}
}
}
return true;
}
@Override
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
if (Platform.isServer()) {
this.cb(world, pos).onneighborUpdate(world, pos, fromPos);
}
}
private ICableBusContainer cb(final BlockView w, final BlockPos pos) {
final BlockEntity te = w.getBlockEntity(pos);
ICableBusContainer out = null;
if (te instanceof CableBusBlockEntity) {
out = ((CableBusBlockEntity) te).getCableBus();
}
return out == null ? NULL_CABLE_BUS : out;
}
@Nullable
private IFacadeContainer fc(final BlockView w, final BlockPos pos) {
final BlockEntity te = w.getBlockEntity(pos);
IFacadeContainer out = null;
if (te instanceof CableBusBlockEntity) {
out = ((CableBusBlockEntity) te).getCableBus().getFacadeContainer();
}
return out;
}
@Environment(EnvType.CLIENT)
@Override
public void onBlockBreakStart(BlockState state, World worldIn, BlockPos pos, PlayerEntity player) {
if (worldIn.isClient()) {
final HitResult rtr = AppEng.instance().getRTR();
if (rtr instanceof BlockHitResult) {
BlockHitResult brtr = (BlockHitResult) rtr;
if (brtr.getBlockPos().equals(pos)) {
final Vec3d hitVec = rtr.getPos().subtract(new Vec3d(pos.getX(), pos.getY(), pos.getZ()));
if (this.cb(worldIn, pos).clicked(player, Hand.MAIN_HAND, hitVec)) {
throw new IllegalStateException();
// FIXME FABRIC NetworkHandler.instance().sendToServer(new ClickPacket(pos, brtr.getSide(), (float) hitVec.x,
// FIXME FABRIC (float) hitVec.y, (float) hitVec.z, Hand.MAIN_HAND, true));
}
}
}
}
}
public void onBlockClickPacket(World worldIn, BlockPos pos, PlayerEntity playerIn, Hand hand, Vec3d hitVec) {
this.cb(worldIn, pos).clicked(playerIn, hand, hitVec);
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity player, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
// Transform from world into block space
Vec3d hitVec = hit.getPos();
Vec3d hitInBlock = new Vec3d(hitVec.x - pos.getX(), hitVec.y - pos.getY(), hitVec.z - pos.getZ());
return this.cb(w, pos).activate(player, hand, hitInBlock) ? ActionResult.SUCCESS : ActionResult.PASS;
}
public boolean recolorBlock(final BlockView world, final BlockPos pos, final Direction side,
final DyeColor color, final PlayerEntity who) {
try {
return this.cb(world, pos).recolourBlock(side, AEColor.values()[color.ordinal()], who);
} catch (final Throwable ignored) {
}
return false;
}
@Override
public BlockState getFacadeState(BlockView world, BlockPos pos, Direction side) {
if (side != null) {
IFacadeContainer container = this.fc(world, pos);
if (container != null) {
IFacadePart facade = container.getFacade(AEPartLocation.fromFacing(side));
if (facade != null) {
return facade.getBlockState();
}
}
}
return world.getBlockState(pos);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView w, BlockPos pos, ShapeContext context) {
CableBusBlockEntity te = getBlockEntity(w, pos);
if (te == null) {
return VoxelShapes.empty();
} else {
return te.getCableBus().getOutlineShape();
}
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView w, BlockPos pos, ShapeContext context) {
CableBusBlockEntity te = getBlockEntity(w, pos);
if (te == null) {
return VoxelShapes.empty();
} else {
Entity entity = null;
// FIXME FABRIC: even EntityShapeContext doesn't give us the actual entity we're colliding with :|
return te.getCableBus().getCollisionShape(entity);
}
}
}
@@ -0,0 +1,58 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.networking;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.color.block.BlockColorProvider;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockRenderView;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.api.util.AEColor;
import appeng.parts.CableBusContainer;
import appeng.tile.networking.CableBusBlockEntity;
/**
* Exposes the cable bus color as tint indices 0 (dark variant), 1 (medium
* variant) and 2 (bright variant).
*/
@Environment(EnvType.CLIENT)
public class CableBusColor implements BlockColorProvider {
@Override
public int getColor(BlockState state, @Nullable BlockRenderView worldIn, @Nullable BlockPos pos, int color) {
AEColor busColor = AEColor.TRANSPARENT;
if (worldIn != null && pos != null) {
BlockEntity tileEntity = worldIn.getBlockEntity(pos);
if (tileEntity instanceof CableBusBlockEntity) {
CableBusContainer container = ((CableBusBlockEntity) tileEntity).getCableBus();
busColor = container.getColor();
}
}
return busColor.getVariantByTintIndex(color);
}
}
@@ -16,26 +16,28 @@
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.misc;
package appeng.block.networking;
import net.fabricmc.api.EnvType;
import net.minecraft.client.render.RenderLayer;
import net.fabricmc.api.Environment;
import appeng.api.util.AEColor;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
import appeng.client.render.ColorableTileBlockColor;
import appeng.client.render.StaticItemColor;
public class SecurityStationRendering extends BlockRenderingCustomizer {
/**
* Customizes the rendering behavior for cable busses, which are the biggest
* multipart of AE2.
*/
public class CableBusRendering extends BlockRenderingCustomizer {
@Override
@Environment(EnvType.CLIENT)
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
rendering.renderType(RenderLayer.getCutout());
rendering.blockColor(ColorableTileBlockColor.INSTANCE);
itemRendering.color(new StaticItemColor(AEColor.TRANSPARENT));
// FIXME This is straight up impossible in Vanilla, and questionable if it's actually needed.
// FIXME rendering.renderType(rt -> true);
rendering.blockColor(new CableBusColor());
rendering.modelCustomizer((loc, model) -> model);
}
}
@@ -1,140 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.networking;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.state.property.EnumProperty;
import net.minecraft.state.StateManager;
import net.minecraft.util.StringIdentifiable;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.tile.networking.ControllerBlockEntity;
public class ControllerBlock extends AEBaseTileBlock<ControllerBlockEntity> {
public enum ControllerBlockState implements StringIdentifiable {
offline, online, conflicted;
@Override
public String asString() {
return this.name();
}
}
/**
* Controls the rendering of the controller block (connected texture style).
* inside_a and inside_b are alternating patterns for a controller that is
* enclosed by other controllers, and since they are always offline, they do not
* have the usual sub-states.
*/
public enum ControllerRenderType implements StringIdentifiable {
block, column_x, column_y, column_z, inside_a, inside_b;
@Override
public String asString() {
return this.name();
}
}
public static final EnumProperty<ControllerBlockState> CONTROLLER_STATE = EnumProperty.create("state",
ControllerBlockState.class);
public static final EnumProperty<ControllerRenderType> CONTROLLER_TYPE = EnumProperty.create("type",
ControllerRenderType.class);
public ControllerBlock() {
super(defaultProps(Material.METAL).strength(6));
this.setDefaultState(this.getDefaultState().with(CONTROLLER_STATE, ControllerBlockState.offline)
.with(CONTROLLER_TYPE, ControllerRenderType.block));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(CONTROLLER_STATE);
builder.add(CONTROLLER_TYPE);
}
/**
* This will compute the AE_BLOCK_FORWARD, AE_BLOCK_UP and CONTROLLER_TYPE block
* states based on adjacent controllers and the network state of this controller
* (offline, online, conflicted). This is used to get a rudimentary connected
* texture feel for the controller based on how it is placed.
*/
@Override
public BlockState getStateForNeighborUpdate(BlockState state, Direction facing, BlockState facingState, WorldAccess world,
BlockPos pos, BlockPos facingPos) {
// FIXME: this might work, or might _NOT_ work, but needs to be investigated
// Only used for columns, really
ControllerRenderType type = ControllerRenderType.block;
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
// Detect whether controllers are on both sides of the x, y, and z axes
final boolean xx = this.getBlockEntity(world, x - 1, y, z) != null
&& this.getBlockEntity(world, x + 1, y, z) != null;
final boolean yy = this.getBlockEntity(world, x, y - 1, z) != null
&& this.getBlockEntity(world, x, y + 1, z) != null;
final boolean zz = this.getBlockEntity(world, x, y, z - 1) != null
&& this.getBlockEntity(world, x, y, z + 1) != null;
if (xx && !yy && !zz) {
type = ControllerRenderType.column_x;
} else if (!xx && yy && !zz) {
type = ControllerRenderType.column_y;
} else if (!xx && !yy && zz) {
type = ControllerRenderType.column_z;
} else if ((xx ? 1 : 0) + (yy ? 1 : 0) + (zz ? 1 : 0) >= 2) {
final int v = (Math.abs(x) + Math.abs(y) + Math.abs(z)) % 2;
// While i'd like this to be based on the blockstate randomization feature, this
// generates
// an alternating pattern based on world position, so this is not 100% doable
// with blockstates.
if (v == 0) {
type = ControllerRenderType.inside_a;
} else {
type = ControllerRenderType.inside_b;
}
}
return state.with(CONTROLLER_TYPE, type);
}
@Override
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
final ControllerBlockEntity tc = this.getBlockEntity(world, pos);
if (tc != null) {
tc.onNeighborChange(false);
}
}
}
@@ -1,34 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.networking;
import net.minecraft.client.render.RenderLayer;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
public class ControllerRendering extends BlockRenderingCustomizer {
@Override
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
// Disables the default model rotator
rendering.modelCustomizer((loc, model) -> model);
rendering.renderType(RenderLayer.getCutout());
}
}
@@ -1,30 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.networking;
import appeng.block.AEBaseTileBlock;
import appeng.helpers.AEGlassMaterial;
import appeng.tile.networking.CreativeEnergyCellBlockEntity;
public class CreativeEnergyCellBlock extends AEBaseTileBlock<CreativeEnergyCellBlockEntity> {
public CreativeEnergyCellBlock() {
super(defaultProps(AEGlassMaterial.INSTANCE));
}
}
@@ -1,31 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.networking;
public class DenseEnergyCellBlock extends EnergyCellBlock {
public DenseEnergyCellBlock() {
}
@Override
public double getMaxPower() {
return 200000.0 * 8.0;
}
}
@@ -1,31 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.networking;
import net.minecraft.block.Material;
import appeng.block.AEBaseTileBlock;
import appeng.tile.networking.EnergyAcceptorBlockEntity;
public class EnergyAcceptorBlock extends AEBaseTileBlock<EnergyAcceptorBlockEntity> {
public EnergyAcceptorBlock() {
super(defaultProps(Material.METAL));
}
}
@@ -1,67 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.networking;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.state.IntegerProperty;
import net.minecraft.state.StateManager;
import net.minecraft.util.collection.DefaultedList;
import appeng.block.AEBaseTileBlock;
import appeng.helpers.AEGlassMaterial;
import appeng.tile.networking.EnergyCellBlockEntity;
public class EnergyCellBlock extends AEBaseTileBlock<EnergyCellBlockEntity> {
public static final IntegerProperty ENERGY_STORAGE = IntegerProperty.create("fullness", 0, 7);
public EnergyCellBlock() {
super(defaultProps(AEGlassMaterial.INSTANCE));
}
@Override
@Environment(EnvType.CLIENT)
public void appendStacks(ItemGroup group, DefaultedList<ItemStack> itemStacks) {
super.appendStacks(group, itemStacks);
final ItemStack charged = new ItemStack(this, 1);
final CompoundTag tag = charged.getOrCreateTag();
tag.putDouble("internalCurrentPower", this.getMaxPower());
tag.putDouble("internalMaxPower", this.getMaxPower());
itemStacks.add(charged);
}
public double getMaxPower() {
return 200000.0;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(ENERGY_STORAGE);
}
}
@@ -1,228 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.networking;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.property.EnumProperty;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.StringIdentifiable;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.WirelessContainer;
import appeng.helpers.AEGlassMaterial;
import appeng.tile.networking.WirelessBlockEntity;
import appeng.util.Platform;
public class WirelessBlock extends AEBaseTileBlock<WirelessBlockEntity> {
enum State implements StringIdentifiable {
OFF, ON, HAS_CHANNEL;
@Override
public String asString() {
return this.name().toLowerCase();
}
}
public static final EnumProperty<State> STATE = EnumProperty.create("state", State.class);
public WirelessBlock() {
super(defaultProps(AEGlassMaterial.INSTANCE)
.nonOpaque()
.solidBlock((state, world, pos) -> false)
);
this.setDefaultState(this.getDefaultState().with(STATE, State.OFF));
}
@Override
protected BlockState updateBlockStateFromTileEntity(BlockState currentState, WirelessBlockEntity te) {
State teState = State.OFF;
if (te.isActive()) {
teState = State.HAS_CHANNEL;
} else if (te.isPowered()) {
teState = State.ON;
}
return currentState.with(STATE, teState);
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(STATE);
}
@Override
public ActionResult onUse(BlockState state, World w, BlockPos pos, PlayerEntity player, Hand hand,
BlockHitResult hit) {
final WirelessBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null && !player.isInSneakingPose()) {
if (Platform.isServer()) {
ContainerOpener.openContainer(WirelessContainer.TYPE, player,
ContainerLocator.forTileEntitySide(tg, hit.getSide()));
}
return ActionResult.SUCCESS;
}
return super.onUse(state, w, pos, player, hand, hit);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView w, BlockPos pos, ShapeContext context) {
final WirelessBlockEntity tile = this.getBlockEntity(w, pos);
if (tile != null) {
final Direction forward = tile.getForward();
double minX = 0;
double minY = 0;
double minZ = 0;
double maxX = 1;
double maxY = 1;
double maxZ = 1;
switch (forward) {
case DOWN:
minZ = minX = 3.0 / 16.0;
maxZ = maxX = 13.0 / 16.0;
maxY = 1.0;
minY = 5.0 / 16.0;
break;
case EAST:
minZ = minY = 3.0 / 16.0;
maxZ = maxY = 13.0 / 16.0;
maxX = 11.0 / 16.0;
minX = 0.0;
break;
case NORTH:
minY = minX = 3.0 / 16.0;
maxY = maxX = 13.0 / 16.0;
maxZ = 1.0;
minZ = 5.0 / 16.0;
break;
case SOUTH:
minY = minX = 3.0 / 16.0;
maxY = maxX = 13.0 / 16.0;
maxZ = 11.0 / 16.0;
minZ = 0.0;
break;
case UP:
minZ = minX = 3.0 / 16.0;
maxZ = maxX = 13.0 / 16.0;
maxY = 11.0 / 16.0;
minY = 0.0;
break;
case WEST:
minZ = minY = 3.0 / 16.0;
maxZ = maxY = 13.0 / 16.0;
maxX = 1.0;
minX = 5.0 / 16.0;
break;
default:
break;
}
return VoxelShapes.cuboid(new Box(minX, minY, minZ, maxX, maxY, maxZ));
}
return VoxelShapes.empty();
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView w, BlockPos pos, ShapeContext context) {
final WirelessBlockEntity tile = this.getBlockEntity(w, pos);
if (tile != null) {
final Direction forward = tile.getForward();
double minX = 0;
double minY = 0;
double minZ = 0;
double maxX = 1;
double maxY = 1;
double maxZ = 1;
switch (forward) {
case DOWN:
minZ = minX = 3.0 / 16.0;
maxZ = maxX = 13.0 / 16.0;
maxY = 1.0;
minY = 5.0 / 16.0;
break;
case EAST:
minZ = minY = 3.0 / 16.0;
maxZ = maxY = 13.0 / 16.0;
maxX = 11.0 / 16.0;
minX = 0.0;
break;
case NORTH:
minY = minX = 3.0 / 16.0;
maxY = maxX = 13.0 / 16.0;
maxZ = 1.0;
minZ = 5.0 / 16.0;
break;
case SOUTH:
minY = minX = 3.0 / 16.0;
maxY = maxX = 13.0 / 16.0;
maxZ = 11.0 / 16.0;
minZ = 0.0;
break;
case UP:
minZ = minX = 3.0 / 16.0;
maxZ = maxX = 13.0 / 16.0;
maxY = 11.0 / 16.0;
minY = 0.0;
break;
case WEST:
minZ = minY = 3.0 / 16.0;
maxZ = maxY = 13.0 / 16.0;
maxX = 1.0;
minX = 5.0 / 16.0;
break;
default:
break;
}
return VoxelShapes.cuboid(new Box(minX, minY, minZ, maxX, maxY, maxZ));
} else {
return VoxelShapes.empty();
}
}
@Override
public boolean isTranslucent(BlockState state, BlockView reader, BlockPos pos) {
return true;
}
}
@@ -1,21 +0,0 @@
package appeng.block.networking;
import net.minecraft.client.render.RenderLayer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.api.util.AEColor;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
import appeng.client.render.StaticBlockColor;
public class WirelessRendering extends BlockRenderingCustomizer {
@Override
@Environment(EnvType.CLIENT)
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
rendering.renderType(RenderLayer.getCutout());
rendering.blockColor(new StaticBlockColor(AEColor.TRANSPARENT));
}
}
@@ -1,27 +0,0 @@
package appeng.block.paint;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.ImmutableList;
import appeng.helpers.Splotch;
/**
* Used to transfer the state about paint splotches from the game thread to the
* render thread.
*/
public class PaintSplotches {
private final List<Splotch> splotches;
public PaintSplotches(Collection<Splotch> splotches) {
this.splotches = ImmutableList.copyOf(splotches);
}
List<Splotch> getSplotches() {
return this.splotches;
}
}
@@ -1,177 +0,0 @@
package appeng.block.paint;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
import appeng.client.render.cablebus.CubeBuilder;
import appeng.core.AppEng;
import appeng.helpers.Splotch;
import appeng.tile.misc.PaintSplotchesBlockEntity;
/**
* Renders paint blocks, which render multiple "splotches" that have been
* applied to the sides of adjacent blocks using a matter cannon with paint
* balls.
*/
class PaintSplotchesBakedModel implements IDynamicBakedModel {
private static final SpriteIdentifier TEXTURE_PAINT1 = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "block/paint1"));
private static final SpriteIdentifier TEXTURE_PAINT2 = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "block/paint2"));
private static final SpriteIdentifier TEXTURE_PAINT3 = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "block/paint3"));
private final Sprite[] textures;
PaintSplotchesBakedModel(Function<SpriteIdentifier, Sprite> bakedTextureGetter) {
this.textures = new Sprite[] { bakedTextureGetter.apply(TEXTURE_PAINT1),
bakedTextureGetter.apply(TEXTURE_PAINT2), bakedTextureGetter.apply(TEXTURE_PAINT3) };
}
@Nonnull
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand,
@Nonnull IModelData extraData) {
if (side != null) {
return Collections.emptyList();
}
PaintSplotches splotchesState = extraData.getData(PaintSplotchesBlockEntity.SPLOTCHES);
if (splotchesState == null) {
// This is the inventory model which should usually not be used other than in
// special cases
List<BakedQuad> quads = new ArrayList<>(1);
CubeBuilder builder = new CubeBuilder(quads);
builder.setTexture(this.textures[0]);
builder.addCube(0, 0, 0, 16, 16, 16);
return quads;
}
List<Splotch> splotches = splotchesState.getSplotches();
CubeBuilder builder = new CubeBuilder();
float offsetConstant = 0.001f;
for (final Splotch s : splotches) {
if (s.isLumen()) {
builder.setColorRGB(s.getColor().whiteVariant);
builder.setRenderFullBright(true);
} else {
builder.setColorRGB(s.getColor().mediumVariant);
builder.setRenderFullBright(false);
}
float offset = offsetConstant;
offsetConstant += 0.001f;
final float buffer = 0.1f;
float pos_x = s.x();
float pos_y = s.y();
pos_x = Math.max(buffer, Math.min(1.0f - buffer, pos_x));
pos_y = Math.max(buffer, Math.min(1.0f - buffer, pos_y));
Sprite ico = this.textures[s.getSeed() % this.textures.length];
builder.setTexture(ico);
builder.setCustomUv(s.getSide().getOpposite(), 0, 0, 16, 16);
switch (s.getSide()) {
case UP:
offset = 1.0f - offset;
builder.addQuad(Direction.DOWN, pos_x - buffer, offset, pos_y - buffer, pos_x + buffer, offset,
pos_y + buffer);
break;
case DOWN:
builder.addQuad(Direction.UP, pos_x - buffer, offset, pos_y - buffer, pos_x + buffer, offset,
pos_y + buffer);
break;
case EAST:
offset = 1.0f - offset;
builder.addQuad(Direction.WEST, offset, pos_x - buffer, pos_y - buffer, offset, pos_x + buffer,
pos_y + buffer);
break;
case WEST:
builder.addQuad(Direction.EAST, offset, pos_x - buffer, pos_y - buffer, offset, pos_x + buffer,
pos_y + buffer);
break;
case SOUTH:
offset = 1.0f - offset;
builder.addQuad(Direction.NORTH, pos_x - buffer, pos_y - buffer, offset, pos_x + buffer,
pos_y + buffer, offset);
break;
case NORTH:
builder.addQuad(Direction.SOUTH, pos_x - buffer, pos_y - buffer, offset, pos_x + buffer,
pos_y + buffer, offset);
break;
default:
}
}
return builder.getOutput();
}
@Override
public boolean useAmbientOcclusion() {
return false;
}
@Override
public boolean hasDepth() {
return true;
}
@Override
public boolean isBuiltin() {
return false;
}
@Override
public Sprite getSprite() {
return this.textures[0];
}
@Override
public ModelOverrideList getOverrides() {
return ModelOverrideList.EMPTY;
}
@Override
public boolean isSideLit() {
return false;
}
static List<SpriteIdentifier> getRequiredTextures() {
return ImmutableList.of(TEXTURE_PAINT1, TEXTURE_PAINT2, TEXTURE_PAINT3);
}
}
@@ -1,104 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.paint;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.block.MaterialColor;
import net.minecraft.fluid.Fluid;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.block.AEBaseTileBlock;
import appeng.tile.misc.PaintSplotchesBlockEntity;
import appeng.util.Platform;
public class PaintSplotchesBlock extends AEBaseTileBlock<PaintSplotchesBlockEntity> {
public PaintSplotchesBlock() {
super(defaultProps(Material.WATER, MaterialColor.CLEAR));
this.setFullSize(false);
this.setOpaque(false);
}
@Override
@Environment(EnvType.CLIENT)
public void appendStacks(ItemGroup group, DefaultedList<ItemStack> itemStacks) {
// do nothing
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView worldIn, BlockPos pos, ShapeContext context) {
return VoxelShapes.empty();
}
@Override
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
final PaintSplotchesBlockEntity tp = this.getBlockEntity(world, pos);
if (tp != null) {
tp.neighborUpdate();
}
}
@Override
public void fillWithRain(final World w, final BlockPos pos) {
if (Platform.isServer()) {
w.removeBlock(pos, false);
}
}
@Override
public int getLightValue(final BlockState state, final BlockView w, final BlockPos pos) {
final PaintSplotchesBlockEntity tp = this.getBlockEntity(w, pos);
if (tp != null) {
return tp.getLightLevel();
}
return 0;
}
@Override
public boolean isAir(final BlockState state, final BlockView world, final BlockPos pos) {
return true;
}
@Override
public boolean isReplaceable(BlockState state, ItemPlacementContext useContext) {
return true;
}
@Override
public boolean isReplaceable(BlockState p_225541_1_, Fluid p_225541_2_) {
return true;
}
}
@@ -1,36 +0,0 @@
package appeng.block.paint;
import java.util.Collection;
import java.util.Set;
import java.util.function.Function;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.IModelTransform;
import net.minecraft.client.render.model.IUnbakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
public class PaintSplotchesModel implements IModelGeometry<PaintSplotchesModel> {
@Override
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
ModelOverrideList overrides, Identifier modelLocation) {
return new PaintSplotchesBakedModel(spriteGetter);
}
@Override
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return PaintSplotchesBakedModel.getRequiredTextures();
}
}
@@ -1,21 +0,0 @@
package appeng.block.paint;
import net.minecraft.client.render.RenderLayer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
public class PaintSplotchesRendering extends BlockRenderingCustomizer {
@Override
@Environment(EnvType.CLIENT)
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
rendering.renderType(RenderLayer.getCutout());
// Disable auto rotation
rendering.modelCustomizer((location, model) -> model);
}
}
@@ -1,227 +0,0 @@
package appeng.block.qnb;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
import appeng.api.AEApi;
import appeng.client.render.cablebus.CubeBuilder;
import appeng.core.AppEng;
import appeng.tile.qnb.QuantumBridgeBlockEntity;
class QnbFormedBakedModel implements IDynamicBakedModel {
private static final SpriteIdentifier TEXTURE_LINK = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "block/quantum_link"));
private static final SpriteIdentifier TEXTURE_RING = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "block/quantum_ring"));
private static final SpriteIdentifier TEXTURE_RING_LIGHT = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "block/quantum_ring_light"));
private static final SpriteIdentifier TEXTURE_RING_LIGHT_CORNER = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "block/quantum_ring_light_corner"));
private static final SpriteIdentifier TEXTURE_CABLE_GLASS = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "parts/cable/glass/transparent"));
private static final SpriteIdentifier TEXTURE_COVERED_CABLE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "parts/cable/covered/transparent"));
private static final float DEFAULT_RENDER_MIN = 2.0f;
private static final float DEFAULT_RENDER_MAX = 14.0f;
private static final float CORNER_POWERED_RENDER_MIN = 3.9f;
private static final float CORNER_POWERED_RENDER_MAX = 12.1f;
private static final float CENTER_POWERED_RENDER_MIN = -0.01f;
private static final float CENTER_POWERED_RENDER_MAX = 16.01f;
private final BakedModel baseModel;
private final Block linkBlock;
private final Sprite linkTexture;
private final Sprite ringTexture;
private final Sprite glassCableTexture;
private final Sprite coveredCableTexture;
private final Sprite lightTexture;
private final Sprite lightCornerTexture;
public QnbFormedBakedModel(BakedModel baseModel, Function<SpriteIdentifier, Sprite> bakedTextureGetter) {
this.baseModel = baseModel;
this.linkTexture = bakedTextureGetter.apply(TEXTURE_LINK);
this.ringTexture = bakedTextureGetter.apply(TEXTURE_RING);
this.glassCableTexture = bakedTextureGetter.apply(TEXTURE_CABLE_GLASS);
this.coveredCableTexture = bakedTextureGetter.apply(TEXTURE_COVERED_CABLE);
this.lightTexture = bakedTextureGetter.apply(TEXTURE_RING_LIGHT);
this.lightCornerTexture = bakedTextureGetter.apply(TEXTURE_RING_LIGHT_CORNER);
this.linkBlock = AEApi.instance().definitions().blocks().quantumLink().maybeBlock().orElse(null);
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand,
IModelData modelData) {
QnbFormedState formedState = modelData.getData(QuantumBridgeBlockEntity.FORMED_STATE);
if (formedState == null) {
return this.baseModel.getQuads(state, side, rand);
}
if (side != null) {
return Collections.emptyList();
}
return this.getQuads(formedState, state);
}
private List<BakedQuad> getQuads(QnbFormedState formedState, BlockState state) {
CubeBuilder builder = new CubeBuilder();
if (state.getBlock() == this.linkBlock) {
Set<Direction> sides = formedState.getAdjacentQuantumBridges();
this.renderCableAt(builder, 0.11f * 16, this.glassCableTexture, 0.141f * 16, sides);
this.renderCableAt(builder, 0.188f * 16, this.coveredCableTexture, 0.1875f * 16, sides);
builder.setTexture(this.linkTexture);
builder.addCube(DEFAULT_RENDER_MIN, DEFAULT_RENDER_MIN, DEFAULT_RENDER_MIN, DEFAULT_RENDER_MAX,
DEFAULT_RENDER_MAX, DEFAULT_RENDER_MAX);
} else {
if (formedState.isCorner()) {
this.renderCableAt(builder, 0.188f * 16, this.coveredCableTexture, 0.05f * 16,
formedState.getAdjacentQuantumBridges());
builder.setTexture(this.ringTexture);
builder.addCube(DEFAULT_RENDER_MIN, DEFAULT_RENDER_MIN, DEFAULT_RENDER_MIN, DEFAULT_RENDER_MAX,
DEFAULT_RENDER_MAX, DEFAULT_RENDER_MAX);
if (formedState.isPowered()) {
builder.setTexture(this.lightCornerTexture);
builder.setRenderFullBright(true);
for (Direction facing : Direction.values()) {
// Offset the face by a slight amount so that it is drawn over the already drawn
// ring texture
// (avoids z-fighting)
float xOffset = Math.abs(facing.getOffsetX() * 0.01f);
float yOffset = Math.abs(facing.getOffsetY() * 0.01f);
float zOffset = Math.abs(facing.getOffsetZ() * 0.01f);
builder.setDrawFaces(EnumSet.of(facing));
builder.addCube(DEFAULT_RENDER_MIN - xOffset, DEFAULT_RENDER_MIN - yOffset,
DEFAULT_RENDER_MIN - zOffset, DEFAULT_RENDER_MAX + xOffset,
DEFAULT_RENDER_MAX + yOffset, DEFAULT_RENDER_MAX + zOffset);
}
}
} else {
builder.setTexture(this.ringTexture);
builder.addCube(0, DEFAULT_RENDER_MIN, DEFAULT_RENDER_MIN, 16, DEFAULT_RENDER_MAX, DEFAULT_RENDER_MAX);
builder.addCube(DEFAULT_RENDER_MIN, 0, DEFAULT_RENDER_MIN, DEFAULT_RENDER_MAX, 16, DEFAULT_RENDER_MAX);
builder.addCube(DEFAULT_RENDER_MIN, DEFAULT_RENDER_MIN, 0, DEFAULT_RENDER_MAX, DEFAULT_RENDER_MAX, 16);
if (formedState.isPowered()) {
builder.setTexture(this.lightTexture);
builder.setRenderFullBright(true);
for (Direction facing : Direction.values()) {
// Offset the face by a slight amount so that it is drawn over the already drawn
// ring texture
// (avoids z-fighting)
float xOffset = Math.abs(facing.getOffsetX() * 0.01f);
float yOffset = Math.abs(facing.getOffsetY() * 0.01f);
float zOffset = Math.abs(facing.getOffsetZ() * 0.01f);
builder.setDrawFaces(EnumSet.of(facing));
builder.addCube(-xOffset, -yOffset, -zOffset, 16 + xOffset, 16 + yOffset, 16 + zOffset);
}
}
}
}
return builder.getOutput();
}
private void renderCableAt(CubeBuilder builder, float thickness, Sprite texture, float pull,
Set<Direction> connections) {
builder.setTexture(texture);
if (connections.contains(Direction.WEST)) {
builder.addCube(0, 8 - thickness, 8 - thickness, 8 - thickness - pull, 8 + thickness, 8 + thickness);
}
if (connections.contains(Direction.EAST)) {
builder.addCube(8 + thickness + pull, 8 - thickness, 8 - thickness, 16, 8 + thickness, 8 + thickness);
}
if (connections.contains(Direction.NORTH)) {
builder.addCube(8 - thickness, 8 - thickness, 0, 8 + thickness, 8 + thickness, 8 - thickness - pull);
}
if (connections.contains(Direction.SOUTH)) {
builder.addCube(8 - thickness, 8 - thickness, 8 + thickness + pull, 8 + thickness, 8 + thickness, 16);
}
if (connections.contains(Direction.DOWN)) {
builder.addCube(8 - thickness, 0, 8 - thickness, 8 + thickness, 8 - thickness - pull, 8 + thickness);
}
if (connections.contains(Direction.UP)) {
builder.addCube(8 - thickness, 8 + thickness + pull, 8 - thickness, 8 + thickness, 16, 8 + thickness);
}
}
@Override
public boolean useAmbientOcclusion() {
return this.baseModel.useAmbientOcclusion();
}
@Override
public boolean hasDepth() {
return true;
}
@Override
public boolean isSideLit() {
return false;
}
@Override
public boolean isBuiltin() {
return false;
}
@Override
public Sprite getSprite() {
return this.baseModel.getSprite();
}
@Override
public ModelOverrideList getOverrides() {
return this.baseModel.getOverrides();
}
public static List<SpriteIdentifier> getRequiredTextures() {
return ImmutableList.of(TEXTURE_LINK, TEXTURE_RING, TEXTURE_CABLE_GLASS, TEXTURE_COVERED_CABLE,
TEXTURE_RING_LIGHT, TEXTURE_RING_LIGHT_CORNER);
}
}
@@ -1,41 +0,0 @@
package appeng.block.qnb;
import java.util.Collection;
import java.util.Set;
import java.util.function.Function;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.IModelTransform;
import net.minecraft.client.render.model.IUnbakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import appeng.core.AppEng;
public class QnbFormedModel implements IModelGeometry<QnbFormedModel> {
private static final Identifier MODEL_RING = new Identifier(AppEng.MOD_ID, "block/qnb/ring");
@Override
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
ModelOverrideList overrides, Identifier modelLocation) {
BakedModel ringModel = bakery.getBakedModel(MODEL_RING, modelTransform, spriteGetter);
return new QnbFormedBakedModel(ringModel, spriteGetter);
}
@Override
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return QnbFormedBakedModel.getRequiredTextures();
}
}
@@ -1,34 +0,0 @@
package appeng.block.qnb;
import java.util.Set;
import net.minecraft.util.math.Direction;
public class QnbFormedState {
private final Set<Direction> adjacentQuantumBridges;
private final boolean corner;
private final boolean powered;
public QnbFormedState(Set<Direction> adjacentQuantumBridges, boolean corner, boolean powered) {
this.adjacentQuantumBridges = adjacentQuantumBridges;
this.corner = corner;
this.powered = powered;
}
public Set<Direction> getAdjacentQuantumBridges() {
return this.adjacentQuantumBridges;
}
public boolean isCorner() {
return this.corner;
}
public boolean isPowered() {
return this.powered;
}
}
@@ -1,92 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.qnb;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.StateManager;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.tile.qnb.QuantumBridgeBlockEntity;
public abstract class QuantumBaseBlock extends AEBaseTileBlock<QuantumBridgeBlockEntity> {
public static final BooleanProperty FORMED = BooleanProperty.of("formed");
private static final VoxelShape SHAPE;
static {
final float shave = 2.0f / 16.0f;
SHAPE = VoxelShapes.cuboid(new Box(shave, shave, shave, 1.0f - shave, 1.0f - shave, 1.0f - shave));
}
public QuantumBaseBlock(Settings props) {
super(props);
this.setFullSize(this.setOpaque(false));
this.setDefaultState(this.getDefaultState().with(FORMED, false));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView worldIn, BlockPos pos, ShapeContext context) {
return SHAPE;
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(FORMED);
}
@Override
protected BlockState updateBlockStateFromTileEntity(BlockState currentState, QuantumBridgeBlockEntity te) {
return currentState.with(FORMED, te.isFormed());
}
@Override
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
final QuantumBridgeBlockEntity bridge = this.getBlockEntity(world, pos);
if (bridge != null) {
bridge.neighborUpdate();
}
}
@Override
public void onStateReplaced(BlockState state, World w, BlockPos pos, BlockState newState, boolean isMoving) {
if (newState.getBlock() == state.getBlock()) {
return; // Just a block state change
}
final QuantumBridgeBlockEntity bridge = this.getBlockEntity(w, pos);
if (bridge != null) {
bridge.breakCluster();
}
super.onStateReplaced(state, w, pos, newState, isMoving);
}
}
@@ -1,21 +0,0 @@
package appeng.block.qnb;
import net.minecraft.client.render.RenderLayer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
public class QuantumBridgeRendering extends BlockRenderingCustomizer {
@Override
@Environment(EnvType.CLIENT)
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
rendering.renderType(RenderLayer.getCutout());
// Disable auto rotation
rendering.modelCustomizer((location, model) -> model);
}
}
@@ -1,97 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.qnb;
import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import appeng.client.EffectType;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.QNBContainer;
import appeng.core.AppEng;
import appeng.helpers.AEGlassMaterial;
import appeng.tile.qnb.QuantumBridgeBlockEntity;
import appeng.util.Platform;
public class QuantumLinkChamberBlock extends QuantumBaseBlock {
private static final VoxelShape SHAPE;
static {
final double onePixel = 2.0 / 16.0;
SHAPE = VoxelShapes.cuboid(
new Box(onePixel, onePixel, onePixel, 1.0 - onePixel, 1.0 - onePixel, 1.0 - onePixel));
}
public QuantumLinkChamberBlock() {
super(defaultProps(AEGlassMaterial.INSTANCE));
}
@Override
public void randomDisplayTick(final BlockState state, final World w, final BlockPos pos, final Random rand) {
final QuantumBridgeBlockEntity bridge = this.getBlockEntity(w, pos);
if (bridge != null) {
if (bridge.hasQES()) {
if (AppEng.instance().shouldAddParticles(rand)) {
AppEng.instance().spawnEffect(EffectType.Energy, w, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5,
null);
}
}
}
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity p, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (p.isInSneakingPose()) {
return ActionResult.PASS;
}
final QuantumBridgeBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null) {
if (Platform.isServer()) {
ContainerOpener.openContainer(QNBContainer.TYPE, p, ContainerLocator.forTileEntity(tg));
}
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView worldIn, BlockPos pos, ShapeContext context) {
return SHAPE;
}
}
@@ -1,57 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.qnb;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import appeng.tile.qnb.QuantumBridgeBlockEntity;
public class QuantumRingBlock extends QuantumBaseBlock {
private static final VoxelShape SHAPE = createShape(2.0 / 16.0);
private static final VoxelShape SHAPE_CORNER = createShape(4.0 / 16.0);
private static final VoxelShape SHAPE_FORMED = createShape(1.0 / 16.0);
public QuantumRingBlock() {
super(defaultProps(Material.METAL));
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView w, BlockPos pos, ShapeContext context) {
final QuantumBridgeBlockEntity bridge = this.getBlockEntity(w, pos);
if (bridge != null && bridge.isCorner()) {
return SHAPE_CORNER;
} else if (bridge != null && bridge.isFormed()) {
return SHAPE_FORMED;
}
return SHAPE;
}
private static VoxelShape createShape(double onePixel) {
return VoxelShapes.cuboid(
new Box(onePixel, onePixel, onePixel, 1.0 - onePixel, 1.0 - onePixel, 1.0 - onePixel));
}
}
@@ -1,104 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.spatial;
import net.fabricmc.api.Environment;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.block.MaterialColor;
import net.minecraft.block.piston.PistonBehavior;
import net.minecraft.entity.Entity;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.explosion.Explosion;
import net.minecraft.world.BlockView;
import net.minecraft.world.WorldView;
import net.minecraft.world.World;
import net.fabricmc.api.EnvType;
import appeng.block.AEBaseBlock;
/**
* This block is used to fill empty space in spatial dimensions and delinates
* the border of a spatial dimensions's usable space.
*/
public class MatrixFrameBlock extends AEBaseBlock {
private static final Material MATERIAL = new Material(MaterialColor.CLEAR, false, true, true, false, false, false,
false, PistonBehavior.PUSH_ONLY);
public MatrixFrameBlock() {
super(Settings.create(MATERIAL).strength(-1.0F, 6000000.0F).notSolid().noDrops());
}
@Override
public BlockRenderType getRenderType(BlockState state) {
return BlockRenderType.INVISIBLE;
}
@Override
@Environment(EnvType.CLIENT)
public void appendStacks(ItemGroup group, DefaultedList<ItemStack> itemStacks) {
// do nothing
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView worldIn, BlockPos pos,
ShapeContext context) {
return VoxelShapes.fullCube();
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView worldIn, BlockPos pos, ShapeContext context) {
// This also prevents any blocks from being placed on this block!
return VoxelShapes.empty();
}
@Override
public boolean canPlaceAt(BlockState state, WorldView worldIn, BlockPos pos) {
return false;
}
@Override
public void onExplosionDestroy(final World world, final BlockPos pos, final Explosion explosion) {
// Don't explode.
}
@Override
public boolean isTranslucent(BlockState state, BlockView reader, BlockPos pos) {
return true;
}
@Override
public float getAmbientOcclusionLightValue(BlockState state, BlockView worldIn, BlockPos pos) {
return 1.0f;
}
@Override
public boolean canEntityDestroy(final BlockState state, final BlockView world, final BlockPos pos,
final Entity entity) {
return false;
}
}
@@ -1,73 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.spatial;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.SpatialIOPortContainer;
import appeng.tile.spatial.SpatialIOPortBlockEntity;
import appeng.util.Platform;
public class SpatialIOPortBlock extends AEBaseTileBlock<SpatialIOPortBlockEntity> {
public SpatialIOPortBlock() {
super(defaultProps(Material.METAL));
}
@Override
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
final SpatialIOPortBlockEntity te = this.getBlockEntity(world, pos);
if (te != null) {
te.updateRedstoneState();
}
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity p, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (p.isInSneakingPose()) {
return ActionResult.PASS;
}
final SpatialIOPortBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null) {
if (Platform.isServer()) {
ContainerOpener.openContainer(SpatialIOPortContainer.TYPE, p,
ContainerLocator.forTileEntitySide(tg, hit.getSide()));
}
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
}
@@ -1,55 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.spatial;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.helpers.AEGlassMaterial;
import appeng.tile.spatial.SpatialPylonBlockEntity;
public class SpatialPylonBlock extends AEBaseTileBlock<SpatialPylonBlockEntity> {
public SpatialPylonBlock() {
super(defaultProps(AEGlassMaterial.INSTANCE));
}
@Override
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
final SpatialPylonBlockEntity tsp = this.getBlockEntity(world, pos);
if (tsp != null) {
tsp.neighborUpdate();
}
}
@Override
public int getLightValue(final BlockState state, final BlockView w, final BlockPos pos) {
final SpatialPylonBlockEntity tsp = this.getBlockEntity(w, pos);
if (tsp != null) {
return tsp.getLightValue();
}
return super.getLightValue(state, w, pos);
}
}
@@ -1,98 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.storage;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.state.property.EnumProperty;
import net.minecraft.state.StateManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.Util;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.ChestContainer;
import appeng.core.localization.PlayerMessages;
import appeng.tile.storage.ChestBlockEntity;
public class ChestBlock extends AEBaseTileBlock<ChestBlockEntity> {
private final static EnumProperty<DriveSlotState> SLOT_STATE = EnumProperty.create("slot_state",
DriveSlotState.class);
public ChestBlock() {
super(defaultProps(Material.METAL));
this.setDefaultState(this.getDefaultState().with(SLOT_STATE, DriveSlotState.EMPTY));
}
@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder);
builder.add(SLOT_STATE);
}
@Override
protected BlockState updateBlockStateFromTileEntity(BlockState currentState, ChestBlockEntity te) {
DriveSlotState slotState = DriveSlotState.EMPTY;
if (te.getCellCount() >= 1) {
slotState = DriveSlotState.fromCellStatus(te.getCellStatus(0));
}
// Power-state has to be checked separately
if (!te.isPowered() && slotState != DriveSlotState.EMPTY) {
slotState = DriveSlotState.OFFLINE;
}
return currentState.with(SLOT_STATE, slotState);
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity p, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
final ChestBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null && !p.isInSneakingPose()) {
if (w.isClient()) {
return ActionResult.SUCCESS;
}
if (hit.getSide() == tg.getUp()) {
if (!tg.openGui(p)) {
p.sendSystemMessage(PlayerMessages.ChestCannotReadStorageCell.get(), Util.NIL_UUID);
}
} else {
ContainerOpener.openContainer(ChestContainer.TYPE, p,
ContainerLocator.forTileEntitySide(tg, hit.getSide()));
}
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
}
@@ -1,44 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.storage;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.RenderLayer;
import appeng.api.util.AEColor;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
import appeng.client.render.ColorableTileBlockColor;
import appeng.client.render.StaticItemColor;
public class ChestRendering extends BlockRenderingCustomizer {
@Override
@Environment(EnvType.CLIENT)
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
rendering.renderType(RenderLayer.getCutout());
// I checked, the ME chest doesn't keep its color in item form
itemRendering.color(new StaticItemColor(AEColor.TRANSPARENT));
rendering.blockColor(new ColorableTileBlockColor());
}
}
@@ -1,61 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.storage;
import javax.annotation.Nullable;
import net.minecraft.block.Material;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.DriveContainer;
import appeng.tile.storage.DriveBlockEntity;
import appeng.util.Platform;
public class DriveBlock extends AEBaseTileBlock<DriveBlockEntity> {
public DriveBlock() {
super(defaultProps(Material.METAL));
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity p, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (p.isInSneakingPose()) {
return ActionResult.PASS;
}
final DriveBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null) {
if (Platform.isServer()) {
ContainerOpener.openContainer(DriveContainer.TYPE, p, ContainerLocator.forTileEntity(tg));
}
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
}
@@ -1,32 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.storage;
import net.minecraft.client.render.RenderLayer;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
public class DriveRendering extends BlockRenderingCustomizer {
@Override
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
rendering.renderType(RenderLayer.getCutout());
}
}
@@ -1,72 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.storage;
import net.minecraft.util.StringIdentifiable;
import appeng.api.storage.cells.CellState;
/**
* Describes the different states a single slot of a BlockDrive can be in in
* terms of rendering.
*/
public enum DriveSlotState implements StringIdentifiable {
// No cell in slot
EMPTY("empty"),
// Cell in slot, but unpowered
OFFLINE("offline"),
// Online and free space
ONLINE("online"),
// Types full, space left
TYPES_FULL("types_full"),
// Completely full
FULL("full");
private final String name;
DriveSlotState(String name) {
this.name = name;
}
@Override
public String asString() {
return this.name;
}
public static DriveSlotState fromCellStatus(CellState cellStatus) {
switch (cellStatus) {
default:
case ABSENT:
return DriveSlotState.EMPTY;
case EMPTY:
case NOT_EMPTY:
return DriveSlotState.ONLINE;
case TYPES_FULL:
return DriveSlotState.TYPES_FULL;
case FULL:
return DriveSlotState.FULL;
}
}
}
@@ -1,93 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.storage;
import com.google.common.base.Preconditions;
import net.minecraft.item.Item;
import appeng.api.implementations.tiles.IChestOrDrive;
import appeng.api.storage.cells.CellState;
/**
* Contains the full information about what the state of the slots in a
* BlockDrive is.
*/
public class DriveSlotsState {
private final Item[] cells;
private final DriveSlotState[] states;
public DriveSlotsState(Item[] cells, DriveSlotState[] states) {
Preconditions.checkArgument(cells.length == states.length);
this.cells = cells;
this.states = states;
}
public DriveSlotState getState(int index) {
if (index >= this.states.length) {
return DriveSlotState.EMPTY;
}
return this.states[index];
}
public Item getCell(int index) {
if (index >= this.cells.length) {
return null;
}
return this.cells[index];
}
public int getSlotCount() {
return this.cells.length;
}
/**
* Retrieve an array that describes the state of each slot in this drive or
* chest.
*/
public static DriveSlotsState fromChestOrDrive(IChestOrDrive chestOrDrive) {
DriveSlotState[] states = new DriveSlotState[chestOrDrive.getCellCount()];
Item[] cells = new Item[chestOrDrive.getCellCount()];
for (int i = 0; i < chestOrDrive.getCellCount(); i++) {
cells[i] = chestOrDrive.getCellItem(i);
if (!chestOrDrive.isPowered()) {
if (chestOrDrive.getCellStatus(i) != CellState.EMPTY) {
states[i] = DriveSlotState.OFFLINE;
} else {
states[i] = DriveSlotState.EMPTY;
}
} else {
states[i] = DriveSlotState.fromCellStatus(chestOrDrive.getCellStatus(i));
}
}
return new DriveSlotsState(cells, states);
}
public static DriveSlotsState createEmpty(int slotCount) {
DriveSlotState[] states = new DriveSlotState[slotCount];
Item[] cells = new Item[slotCount];
for (int i = 0; i < slotCount; i++) {
states[i] = DriveSlotState.EMPTY;
}
return new DriveSlotsState(cells, states);
}
}
@@ -1,73 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.storage;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.IOPortContainer;
import appeng.tile.storage.IOPortBlockEntity;
import appeng.util.Platform;
public class IOPortBlock extends AEBaseTileBlock<IOPortBlockEntity> {
public IOPortBlock() {
super(defaultProps(Material.METAL));
}
@Override
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
final IOPortBlockEntity te = this.getBlockEntity(world, pos);
if (te != null) {
te.updateRedstoneState();
}
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity p, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (p.isInSneakingPose()) {
return ActionResult.PASS;
}
final IOPortBlockEntity tg = this.getBlockEntity(w, pos);
if (tg != null) {
if (Platform.isServer()) {
ContainerOpener.openContainer(IOPortContainer.TYPE, p,
ContainerLocator.forTileEntitySide(tg, hit.getSide()));
}
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
}
@@ -0,0 +1,122 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.storage;
import javax.annotation.Nullable;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import appeng.block.AEBaseTileBlock;
import appeng.tile.storage.SkyChestBlockEntity;
import appeng.util.Platform;
public class SkyChestBlock extends AEBaseTileBlock<SkyChestBlockEntity> {
private static final double AABB_OFFSET_BOTTOM = 0.00;
private static final double AABB_OFFSET_SIDES = 0.06;
private static final double AABB_OFFSET_TOP = 0.125;
public enum SkyChestType {
STONE, BLOCK
};
public final SkyChestType type;
public SkyChestBlock(final SkyChestType type, Settings props) {
super(props);
this.type = type;
}
@Override
public BlockRenderType getRenderType(BlockState state) {
return BlockRenderType.ENTITYBLOCK_ANIMATED;
}
@Override
public boolean isTranslucent(BlockState state, BlockView reader, BlockPos pos) {
return true;
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity player, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
if (Platform.isServer()) {
SkyChestBlockEntity tile = getBlockEntity(w, pos);
if (tile == null) {
return ActionResult.PASS;
}
throw new IllegalStateException();
// FIXME FABRIC ContainerOpener.openContainer(SkyChestContainer.TYPE, player, ContainerLocator.forTileEntity(tile));
}
return ActionResult.SUCCESS;
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView worldIn, BlockPos pos, ShapeContext context) {
// TODO Cache this! It can't be that hard!
Box aabb = computeAABB(worldIn, pos);
return VoxelShapes.cuboid(aabb);
}
private Box computeAABB(final BlockView w, final BlockPos pos) {
final SkyChestBlockEntity sk = this.getBlockEntity(w, pos);
Direction o = Direction.UP;
if (sk != null) {
o = sk.getUp();
}
final double offsetX = o.getOffsetX() == 0 ? AABB_OFFSET_SIDES : 0.0;
final double offsetY = o.getOffsetY() == 0 ? AABB_OFFSET_SIDES : 0.0;
final double offsetZ = o.getOffsetZ() == 0 ? AABB_OFFSET_SIDES : 0.0;
// for x/z top and bottom is swapped
final double minX = Math.max(0.0,
offsetX + (o.getOffsetX() < 0 ? AABB_OFFSET_BOTTOM : (o.getOffsetX() * AABB_OFFSET_TOP)));
final double minY = Math.max(0.0,
offsetY + (o.getOffsetY() < 0 ? AABB_OFFSET_TOP : (o.getOffsetY() * AABB_OFFSET_BOTTOM)));
final double minZ = Math.max(0.0,
offsetZ + (o.getOffsetZ() < 0 ? AABB_OFFSET_BOTTOM : (o.getOffsetZ() * AABB_OFFSET_TOP)));
final double maxX = Math.min(1.0,
1.0 - offsetX - (o.getOffsetX() < 0 ? AABB_OFFSET_TOP : (o.getOffsetX() * AABB_OFFSET_BOTTOM)));
final double maxY = Math.min(1.0,
1.0 - offsetY - (o.getOffsetY() < 0 ? AABB_OFFSET_BOTTOM : (o.getOffsetY() * AABB_OFFSET_TOP)));
final double maxZ = Math.min(1.0,
1.0 - offsetZ - (o.getOffsetZ() < 0 ? AABB_OFFSET_TOP : (o.getOffsetZ() * AABB_OFFSET_BOTTOM)));
return new Box(minX, minY, minZ, maxX, maxY, maxZ);
}
}