Moving code around

This commit is contained in:
Sebastian Hartte
2020-06-28 00:51:00 +02:00
parent 7f049e099d
commit 7c28a71e10
7 changed files with 0 additions and 0 deletions
-226
View File
@@ -1,226 +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;
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 ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity player, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
return ActionResult.PASS;
}
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;
}
}
@@ -1,155 +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;
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.block.networking.WirelessBlock;
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 (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) {
((IGridProxyable) tile).getProxy().setOwner(player);
}
tile.onPlacement(context);
} else if (this.blockType instanceof IOrientableBlock) {
ori.setOrientation(forward, up);
}
return ActionResult.SUCCESS;
}
}
@@ -1,153 +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;
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);
}
}
@@ -1,302 +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;
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.item.FixedItemInv;
import com.google.common.collect.Lists;
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.block.networking.CableBusBlock;
import appeng.tile.AEBaseInvBlockEntity;
import appeng.tile.AEBaseBlockEntity;
import appeng.tile.networking.CableBusBlockEntity;
import appeng.tile.storage.SkyChestBlockEntity;
import appeng.util.Platform;
import appeng.util.SettingsFrom;
public abstract class AEBaseTileBlock<T extends AEBaseBlockEntity> extends AEBaseBlock implements BlockEntityProvider {
@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 (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 && !(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);
}
@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;
}
}
@@ -1,44 +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.items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
public abstract class AEBaseItem extends Item {
public AEBaseItem(Item.Settings properties) {
super(properties);
}
@Override
public String toString() {
Identifier id = Registry.ITEM.getId(this);
String regName = id != Registry.ITEM.getDefaultId() ? id.getPath() : "unregistered";
return this.getClass().getSimpleName() + "[" + regName + "]";
}
@Override
public boolean canRepair(ItemStack stack, ItemStack ingredient) {
return false;
}
}
@@ -1,420 +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.tile;
import alexiil.mc.lib.attributes.item.ItemTransferable;
import appeng.api.implementations.tiles.ISegmentedInventory;
import appeng.api.util.ICommonTile;
import appeng.api.util.IConfigManager;
import appeng.api.util.IConfigurableObject;
import appeng.api.util.IOrientable;
import appeng.block.AEBaseTileBlock;
import appeng.client.render.model.AEModelData;
import appeng.core.AELog;
import appeng.core.features.IStackSrc;
import appeng.helpers.ICustomNameObject;
import appeng.helpers.IPriorityHost;
import appeng.hooks.TickHandler;
import appeng.tile.inventory.AppEngInternalAEInventory;
import appeng.util.Platform;
import appeng.util.SettingsFrom;
import io.netty.buffer.Unpooled;
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable;
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachmentBlockEntity;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AEBaseBlockEntity extends BlockEntity implements IOrientable, ICommonTile, ICustomNameObject, BlockEntityClientSerializable, RenderAttachmentBlockEntity {
private static final ThreadLocal<WeakReference<AEBaseBlockEntity>> DROP_NO_ITEMS = new ThreadLocal<>();
private static final Map<Class<? extends BlockEntity>, IStackSrc> ITEM_STACKS = new HashMap<>();
private int renderFragment = 0;
@Nullable
private String customName;
private Direction forward = Direction.NORTH;
private Direction up = Direction.UP;
private boolean markDirtyQueued = false;
public AEBaseBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
}
public static void registerTileItem(final Class<? extends BlockEntity> c, final IStackSrc wat) {
ITEM_STACKS.put(c, wat);
}
public boolean dropItems() {
final WeakReference<AEBaseBlockEntity> what = DROP_NO_ITEMS.get();
return what == null || what.get() != this;
}
public boolean notLoaded() {
return !this.world.isChunkLoaded(this.pos);
}
@Nonnull
public BlockEntity getTile() {
return this;
}
@Nullable
protected ItemStack getItemFromTile(final Object obj) {
final IStackSrc src = ITEM_STACKS.get(obj.getClass());
if (src == null) {
return ItemStack.EMPTY;
}
return src.stack(1);
}
@Override
public void fromTag(BlockState state, final CompoundTag data) {
super.fromTag(state, data);
if (data.contains("customName")) {
this.customName = data.getString("customName");
} else {
this.customName = null;
}
try {
if (this.canBeRotated()) {
this.forward = Direction.valueOf(data.getString("forward"));
this.up = Direction.valueOf(data.getString("up"));
}
} catch (final IllegalArgumentException ignored) {
}
}
@Override
public CompoundTag toTag(final CompoundTag data) {
super.toTag(data);
if (this.canBeRotated()) {
data.putString("forward", this.getForward().name());
data.putString("up", this.getUp().name());
}
if (this.customName != null) {
data.putString("customName", this.customName);
}
return data;
}
public void onReady() {
}
private boolean readUpdateData(PacketByteBuf stream) {
boolean output = false;
try {
this.renderFragment = 100;
output = this.readFromStream(stream);
if ((this.renderFragment & 1) == 1) {
output = true;
}
this.renderFragment = 0;
} catch (final Throwable t) {
AELog.debug(t);
}
return output;
}
@Override
public CompoundTag toClientTag(CompoundTag data) {
boolean finished = false;
final PacketByteBuf stream = new PacketByteBuf(Unpooled.buffer());
try {
this.writeToStream(stream);
if (stream.readableBytes() == 0) {
finished = true;
}
} catch (final Throwable t) {
AELog.debug(t);
}
if (!finished) {
stream.capacity(stream.readableBytes());
data.putByteArray("X", stream.array());
}
return data;
}
/**
* Handles tile entites that are being received by the client as part of a full
* chunk.
*/
@Override
public void fromClientTag(CompoundTag tag) {
final PacketByteBuf stream = new PacketByteBuf(Unpooled.copiedBuffer(tag.getByteArray("X")));
if (this.readUpdateData(stream)) {
this.markForUpdate();
}
}
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
if (this.canBeRotated()) {
final Direction old_Forward = this.forward;
final Direction old_Up = this.up;
final byte orientation = data.readByte();
this.forward = Direction.values()[orientation & 0x7];
this.up = Direction.values()[orientation >> 3];
return this.forward != old_Forward || this.up != old_Up;
}
return false;
}
protected void writeToStream(final PacketByteBuf data) throws IOException {
if (this.canBeRotated()) {
final byte orientation = (byte) ((this.up.ordinal() << 3) | this.forward.ordinal());
data.writeByte(orientation);
}
}
public void markForUpdate() {
if (this.renderFragment > 0) {
this.renderFragment |= 1;
} else {
// TODO: Optimize Network Load
if (this.world != null) {
boolean alreadyUpdated = false;
// Let the block update it's own state with our internal state changes
BlockState currentState = getCachedState();
if (currentState.getBlock() instanceof AEBaseTileBlock) {
AEBaseTileBlock<?> tileBlock = (AEBaseTileBlock<?>) currentState.getBlock();
BlockState newState = tileBlock.getBlockEntityBlockState(currentState, this);
if (currentState != newState) {
AELog.blockUpdate(this.pos, currentState, newState, this);
this.world.setBlockState(pos, newState);
alreadyUpdated = true;
}
}
if (!alreadyUpdated) {
this.world.updateListeners(this.pos, currentState, currentState, 1);
}
}
}
}
/**
* By default all blocks can have orientation, this handles saving, and loading,
* as well as synchronization.
*
* @return true if tile can be rotated
*/
@Override
public boolean canBeRotated() {
return true;
}
@Override
public Direction getForward() {
return this.forward;
}
@Override
public Direction getUp() {
return this.up;
}
@Override
public void setOrientation(final Direction inForward, final Direction inUp) {
this.forward = inForward;
this.up = inUp;
this.markForUpdate();
Platform.notifyBlocksOfNeighbors(this.world, this.pos);
}
public void onPlacement(ItemPlacementContext context) {
ItemStack stack = context.getStack();
if (stack.hasTag()) {
this.uploadSettings(SettingsFrom.DISMANTLE_ITEM, stack.getTag());
}
}
/**
* depending on the from, different settings will be accepted, don't call this
* with null
*
* @param from source of settings
* @param compound compound of source
*/
public void uploadSettings(final SettingsFrom from, final CompoundTag compound) {
if (this instanceof IConfigurableObject) {
final IConfigManager cm = ((IConfigurableObject) this).getConfigManager();
if (cm != null) {
cm.readFromNBT(compound);
}
}
if (this instanceof IPriorityHost) {
final IPriorityHost pHost = (IPriorityHost) this;
pHost.setPriority(compound.getInt("priority"));
}
if (this instanceof ISegmentedInventory) {
final ItemTransferable inv = ((ISegmentedInventory) this).getInventoryByName("config");
if (inv instanceof AppEngInternalAEInventory) {
final AppEngInternalAEInventory target = (AppEngInternalAEInventory) inv;
final AppEngInternalAEInventory tmp = new AppEngInternalAEInventory(null, target.getSlots());
tmp.readFromNBT(compound, "config");
for (int x = 0; x < tmp.getSlots(); x++) {
target.setStackInSlot(x, tmp.getStackInSlot(x));
}
}
}
}
/**
* returns the contents of the block entity, into the world, defaults to dropping
* everything in the inventory.
*
* @param w world
* @param pos block position
* @param drops drops of block entity
*/
@Override
public void getDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
}
public void getNoDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
}
/**
* null means nothing to store...
*
* @param from source of settings
*
* @return compound of source
*/
public CompoundTag downloadSettings(final SettingsFrom from) {
final CompoundTag output = new CompoundTag();
if (this.hasCustomInventoryName()) {
final CompoundTag dsp = new CompoundTag();
dsp.putString("Name", this.customName);
output.put("display", dsp);
}
if (this instanceof IConfigurableObject) {
final IConfigManager cm = ((IConfigurableObject) this).getConfigManager();
if (cm != null) {
cm.writeToNBT(output);
}
}
if (this instanceof IPriorityHost) {
final IPriorityHost pHost = (IPriorityHost) this;
output.putInt("priority", pHost.getPriority());
}
if (this instanceof ISegmentedInventory) {
final ItemTransferable inv = ((ISegmentedInventory) this).getInventoryByName("config");
if (inv instanceof AppEngInternalAEInventory) {
((AppEngInternalAEInventory) inv).writeToNBT(output, "config");
}
}
return output.isEmpty() ? null : output;
}
@Override
public Text getCustomInventoryName() {
return new LiteralText(
this.hasCustomInventoryName() ? this.customName : this.getClass().getSimpleName());
}
@Override
public boolean hasCustomInventoryName() {
return this.customName != null && !this.customName.isEmpty();
}
public void securityBreak() {
this.world.breakBlock(this.pos, true);
this.disableDrops();
}
/**
* Checks if this block entity is remote (we are running on the logical client
* side).
*/
public boolean isClient() {
World world = getWorld();
return world == null || world.isClient();
}
public void disableDrops() {
DROP_NO_ITEMS.set(new WeakReference<>(this));
}
public void saveChanges() {
if (this.world != null) {
this.world.markDirty(this.pos, this);
if (!this.markDirtyQueued) {
TickHandler.INSTANCE.addCallable(null, this::markDirtyAtEndOfTick);
this.markDirtyQueued = true;
}
}
}
private Object markDirtyAtEndOfTick(final World w) {
this.markDirty();
this.markDirtyQueued = false;
return null;
}
public void setName(final String name) {
this.customName = name;
}
@Override
public Object getRenderAttachmentData() {
return new AEModelData(up, forward);
}
}
@@ -1,119 +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.tile;
import java.util.List;
import javax.annotation.Nonnull;
import alexiil.mc.lib.attributes.item.FixedItemInv;
import alexiil.mc.lib.attributes.item.ItemTransferable;
import alexiil.mc.lib.attributes.item.impl.EmptyFixedItemInv;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.inv.IAEAppEngInventory;
import appeng.util.inv.InvOperation;
public abstract class AEBaseInvBlockEntity extends AEBaseBlockEntity implements IAEAppEngInventory {
public AEBaseInvBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
}
@Override
public void fromTag(BlockState state, final CompoundTag data) {
super.fromTag(state, data);
final ItemTransferable inv = this.getInternalInventory();
if (inv != EmptyFixedItemInv.INSTANCE) {
final CompoundTag opt = data.getCompound("inv");
for (int x = 0; x < inv.getSlots(); x++) {
final CompoundTag item = opt.getCompound("item" + x);
ItemHandlerUtil.setStackInSlot(inv, x, ItemStack.read(item));
}
}
}
public abstract @Nonnull
FixedItemInv getInternalInventory();
@Override
public CompoundTag toTag(final CompoundTag data) {
super.toTag(data);
final FixedItemInv inv = this.getInternalInventory();
if (inv != EmptyFixedItemInv.INSTANCE) {
final CompoundTag opt = new CompoundTag();
for (int x = 0; x < inv.getSlotCount(); x++) {
final CompoundTag item = new CompoundTag();
final ItemStack is = inv.getInvStack(x);
if (!is.isEmpty()) {
is.toTag(item);
}
opt.put("item" + x, item);
}
data.put("inv", opt);
}
return data;
}
@Override
public void getDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
final ItemTransferable inv = this.getInternalInventory();
for (int l = 0; l < inv.getSlots(); l++) {
final ItemStack is = inv.getStackInSlot(l);
if (!is.isEmpty()) {
drops.add(is);
}
}
}
@Override
public abstract void onChangeInventory(ItemTransferable inv, int slot, InvOperation mc, ItemStack removed,
ItemStack added);
protected @Nonnull
ItemTransferable getItemHandlerForSide(@Nonnull Direction side) {
return this.getInternalInventory();
}
@SuppressWarnings("unchecked")
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> capability, Direction facing) {
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
if (facing == null) {
return (LazyOptional<T>) LazyOptional.of(this::getInternalInventory);
} else {
return (LazyOptional<T>) LazyOptional.of(() -> getItemHandlerForSide(facing));
}
}
return super.getCapability(capability, facing);
}
}