Lots more moved

This commit is contained in:
Sebastian Hartte
2020-07-04 21:03:30 +02:00
parent 5982f094ec
commit 1478e4c378
444 changed files with 4693 additions and 5235 deletions
@@ -0,0 +1,66 @@
/*
* 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.attributes;
import alexiil.mc.lib.attributes.Attribute;
import alexiil.mc.lib.attributes.Attributes;
import alexiil.mc.lib.attributes.SearchOptions;
import appeng.api.storage.IStorageMonitorableAccessor;
import appeng.parts.AEBasePart;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
/**
* Utility class that holds various attributes, both by AE2 and other Mods.
*/
public final class MEAttributes {
private MEAttributes() {
}
public static Attribute<IStorageMonitorableAccessor> STORAGE_MONITORABLE_ACCESSOR
= Attributes.createDefaulted(IStorageMonitorableAccessor.class, new NullMENetworkAccessor());
public static <T> T getFirstAttributeOnSide(Attribute<T> attribute, BlockEntity be, Direction side) {
World world = be.getWorld();
if (world == null) {
return null;
}
return attribute.getFirstOrNull(world, be.getPos().offset(side), SearchOptions.inDirection(side.getOpposite()));
}
// Convenience function to get an attribute of the block that is in front of a part
public static <T> T getAttributeInFrontOfPart(Attribute<T> attribute, AEBasePart part) {
BlockEntity self = part.getHost().getTile();
Direction direction = part.getSide().getFacing();
final World w = self.getWorld();
BlockPos neighborPos = self.getPos().offset(direction);
// Do not force-load a neighboring chunk for this.
ChunkPos chunkPos = new ChunkPos(neighborPos);
if (!w.getChunkManager().isChunkLoaded(chunkPos.x, chunkPos.z)) {
return null;
}
return attribute.getFirstOrNull(w, neighborPos, SearchOptions.inDirection(direction));
}
}
@@ -0,0 +1,32 @@
/*
* 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.attributes;
import appeng.api.networking.security.IActionSource;
import appeng.api.storage.IStorageMonitorable;
import appeng.api.storage.IStorageMonitorableAccessor;
class NullMENetworkAccessor implements IStorageMonitorableAccessor {
@Override
public IStorageMonitorable getInventory(IActionSource src) {
return null;
}
}
@@ -0,0 +1,100 @@
/*
* 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
}
}
@@ -0,0 +1,27 @@
/*
* 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);
}
}
@@ -0,0 +1,29 @@
/*
* 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);
}
}
@@ -0,0 +1,46 @@
/*
* 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.Item;
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);
}
// FIXME FABRIC needs to move to disassembly crafting recipes
// FIXME FABRIC @Override
// FIXME FABRIC public Item getRecipeRemainder() {
// FIXME FABRIC return AEApi.instance().definitions().blocks().craftingUnit().item();
// FIXME FABRIC }
// FIXME FABRIC
// FIXME FABRIC @Override
// FIXME FABRIC public boolean hasRecipeRemainder() {
// FIXME FABRIC return AEConfig.instance().isFeatureEnabled(AEFeature.ENABLE_DISASSEMBLY_CRAFTING);
// FIXME FABRIC }
}
@@ -0,0 +1,29 @@
/*
* 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);
}
}
@@ -0,0 +1,73 @@
/*
* 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);
}
}
@@ -0,0 +1,163 @@
/*
* 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 appeng.util.FakePlayer;
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 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 (FakePlayer.isFakePlayer(player) || 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));
}
}
}
@@ -0,0 +1,57 @@
/*
* 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;
}
}
@@ -0,0 +1,60 @@
/*
* 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;
}
}
@@ -0,0 +1,190 @@
/*
* 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).solidBlock((state, world, pos) -> false));
}
@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);
}
}
@@ -0,0 +1,63 @@
/*
* 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;
}
}
@@ -0,0 +1,68 @@
/*
* 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;
}
}
@@ -0,0 +1,20 @@
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);
}
}
@@ -0,0 +1,93 @@
/*
* 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,141 @@
/*
* 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);
}
}
}
@@ -0,0 +1,82 @@
/*
* 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,41 @@
/*
* 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.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 {
@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));
}
}
@@ -0,0 +1,126 @@
/*
* 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);
}
}
}
@@ -158,8 +158,8 @@ public class CableBusBlock extends AEBaseTileBlock<CableBusBlockEntity> implemen
// 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 boolean willHarvest, FluidState fluid) {
// FIXME FABRIC if (player.isCreative()) {
// FIXME FABRIC final AEBaseBlockEntity tile = this.getBlockEntity(world, pos);
// FIXME FABRIC if (tile != null) {
// FIXME FABRIC tile.disableDrops();
@@ -0,0 +1,140 @@
/*
* 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.tile.networking.ControllerBlockEntity;
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;
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.of("state",
ControllerBlockState.class);
public static final EnumProperty<ControllerRenderType> CONTROLLER_TYPE = EnumProperty.of("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);
}
}
}
@@ -0,0 +1,34 @@
/*
* 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());
}
}
@@ -0,0 +1,30 @@
/*
* 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.AEMaterials;
import appeng.tile.networking.CreativeEnergyCellBlockEntity;
public class CreativeEnergyCellBlock extends AEBaseTileBlock<CreativeEnergyCellBlockEntity> {
public CreativeEnergyCellBlock() {
super(defaultProps(AEMaterials.GLASS));
}
}
@@ -0,0 +1,31 @@
/*
* 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;
}
}
@@ -0,0 +1,31 @@
/*
* 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));
}
}
@@ -0,0 +1,64 @@
/*
* 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.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.IntProperty;
import net.minecraft.util.collection.DefaultedList;
import appeng.block.AEBaseTileBlock;
import appeng.helpers.AEMaterials;
import appeng.tile.networking.EnergyCellBlockEntity;
public class EnergyCellBlock extends AEBaseTileBlock<EnergyCellBlockEntity> {
public static final IntProperty ENERGY_STORAGE = IntProperty.of("fullness", 0, 7);
public EnergyCellBlock() {
super(defaultProps(AEMaterials.GLASS));
}
@Override
public void addStacksForDisplay(ItemGroup group, DefaultedList<ItemStack> itemStacks) {
super.addStacksForDisplay(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);
}
}
@@ -0,0 +1,228 @@
/*
* 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.AEMaterials;
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.of("state", State.class);
public WirelessBlock() {
super(defaultProps(AEMaterials.GLASS)
.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;
}
}
@@ -0,0 +1,21 @@
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));
}
}
@@ -0,0 +1,27 @@
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;
}
}
@@ -0,0 +1,184 @@
package appeng.block.paint;
import appeng.client.render.cablebus.CubeBuilder;
import appeng.core.AppEng;
import appeng.helpers.Splotch;
import com.google.common.collect.ImmutableList;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockRenderView;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* 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 BakedModel, FabricBakedModel {
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) };
}
@Override
public boolean isVanillaAdapter() {
return false;
}
@Override
public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier<Random> randomSupplier, RenderContext context) {
Object renderAttachment = ((RenderAttachedBlockView) blockView).getBlockEntityRenderAttachment(pos);
if (!(renderAttachment instanceof PaintSplotches)) {
return;
}
PaintSplotches splotchesState = (PaintSplotches) renderAttachment;
List<Splotch> splotches = splotchesState.getSplotches();
CubeBuilder builder = new CubeBuilder(context.getEmitter());
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:
}
}
}
@Override
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) {
return Collections.emptyList();
}
@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 ModelTransformation getTransformation() {
return null;
}
@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);
}
}
@@ -0,0 +1,92 @@
/*
* 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).solidBlock((state, world, pos) -> false)
.air());
}
@Override
public void addStacksForDisplay(ItemGroup group, DefaultedList<ItemStack> list) {
}
@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 rainTick(World world, BlockPos pos) {
if (Platform.isServer()) {
world.removeBlock(pos, false);
}
}
// FIXME FABRIC currently no equivalent
// FIXME FABRIC @Override
// FIXME FABRIC public int getLightValue(final BlockState state, final BlockView w, final BlockPos pos) {
// FIXME FABRIC final PaintSplotchesBlockEntity tp = this.getBlockEntity(w, pos);
// FIXME FABRIC if (tp != null) {
// FIXME FABRIC return tp.getLightLevel();
// FIXME FABRIC }
// FIXME FABRIC return 0;
// FIXME FABRIC }
@Override
public boolean canReplace(BlockState state, ItemPlacementContext context) {
return true;
}
}
@@ -0,0 +1,36 @@
package appeng.block.paint;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.util.Identifier;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
public class PaintSplotchesModel implements UnbakedModel {
@Nullable
@Override
public BakedModel bake(ModelLoader loader, Function<SpriteIdentifier, Sprite> textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
return new PaintSplotchesBakedModel(textureGetter);
}
@Override
public Collection<SpriteIdentifier> getTextureDependencies(Function<Identifier, UnbakedModel> unbakedModelGetter, Set<Pair<String, String>> unresolvedTextureReferences) {
return PaintSplotchesBakedModel.getRequiredTextures();
}
@Override
public Collection<Identifier> getModelDependencies() {
return Collections.emptyList();
}
}
@@ -0,0 +1,21 @@
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);
}
}
@@ -0,0 +1,34 @@
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;
}
}
@@ -0,0 +1,91 @@
/*
* 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.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);
}
}
@@ -0,0 +1,21 @@
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);
}
}
@@ -0,0 +1,97 @@
/*
* 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.AEMaterials;
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(AEMaterials.GLASS));
}
@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;
}
}
@@ -0,0 +1,57 @@
/*
* 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));
}
}
@@ -0,0 +1,89 @@
/*
* 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 appeng.block.AEBaseBlock;
import net.minecraft.block.*;
import net.minecraft.block.piston.PistonBehavior;
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.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldView;
import net.minecraft.world.explosion.Explosion;
/**
* 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, PistonBehavior.PUSH_ONLY);
public MatrixFrameBlock() {
super(Settings.of(MATERIAL).strength(-1.0F, 6000000.0F).solidBlock((state, world, pos) -> false).dropsNothing());
}
@Override
public BlockRenderType getRenderType(BlockState state) {
return BlockRenderType.INVISIBLE;
}
@Override
public void addStacksForDisplay(ItemGroup group, DefaultedList<ItemStack> list) {
// 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 onDestroyedByExplosion(World world, BlockPos pos, Explosion explosion) {
world.setBlockState(pos, getDefaultState(), 3);
}
@Override
public boolean isTranslucent(BlockState state, BlockView reader, BlockPos pos) {
return true;
}
@Override
public float getAmbientOcclusionLightLevel(BlockState state, BlockView world, BlockPos pos) {
return 1.0f;
}
}
@@ -0,0 +1,73 @@
/*
* 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;
}
}
@@ -0,0 +1,56 @@
/*
* 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.AEMaterials;
import appeng.tile.spatial.SpatialPylonBlockEntity;
public class SpatialPylonBlock extends AEBaseTileBlock<SpatialPylonBlockEntity> {
public SpatialPylonBlock() {
super(defaultProps(AEMaterials.GLASS));
}
@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();
}
}
// FIXME FABRIC Must use block states for dynamic lighting
// FIXME FABRIC @Override
// FIXME FABRIC public int getLightValue(final BlockState state, final BlockView w, final BlockPos pos) {
// FIXME FABRIC final SpatialPylonBlockEntity tsp = this.getBlockEntity(w, pos);
// FIXME FABRIC if (tsp != null) {
// FIXME FABRIC return tsp.getLightValue();
// FIXME FABRIC }
// FIXME FABRIC return super.getLightValue(state, w, pos);
// FIXME FABRIC }
}
@@ -20,6 +20,9 @@ package appeng.block.storage;
import javax.annotation.Nullable;
import appeng.container.ContainerLocator;
import appeng.container.ContainerOpener;
import appeng.container.implementations.ChestContainer;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
@@ -83,8 +86,8 @@ public class ChestBlock extends AEBaseTileBlock<ChestBlockEntity> {
p.sendSystemMessage(PlayerMessages.ChestCannotReadStorageCell.get(), Util.NIL_UUID);
}
} else {
// FIXME FABRIC ContainerOpener.openContainer(ChestContainer.TYPE, p,
// FIXME FABRIC ContainerLocator.forTileEntitySide(tg, hit.getSide()));
ContainerOpener.openContainer(ChestContainer.TYPE, p,
ContainerLocator.forTileEntitySide(tg, hit.getSide()));
throw new IllegalStateException();
}
@@ -0,0 +1,61 @@
/*
* 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;
}
}
@@ -0,0 +1,32 @@
/*
* 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());
}
}
@@ -0,0 +1,45 @@
/*
* 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;
/**
* Describes the type of cell present in a slot.
*/
public enum DriveSlotCellType implements StringIdentifiable {
EMPTY("empty"),
ITEM("item"),
FLUID("fluid");
private final String name;
DriveSlotCellType(String name) {
this.name = name;
}
@Override
public String asString() {
return this.name;
}
}
@@ -0,0 +1,93 @@
/*
* 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);
}
}
@@ -0,0 +1,73 @@
/*
* 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;
}
}
+59 -8
View File
@@ -6,9 +6,12 @@ import appeng.bootstrap.components.IClientSetupComponent;
import appeng.bootstrap.components.IItemColorRegistrationComponent;
import appeng.bootstrap.components.IModelBakeComponent;
import appeng.bootstrap.components.ITileEntityRegistrationComponent;
import appeng.client.gui.implementations.*;
import appeng.client.render.cablebus.CableBusModelLoader;
import appeng.client.render.effects.*;
import appeng.client.render.tesr.InscriberTESR;
import appeng.client.render.tesr.SkyChestTESR;
import appeng.container.implementations.*;
import appeng.core.Api;
import appeng.core.ApiDefinitions;
import appeng.core.AppEng;
@@ -24,9 +27,12 @@ import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.render.entity.ItemEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.InputUtil;
@@ -39,10 +45,7 @@ import net.minecraft.util.hit.HitResult;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -55,6 +58,8 @@ public final class AppEngClient extends AppEngBase {
private final ClientTickHandler tickHandler;
private final EnumMap<ActionKey, KeyBinding> bindings = new EnumMap<>(ActionKey.class);
public static AppEngClient instance() {
return (AppEngClient) AppEng.instance();
}
@@ -75,6 +80,7 @@ public final class AppEngClient extends AppEngBase {
registerEntityRenderers();
registerItemColors();
registerTextures();
registerScreens();
// On the client, we'll register for server startup/shutdown to properly setup WorldData
// each time the integrated server starts&stops
@@ -153,8 +159,8 @@ public final class AppEngClient extends AppEngBase {
}
@Override
public boolean isActionKey(@Nonnull ActionKey key, InputUtil.Key input) {
return false;
public boolean isActionKey(@Nonnull ActionKey key, int keyCode, int scanCode) {
return this.bindings.get(key).matchesKey(keyCode, scanCode);
}
protected void registerParticleRenderers() {
@@ -194,9 +200,9 @@ public final class AppEngClient extends AppEngBase {
}
public void registerTextures() {
// FIXME FABRIC InscriberTESR.registerTexture();
Stream<Collection<SpriteIdentifier>> sprites = Stream.of(
SkyChestTESR.SPRITES
SkyChestTESR.SPRITES,
InscriberTESR.SPRITES
);
// Group every needed sprite by atlas, since every atlas has their own event
@@ -241,4 +247,49 @@ public final class AppEngClient extends AppEngBase {
// FIXME FABRIC new CableBusModelLoader());
}
private void registerScreens() {
ScreenRegistry.register(GrinderContainer.TYPE, GrinderScreen::new);
ScreenRegistry.register(QNBContainer.TYPE, QNBScreen::new);
ScreenRegistry.register(SkyChestContainer.TYPE, SkyChestScreen::new);
ScreenRegistry.register(ChestContainer.TYPE, ChestScreen::new);
ScreenRegistry.register(WirelessContainer.TYPE, WirelessScreen::new);
// FIXME FABRIC ScreenRegistry.<MEMonitorableContainer, MEMonitorableScreen<MEMonitorableContainer>>register(
// FIXME FABRIC MEMonitorableContainer.TYPE, MEMonitorableScreen::new);
// FIXME FABRIC ScreenRegistry.register(MEPortableCellContainer.TYPE, MEPortableCellScreen::new);
// FIXME FABRIC ScreenRegistry.register(WirelessTermContainer.TYPE, WirelessTermScreen::new);
// FIXME FABRIC ScreenRegistry.register(NetworkStatusContainer.TYPE, NetworkStatusScreen::new);
// FIXME FABRIC ScreenRegistry.<CraftingCPUContainer, CraftingCPUScreen<CraftingCPUContainer>>register(
// FIXME FABRIC CraftingCPUContainer.TYPE, CraftingCPUScreen::new);
// FIXME FABRIC ScreenRegistry.register(NetworkToolContainer.TYPE, NetworkToolScreen::new);
// FIXME FABRIC ScreenRegistry.register(QuartzKnifeContainer.TYPE, QuartzKnifeScreen::new);
// FIXME FABRIC ScreenRegistry.register(DriveContainer.TYPE, DriveScreen::new);
// FIXME FABRIC ScreenRegistry.register(VibrationChamberContainer.TYPE, VibrationChamberScreen::new);
// FIXME FABRIC ScreenRegistry.register(CondenserContainer.TYPE, CondenserScreen::new);
// FIXME FABRIC ScreenRegistry.register(InterfaceContainer.TYPE, InterfaceScreen::new);
// FIXME FABRIC ScreenRegistry.register(FluidInterfaceContainer.TYPE, FluidInterfaceScreen::new);
// FIXME FABRIC ScreenRegistry.<UpgradeableContainer, UpgradeableScreen<UpgradeableContainer>>register(
// FIXME FABRIC UpgradeableContainer.TYPE, UpgradeableScreen::new);
// FIXME FABRIC ScreenRegistry.register(FluidIOContainer.TYPE, FluidIOScreen::new);
// FIXME FABRIC ScreenRegistry.register(IOPortContainer.TYPE, IOPortScreen::new);
// FIXME FABRIC ScreenRegistry.register(StorageBusContainer.TYPE, StorageBusScreen::new);
// FIXME FABRIC ScreenRegistry.register(FluidStorageBusContainer.TYPE, FluidStorageBusScreen::new);
// FIXME FABRIC ScreenRegistry.register(FormationPlaneContainer.TYPE, FormationPlaneScreen::new);
// FIXME FABRIC ScreenRegistry.register(FluidFormationPlaneContainer.TYPE, FluidFormationPlaneScreen::new);
// FIXME FABRIC ScreenRegistry.register(PriorityContainer.TYPE, PriorityScreen::new);
// FIXME FABRIC ScreenRegistry.register(SecurityStationContainer.TYPE, SecurityStationScreen::new);
// FIXME FABRIC ScreenRegistry.register(CraftingTermContainer.TYPE, CraftingTermScreen::new);
// FIXME FABRIC ScreenRegistry.register(PatternTermContainer.TYPE, PatternTermScreen::new);
// FIXME FABRIC ScreenRegistry.register(FluidTerminalContainer.TYPE, FluidTerminalScreen::new);
// FIXME FABRIC ScreenRegistry.register(LevelEmitterContainer.TYPE, LevelEmitterScreen::new);
// FIXME FABRIC ScreenRegistry.register(FluidLevelEmitterContainer.TYPE, FluidLevelEmitterScreen::new);
// FIXME FABRIC ScreenRegistry.register(SpatialIOPortContainer.TYPE, SpatialIOPortScreen::new);
// FIXME FABRIC ScreenRegistry.register(InscriberContainer.TYPE, InscriberScreen::new);
// FIXME FABRIC ScreenRegistry.register(CellWorkbenchContainer.TYPE, CellWorkbenchScreen::new);
// FIXME FABRIC ScreenRegistry.register(MolecularAssemblerContainer.TYPE, MolecularAssemblerScreen::new);
// FIXME FABRIC ScreenRegistry.register(CraftAmountContainer.TYPE, CraftAmountScreen::new);
// FIXME FABRIC ScreenRegistry.register(CraftConfirmContainer.TYPE, CraftConfirmScreen::new);
// FIXME FABRIC ScreenRegistry.register(InterfaceTerminalContainer.TYPE, InterfaceTerminalScreen::new);
// FIXME FABRIC ScreenRegistry.register(CraftingStatusContainer.TYPE, CraftingStatusScreen::new);
}
}
@@ -0,0 +1,89 @@
/*
* 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.client.gui;
import java.text.NumberFormat;
import java.util.List;
import java.util.Locale;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.slot.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import appeng.api.storage.data.IAEItemStack;
import appeng.client.me.SlotME;
import appeng.container.AEBaseContainer;
import appeng.core.AEConfig;
import appeng.core.localization.ButtonToolTips;
public abstract class AEBaseMEScreen<T extends AEBaseContainer> extends AEBaseScreen<T> {
public AEBaseMEScreen(T container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
}
@Override
protected void renderTooltip(MatrixStack matrices, final ItemStack stack, final int x, final int y) {
final Slot s = this.getSlot(x, y);
if (s instanceof SlotME && !stack.isEmpty()) {
final int bigNumber = AEConfig.instance().isUseLargeFonts() ? 999 : 9999;
IAEItemStack myStack = null;
final List<Text> currentToolTip = this.getTooltipFromItem(stack);
try {
final SlotME theSlotField = (SlotME) s;
myStack = theSlotField.getAEStack();
} catch (final Throwable ignore) {
}
if (myStack != null) {
if (myStack.getStackSize() > bigNumber || (myStack.getStackSize() > 1 && stack.isDamaged())) {
final String formattedAmount = NumberFormat.getNumberInstance(Locale.US)
.format(myStack.getStackSize());
currentToolTip.add(ButtonToolTips.ItemsStored.text(formattedAmount)
.formatted(Formatting.GRAY));
}
if (myStack.getCountRequestable() > 0) {
final String formattedAmount = NumberFormat.getNumberInstance(Locale.US)
.format(myStack.getCountRequestable());
currentToolTip.add(ButtonToolTips.ItemsRequestable.text(formattedAmount));
}
this.renderTooltip(matrices, currentToolTip, x, y);
return;
} else if (stack.getCount() > bigNumber) {
final String formattedAmount = NumberFormat.getNumberInstance(Locale.US).format(stack.getCount());
currentToolTip.add(ButtonToolTips.ItemsStored.text(formattedAmount).formatted(Formatting.GRAY));
this.renderTooltip(matrices, currentToolTip, x, y);
return;
}
}
super.renderTooltip(matrices, stack, x, y);
}
}
@@ -0,0 +1,782 @@
/*
* 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.client.gui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import appeng.mixins.SlotMixin;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.InputUtil;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.StringRenderable;
import net.minecraft.text.Style;
import net.minecraft.util.Formatting;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL11;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.text.Text;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEItemStack;
import appeng.client.gui.widgets.CustomSlotWidget;
import appeng.client.gui.widgets.ITooltip;
import appeng.client.gui.widgets.Scrollbar;
import appeng.client.me.InternalSlotME;
import appeng.client.me.SlotDisconnected;
import appeng.client.me.SlotME;
import appeng.client.render.StackSizeRenderer;
import appeng.container.AEBaseContainer;
import appeng.container.slot.AppEngCraftingSlot;
import appeng.container.slot.AppEngSlot;
import appeng.container.slot.AppEngSlot.CalculatedValidity;
import appeng.container.slot.CraftingTermSlot;
import appeng.container.slot.DisabledSlot;
import appeng.container.slot.FakeSlot;
import appeng.container.slot.IOptionalSlot;
import appeng.container.slot.InaccessibleSlot;
import appeng.container.slot.OutputSlot;
import appeng.container.slot.PatternTermSlot;
import appeng.container.slot.RestrictedInputSlot;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.InventoryActionPacket;
import appeng.core.sync.packets.SwapSlotsPacket;
import appeng.fluids.client.render.FluidStackSizeRenderer;
import appeng.fluids.container.slots.IMEFluidSlot;
import appeng.helpers.InventoryAction;
public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScreen<T> {
private final List<InternalSlotME> meSlots = new ArrayList<>();
// drag y
private final Set<Slot> drag_click = new HashSet<>();
private final StackSizeRenderer stackSizeRenderer = new StackSizeRenderer();
private final FluidStackSizeRenderer fluidStackSizeRenderer = new FluidStackSizeRenderer();
private Scrollbar myScrollBar = null;
private boolean disableShiftClick = false;
private Stopwatch dbl_clickTimer = Stopwatch.createStarted();
private ItemStack dbl_whichItem = ItemStack.EMPTY;
private Slot bl_clicked;
protected final List<CustomSlotWidget> guiSlots = new ArrayList<>();
public AEBaseScreen(T container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
}
public MinecraftClient getClient() {
return Preconditions.checkNotNull(client);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override
public void init() {
super.init();
final List<Slot> slots = this.getInventorySlots();
slots.removeIf(slot -> slot instanceof SlotME);
for (final InternalSlotME me : this.meSlots) {
slots.add(new SlotME(me));
}
}
private List<Slot> getInventorySlots() {
return this.handler.slots;
}
@Override
public void render(MatrixStack matrices, final int mouseX, final int mouseY, final float partialTicks) {
super.renderBackground(matrices);
super.render(matrices, mouseX, mouseY, partialTicks);
RenderSystem.pushMatrix();
RenderSystem.translatef(this.x, this.y, 0.0F);
RenderSystem.enableDepthTest();
for (final CustomSlotWidget c : this.guiSlots) {
this.drawGuiSlot(matrices, c, mouseX, mouseY, partialTicks);
}
RenderSystem.disableDepthTest();
for (final CustomSlotWidget c : this.guiSlots) {
this.drawTooltip(matrices, c, mouseX - this.x, mouseY - this.y);
}
RenderSystem.popMatrix();
RenderSystem.enableDepthTest();
this.drawMouseoverTooltip(matrices, mouseX, mouseY);
for (final Object c : this.buttons) {
if (c instanceof ITooltip) {
this.drawTooltip(matrices, (ITooltip) c, mouseX, mouseY);
}
}
}
protected void drawGuiSlot(MatrixStack matrices, CustomSlotWidget slot, int mouseX, int mouseY, float partialTicks) {
if (slot.isSlotEnabled()) {
final int left = slot.xPos();
final int top = slot.yPos();
final int right = left + slot.getWidth();
final int bottom = top + slot.getHeight();
slot.drawContent(getClient(), mouseX, mouseY, partialTicks);
if (this.isPointWithinBounds(left, top, slot.getWidth(), slot.getHeight(), mouseX, mouseY)
&& slot.canClick(getPlayer())) {
RenderSystem.colorMask(true, true, true, false);
this.fillGradient(matrices, left, top, right, bottom, -2130706433, -2130706433);
RenderSystem.colorMask(true, true, true, true);
}
}
}
private void drawTooltip(MatrixStack matrices, ITooltip tooltip, int mouseX, int mouseY) {
final int x = tooltip.xPos(); // ((GuiImgButton) c).x;
int y = tooltip.yPos(); // ((GuiImgButton) c).y;
if (x < mouseX && x + tooltip.getWidth() > mouseX && tooltip.isVisible()) {
if (y < mouseY && y + tooltip.getHeight() > mouseY) {
if (y < 15) {
y = 15;
}
final Text msg = tooltip.getMessage();
if (msg != null) {
this.drawTooltip(matrices, x + 11, y + 4, msg);
}
}
}
}
protected void drawTooltip(MatrixStack matrices, int x, int y, Text message) {
String[] lines = message.getString().split("\n"); // FIXME FABRIC
this.drawTooltip(matrices, x, y, Arrays.asList(lines));
}
// FIXME FABRIC: move out to json (?)
private static final Style TOOLTIP_HEADER = Style.EMPTY.withColor(Formatting.WHITE);
private static final Style TOOLTIP_BODY = Style.EMPTY.withColor(Formatting.GRAY);
protected void drawTooltip(MatrixStack matrices, int x, int y, List<String> lines) {
if (lines.isEmpty()) {
return;
}
List<StringRenderable> renderableLines = new ArrayList<>(lines.size());
// Make the first line white
// All lines after the first are colored gray
for (int i = 0; i < lines.size(); i++) {
Style style = (i == 0) ? TOOLTIP_HEADER : TOOLTIP_BODY;
renderableLines.add(StringRenderable.styled(lines.get(0), style));
}
this.renderTooltip(matrices, renderableLines, x, y);
}
@Override
protected final void drawForeground(MatrixStack matrices, final int x, final int y) {
final int ox = this.x; // (width - xSize) / 2;
final int oy = this.y; // (height - ySize) / 2;
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
if (this.getScrollBar() != null) {
this.getScrollBar().draw(matrices, this);
}
this.drawFG(matrices, ox, oy, x, y);
}
public abstract void drawFG(MatrixStack matrices, int offsetX, int offsetY, int mouseX, int mouseY);
@Override
protected final void drawBackground(MatrixStack matrices, final float f, final int x, final int y) {
final int ox = this.x; // (width - xSize) / 2;
final int oy = this.y; // (height - ySize) / 2;
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
this.drawBG(matrices, ox, oy, x, y, f);
final List<Slot> slots = this.getInventorySlots();
for (final Slot slot : slots) {
if (slot instanceof IOptionalSlot) {
final IOptionalSlot optionalSlot = (IOptionalSlot) slot;
if (optionalSlot.isRenderDisabled()) {
final AppEngSlot aeSlot = (AppEngSlot) slot;
if (aeSlot.isSlotEnabled()) {
drawTexture(matrices, ox + aeSlot.x - 1, oy + aeSlot.y - 1,
optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1, 18, 18);
} else {
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 0.4F);
RenderSystem.enableBlend();
drawTexture(matrices, ox + aeSlot.x - 1, oy + aeSlot.y - 1,
optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1, 18, 18);
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
}
}
}
}
for (final CustomSlotWidget slot : this.guiSlots) {
slot.drawBackground(ox, oy, getZOffset());
}
}
@Override
public boolean mouseClicked(final double xCoord, final double yCoord, final int btn) {
this.drag_click.clear();
if (btn == 1) {
for (final Object o : this.buttons) {
final AbstractButtonWidget widget = (AbstractButtonWidget) o;
if (widget.isMouseOver(xCoord, yCoord)) {
return super.mouseClicked(xCoord, yCoord, 0);
}
}
}
for (CustomSlotWidget slot : this.guiSlots) {
if (this.isPointWithinBounds(slot.xPos(), slot.yPos(), slot.getWidth(), slot.getHeight(), xCoord, yCoord)
&& slot.canClick(getPlayer())) {
slot.slotClicked(getPlayer().inventory.getCursorStack(), btn);
}
}
if (this.getScrollBar() != null) {
this.getScrollBar().click(xCoord - this.x, yCoord - this.y);
}
return super.mouseClicked(xCoord, yCoord, btn);
}
@Override
public boolean mouseDragged(double mouseX, double mouseY, int mouseButton, double dragX, double dragY) {
final Slot slot = this.getSlot((int) mouseX, (int) mouseY);
final ItemStack itemstack = getPlayer().inventory.getCursorStack();
if (this.getScrollBar() != null) {
// FIXME: Coordinate system of mouseX/mouseY is unclear
this.getScrollBar().click((int) mouseX - this.x, (int) mouseY - this.y);
}
if (slot instanceof FakeSlot && !itemstack.isEmpty()) {
this.drag_click.add(slot);
if (this.drag_click.size() > 1) {
for (final Slot dr : this.drag_click) {
final InventoryActionPacket p = new InventoryActionPacket(
mouseButton == 0 ? InventoryAction.PICKUP_OR_SET_DOWN : InventoryAction.PLACE_SINGLE,
dr.id, 0);
NetworkHandler.instance().sendToServer(p);
}
}
return true;
} else {
return super.mouseDragged(mouseX, mouseY, mouseButton, dragX, dragY);
}
}
// TODO 1.9.4 aftermath - Whole SlotActionType thing, to be checked.
@Override
protected void onMouseClick(final Slot slot, final int slotIdx, final int mouseButton,
final SlotActionType clickType) {
final PlayerEntity player = getPlayer();
if (slot instanceof FakeSlot) {
final InventoryAction action = mouseButton == 1 ? InventoryAction.SPLIT_OR_PLACE_SINGLE
: InventoryAction.PICKUP_OR_SET_DOWN;
if (this.drag_click.size() > 1) {
return;
}
final InventoryActionPacket p = new InventoryActionPacket(action, slotIdx, 0);
NetworkHandler.instance().sendToServer(p);
return;
}
if (slot instanceof PatternTermSlot) {
if (mouseButton == 6) {
return; // prevent weird double clicks..
}
NetworkHandler.instance().sendToServer(((PatternTermSlot) slot).getRequest(hasShiftDown()));
} else if (slot instanceof CraftingTermSlot) {
if (mouseButton == 6) {
return; // prevent weird double clicks..
}
InventoryAction action;
if (hasShiftDown()) {
action = InventoryAction.CRAFT_SHIFT;
} else {
// Craft stack on right-click, craft single on left-click
action = (mouseButton == 1) ? InventoryAction.CRAFT_STACK : InventoryAction.CRAFT_ITEM;
}
final InventoryActionPacket p = new InventoryActionPacket(action, slotIdx, 0);
NetworkHandler.instance().sendToServer(p);
return;
}
if (InputUtil.isKeyPressed(MinecraftClient.getInstance().getWindow().getHandle(), GLFW.GLFW_KEY_SPACE)) {
if (this.enableSpaceClicking()) {
IAEItemStack stack = null;
if (slot instanceof SlotME) {
stack = ((SlotME) slot).getAEStack();
}
int slotNum = this.getInventorySlots().size();
if (!(slot instanceof SlotME) && slot != null) {
slotNum = slot.id;
}
this.handler.setTargetStack(stack);
final InventoryActionPacket p = new InventoryActionPacket(InventoryAction.MOVE_REGION, slotNum, 0);
NetworkHandler.instance().sendToServer(p);
return;
}
}
if (slot instanceof SlotDisconnected) {
InventoryAction action = null;
switch (clickType) {
case PICKUP: // pickup / set-down.
action = (mouseButton == 1) ? InventoryAction.SPLIT_OR_PLACE_SINGLE
: InventoryAction.PICKUP_OR_SET_DOWN;
break;
case QUICK_MOVE:
action = (mouseButton == 1) ? InventoryAction.PICKUP_SINGLE : InventoryAction.SHIFT_CLICK;
break;
case CLONE: // creative dupe:
if (player.isCreative()) {
action = InventoryAction.CREATIVE_DUPLICATE;
}
break;
default:
case THROW: // drop item:
}
if (action != null) {
final InventoryActionPacket p = new InventoryActionPacket(action, getSlotIndex(slot),
((SlotDisconnected) slot).getSlot().getId());
NetworkHandler.instance().sendToServer(p);
}
return;
}
if (slot instanceof SlotME) {
InventoryAction action = null;
IAEItemStack stack = null;
switch (clickType) {
case PICKUP: // pickup / set-down.
action = (mouseButton == 1) ? InventoryAction.SPLIT_OR_PLACE_SINGLE
: InventoryAction.PICKUP_OR_SET_DOWN;
stack = ((SlotME) slot).getAEStack();
if (stack != null && action == InventoryAction.PICKUP_OR_SET_DOWN && stack.getStackSize() == 0
&& player.inventory.getCursorStack().isEmpty()) {
action = InventoryAction.AUTO_CRAFT;
}
break;
case QUICK_MOVE:
action = (mouseButton == 1) ? InventoryAction.PICKUP_SINGLE : InventoryAction.SHIFT_CLICK;
stack = ((SlotME) slot).getAEStack();
break;
case CLONE: // creative dupe:
stack = ((SlotME) slot).getAEStack();
if (stack != null && stack.isCraftable()) {
action = InventoryAction.AUTO_CRAFT;
} else if (player.isCreative()) {
final IAEItemStack slotItem = ((SlotME) slot).getAEStack();
if (slotItem != null) {
action = InventoryAction.CREATIVE_DUPLICATE;
}
}
break;
default:
case THROW: // drop item:
}
if (action != null) {
this.handler.setTargetStack(stack);
final InventoryActionPacket p = new InventoryActionPacket(action, this.getInventorySlots().size(), 0);
NetworkHandler.instance().sendToServer(p);
}
return;
}
if (!this.disableShiftClick && hasShiftDown() && mouseButton == 0) {
this.disableShiftClick = true;
if (this.dbl_whichItem.isEmpty() || this.bl_clicked != slot
|| this.dbl_clickTimer.elapsed(TimeUnit.MILLISECONDS) > 250) {
// some simple double click logic.
this.bl_clicked = slot;
this.dbl_clickTimer = Stopwatch.createStarted();
if (slot != null) {
this.dbl_whichItem = slot.hasStack() ? slot.getStack().copy() : ItemStack.EMPTY;
} else {
this.dbl_whichItem = ItemStack.EMPTY;
}
} else if (!this.dbl_whichItem.isEmpty()) {
// a replica of the weird broken vanilla feature.
final List<Slot> slots = this.getInventorySlots();
for (final Slot inventorySlot : slots) {
if (inventorySlot != null && inventorySlot.canTakeItems(getPlayer()) && inventorySlot.hasStack()
&& inventorySlot.inventory == slot.inventory
&& ScreenHandler.canInsertItemIntoSlot(inventorySlot, this.dbl_whichItem, true)) {
this.onMouseClick(inventorySlot, inventorySlot.id, 0, SlotActionType.QUICK_MOVE);
}
}
this.dbl_whichItem = ItemStack.EMPTY;
}
this.disableShiftClick = false;
}
super.onMouseClick(slot, slotIdx, mouseButton, clickType);
}
protected ClientPlayerEntity getPlayer() {
// Our UIs are usually not opened when not in-game, so this should not be a
// problem
return Preconditions.checkNotNull(getClient().player);
}
protected int getSlotIndex(Slot slot) {
return ((SlotMixin)slot).getIndex();
}
protected boolean checkHotbarKeys(int keyCode, int scanCode) {
final Slot theSlot = this.focusedSlot;
if (getPlayer().inventory.getCursorStack().isEmpty() && theSlot != null) {
for (int j = 0; j < 9; ++j) {
if (getClient().options.keysHotbar[j].matchesKey(keyCode, scanCode)) {
final List<Slot> slots = this.getInventorySlots();
for (final Slot s : slots) {
if (getSlotIndex(s) == j && s.inventory == this.handler.getPlayerInv()) {
if (!s.canTakeItems(this.handler.getPlayerInv().player)) {
return false;
}
}
}
if (theSlot.getMaxStackAmount() == 64) {
this.onMouseClick(theSlot, theSlot.id, j, SlotActionType.SWAP);
return true;
} else {
for (final Slot s : slots) {
if (getSlotIndex(s) == j
&& s.inventory == this.handler.getPlayerInv()) {
NetworkHandler.instance()
.sendToServer(new SwapSlotsPacket(s.id, theSlot.id));
return true;
}
}
}
}
}
}
return false;
}
@Override
public void removed() {
super.removed();
}
protected Slot getSlot(final int mouseX, final int mouseY) {
final List<Slot> slots = this.getInventorySlots();
for (final Slot slot : slots) {
// isPointWithinBounds
if (this.isPointWithinBounds(slot.x, slot.y, 16, 16, mouseX, mouseY)) {
return slot;
}
}
return null;
}
public abstract void drawBG(MatrixStack matrices, int offsetX, int offsetY, int mouseX, int mouseY, float partialTicks);
@Override
public boolean mouseScrolled(double x, double y, double wheelDelta) {
if (wheelDelta != 0 && hasShiftDown()) {
this.mouseWheelEvent(x, y, wheelDelta / Math.abs(wheelDelta));
return true;
} else if (wheelDelta != 0 && this.getScrollBar() != null) {
this.getScrollBar().wheel(wheelDelta);
return true;
}
return false;
}
private void mouseWheelEvent(final double x, final double y, final double wheel) {
final Slot slot = this.getSlot((int) x, (int) y);
if (slot instanceof SlotME) {
final IAEItemStack item = ((SlotME) slot).getAEStack();
if (item != null) {
this.handler.setTargetStack(item);
final InventoryAction direction = wheel > 0 ? InventoryAction.ROLL_DOWN : InventoryAction.ROLL_UP;
final int times = (int) Math.abs(wheel);
final int inventorySize = this.getInventorySlots().size();
for (int h = 0; h < times; h++) {
final InventoryActionPacket p = new InventoryActionPacket(direction, inventorySize, 0);
NetworkHandler.instance().sendToServer(p);
}
}
}
}
protected boolean enableSpaceClicking() {
return true;
}
public void bindTexture(final String base, final String file) {
final Identifier loc = new Identifier(base, "textures/" + file);
getClient().getTextureManager().bindTexture(loc);
}
protected void drawItem(final int x, final int y, final ItemStack is) {
this.itemRenderer.zOffset = 100.0F;
this.itemRenderer.renderInGuiWithOverrides(is, x, y);
this.itemRenderer.zOffset = 0.0F;
}
protected String getGuiDisplayName(final String in) {
return this.hasCustomInventoryName() ? this.getInventoryName() : in;
}
private boolean hasCustomInventoryName() {
return this.handler.getCustomName() != null;
}
private String getInventoryName() {
return this.handler.getCustomName();
}
/**
* This overrides the base-class method through some access transformer
* hackery...
*/
@Override
public void drawSlot(MatrixStack matrices, Slot s) {
if (s instanceof SlotME) {
try {
if (!this.isPowered()) {
fill(matrices, s.x, s.y, 16 + s.x, 16 + s.y, 0x66111111);
}
// Annoying but easier than trying to splice into render item
super.drawSlot(matrices, new Size1Slot((SlotME) s));
this.stackSizeRenderer.renderStackSize(this.textRenderer, ((SlotME) s).getAEStack(), s.x, s.y);
} catch (final Exception err) {
AELog.warn("[AppEng] AE prevented crash while drawing slot: " + err.toString());
}
return;
} else if (s instanceof IMEFluidSlot && ((IMEFluidSlot) s).shouldRenderAsFluid()) {
final IMEFluidSlot slot = (IMEFluidSlot) s;
final IAEFluidStack fs = slot.getAEFluidStack();
if (fs != null && this.isPowered()) {
fs.getFluidStack().renderGuiRect(s.x, s.y, s.x + 16, s.y + 16);
this.fluidStackSizeRenderer.renderStackSize(this.textRenderer, fs, s.x, s.y);
} else if (!this.isPowered()) {
fill(matrices, s.x, s.y, 16 + s.x, 16 + s.y, 0x66111111);
}
return;
} else {
try {
final ItemStack is = s.getStack();
if (s instanceof AppEngSlot && (((AppEngSlot) s).renderIconWithItem() || is.isEmpty())
&& (((AppEngSlot) s).shouldDisplay())) {
final AppEngSlot aes = (AppEngSlot) s;
if (aes.getIcon() >= 0) {
this.bindTexture("guis/states.png");
try {
final int uv_y = aes.getIcon() / 16;
final int uv_x = aes.getIcon() - uv_y * 16;
RenderSystem.enableBlend();
RenderSystem.enableTexture();
RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
final float par1 = aes.x;
final float par2 = aes.y;
final float par3 = uv_x * 16;
final float par4 = uv_y * 16;
final Tessellator tessellator = Tessellator.getInstance();
final BufferBuilder vb = tessellator.getBuffer();
vb.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE);
final float f1 = 0.00390625F;
final float f = 0.00390625F;
final float par6 = 16;
vb.vertex(par1 + 0, par2 + par6, getZOffset())
.color(1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon())
.texture((par3 + 0) * f, (par4 + par6) * f1)
.next();
final float par5 = 16;
vb.vertex(par1 + par5, par2 + par6, getZOffset())
.color(1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon())
.texture((par3 + par5) * f, (par4 + par6) * f1)
.next();
vb.vertex(par1 + par5, par2 + 0, getZOffset())
.color(1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon())
.texture((par3 + par5) * f, (par4 + 0) * f1)
.next();
vb.vertex(par1 + 0, par2 + 0, getZOffset())
.color(1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon())
.texture((par3 + 0) * f, (par4 + 0) * f1)
.next();
tessellator.draw();
} catch (final Exception err) {
err.printStackTrace();
}
}
}
if (!is.isEmpty() && s instanceof AppEngSlot) {
AppEngSlot aeSlot = (AppEngSlot) s;
if (aeSlot.getIsValid() == CalculatedValidity.NotAvailable) {
boolean isValid = s.canInsert(is) || s instanceof OutputSlot
|| s instanceof AppEngCraftingSlot || s instanceof DisabledSlot
|| s instanceof InaccessibleSlot || s instanceof FakeSlot
|| s instanceof RestrictedInputSlot || s instanceof SlotDisconnected;
if (isValid && s instanceof RestrictedInputSlot) {
try {
isValid = ((RestrictedInputSlot) s).isValid(is, getClient().world);
} catch (final Exception err) {
AELog.debug(err);
}
}
aeSlot.setIsValid(isValid ? CalculatedValidity.Valid : CalculatedValidity.Invalid);
}
if (aeSlot.getIsValid() == CalculatedValidity.Invalid) {
setZOffset(100);
this.itemRenderer.zOffset = 100.0F;
fill(matrices, s.x, s.y, 16 + s.x, 16 + s.y, 0x66ff6666);
setZOffset(0);
this.itemRenderer.zOffset = 0.0F;
}
}
if (s instanceof AppEngSlot) {
((AppEngSlot) s).setDisplay(true);
super.drawSlot(matrices, s);
} else {
super.drawSlot(matrices, s);
}
return;
} catch (final Exception err) {
AELog.warn("[AppEng] AE prevented crash while drawing slot: " + err.toString());
}
}
// do the usual for non-ME Slots.
super.drawSlot(matrices, s);
}
protected boolean isPowered() {
return true;
}
public void bindTexture(final String file) {
final Identifier loc = new Identifier(AppEng.MOD_ID, "textures/" + file);
getClient().getTextureManager().bindTexture(loc);
}
public void bindTexture(final Identifier loc) {
getClient().getTextureManager().bindTexture(loc);
}
protected Scrollbar getScrollBar() {
return this.myScrollBar;
}
protected void setScrollBar(final Scrollbar myScrollBar) {
this.myScrollBar = myScrollBar;
}
protected List<InternalSlotME> getMeSlots() {
return this.meSlots;
}
}
@@ -0,0 +1,81 @@
package appeng.client.gui;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import appeng.client.me.SlotME;
import com.mojang.datafixers.util.Pair;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.screen.slot.Slot;
import net.minecraft.item.ItemStack;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.util.Identifier;
/**
* A proxy for a slot that will always return an itemstack with size 1, if there
* is an item in the slot. Used to prevent the default item count from
* rendering.
*/
class Size1Slot extends Slot {
private final SlotME delegate;
public Size1Slot(SlotME delegate) {
super(delegate.inventory, -1, delegate.x, delegate.y);
this.delegate = delegate;
}
@Override
@Nonnull
public ItemStack getStack() {
ItemStack orgStack = this.delegate.getStack();
if (!orgStack.isEmpty()) {
ItemStack modifiedStack = orgStack.copy();
modifiedStack.setCount(1);
return modifiedStack;
}
return ItemStack.EMPTY;
}
@Override
public boolean hasStack() {
return this.delegate.hasStack();
}
@Override
public int getMaxStackAmount() {
return this.delegate.getMaxStackAmount();
}
@Override
public int getMaxStackAmount(ItemStack stack) {
return this.delegate.getMaxStackAmount(stack);
}
@Override
public boolean canTakeItems(PlayerEntity playerIn) {
return this.delegate.canTakeItems(playerIn);
}
@Override
public void markDirty() {
delegate.markDirty();
}
@Override
@Environment(EnvType.CLIENT)
@Nullable
public Pair<Identifier, Identifier> getBackgroundSprite() {
return delegate.getBackgroundSprite();
}
@Override
@Environment(EnvType.CLIENT)
public boolean doDrawHoveringEffect() {
return delegate.doDrawHoveringEffect();
}
}
@@ -0,0 +1,114 @@
package appeng.client.gui.implementations;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.item.ItemStack;
import appeng.api.AEApi;
import appeng.api.definitions.IDefinitions;
import appeng.api.definitions.IParts;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.widgets.TabButton;
import appeng.container.implementations.ChestContainer;
import appeng.container.implementations.CraftingTermContainer;
import appeng.container.implementations.MEMonitorableContainer;
import appeng.container.implementations.PatternTermContainer;
import appeng.container.implementations.WirelessTermContainer;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.SwitchGuisPacket;
import appeng.helpers.IPriorityHost;
import appeng.helpers.WirelessTerminalGuiObject;
import appeng.parts.reporting.CraftingTerminalPart;
import appeng.parts.reporting.PatternTerminalPart;
import appeng.parts.reporting.TerminalPart;
import appeng.tile.storage.ChestBlockEntity;
import net.minecraft.text.Text;
/**
* Utility class for sub-screens of other containers that allow returning to the
* primary container UI.
*/
final class AESubScreen {
private final AEBaseScreen<?> gui;
private final ScreenHandlerType<?> previousContainerType;
private final ItemStack previousContainerIcon;
/**
* Based on the container we're opening for, try to determine what it's
* "primary" GUI would be so that we can go back to it.
*/
public AESubScreen(AEBaseScreen<?> gui, Object containerTarget) {
this.gui = gui;
final IDefinitions definitions = AEApi.instance().definitions();
final IParts parts = definitions.parts();
if (containerTarget instanceof ChestBlockEntity) {
// A chest is also a priority host, but the priority _interface_ can only be
// opened from the
// chest ui that doesn't actually show the contents of the inserted cell.
IPriorityHost priorityHost = (IPriorityHost) containerTarget;
this.previousContainerIcon = priorityHost.getItemStackRepresentation();
this.previousContainerType = ChestContainer.TYPE;
}
else if (containerTarget instanceof IPriorityHost) {
IPriorityHost priorityHost = (IPriorityHost) containerTarget;
this.previousContainerIcon = priorityHost.getItemStackRepresentation();
this.previousContainerType = priorityHost.getContainerType();
}
else if (containerTarget instanceof WirelessTerminalGuiObject) {
this.previousContainerIcon = definitions.items().wirelessTerminal().maybeStack(1).orElse(ItemStack.EMPTY);
this.previousContainerType = WirelessTermContainer.TYPE;
}
else if (containerTarget instanceof TerminalPart) {
this.previousContainerIcon = parts.terminal().maybeStack(1).orElse(ItemStack.EMPTY);
this.previousContainerType = MEMonitorableContainer.TYPE;
}
else if (containerTarget instanceof CraftingTerminalPart) {
this.previousContainerIcon = parts.craftingTerminal().maybeStack(1).orElse(ItemStack.EMPTY);
this.previousContainerType = CraftingTermContainer.TYPE;
}
else if (containerTarget instanceof PatternTerminalPart) {
this.previousContainerIcon = parts.patternTerminal().maybeStack(1).orElse(ItemStack.EMPTY);
this.previousContainerType = PatternTermContainer.TYPE;
}
else {
this.previousContainerIcon = null;
this.previousContainerType = null;
}
}
public final TabButton addBackButton(Consumer<TabButton> buttonAdder, int x, int y) {
return addBackButton(buttonAdder, x, y, null);
}
public final TabButton addBackButton(Consumer<TabButton> buttonAdder, int x, int y, @Nullable Text label) {
if (this.previousContainerType != null && !previousContainerIcon.isEmpty()) {
if (label == null) {
label = previousContainerIcon.getName();
}
ItemRenderer itemRenderer = gui.getClient().getItemRenderer();
TabButton button = new TabButton(gui.getX() + x, gui.getY() + y, previousContainerIcon, label,
itemRenderer, btn -> goBack());
buttonAdder.accept(button);
return button;
}
return null;
}
public final void goBack() {
NetworkHandler.instance().sendToServer(new SwitchGuisPacket(this.previousContainerType));
}
}
@@ -0,0 +1,64 @@
/*
* 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.client.gui.implementations;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.widgets.TabButton;
import appeng.container.implementations.ChestContainer;
import appeng.container.implementations.PriorityContainer;
import appeng.core.localization.GuiText;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.SwitchGuisPacket;
public class ChestScreen extends AEBaseScreen<ChestContainer> {
public ChestScreen(ChestContainer container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
this.backgroundHeight = 166;
}
@Override
public void init() {
super.init();
this.addButton(new TabButton(this.x + 154, this.y, 2 + 4 * 16, GuiText.Priority.textComponent(),
this.itemRenderer, btn -> openPriority()));
}
private void openPriority() {
NetworkHandler.instance().sendToServer(new SwitchGuisPacket(PriorityContainer.TYPE));
}
@Override
public void drawFG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
this.textRenderer.draw(matrices, this.getGuiDisplayName(GuiText.Chest.getLocal()), 8, 6, 4210752);
this.textRenderer.draw(matrices, GuiText.inventory.getLocal(), 8, this.backgroundHeight - 96 + 3, 4210752);
}
@Override
public void drawBG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY, float partialTicks) {
this.bindTexture("guis/chest.png");
drawTexture(matrices, offsetX, offsetY, 0, 0, this.backgroundWidth, this.backgroundHeight);
}
}
@@ -0,0 +1,48 @@
/*
* 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.client.gui.implementations;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
import appeng.client.gui.AEBaseScreen;
import appeng.container.implementations.GrinderContainer;
import appeng.core.localization.GuiText;
public class GrinderScreen extends AEBaseScreen<GrinderContainer> {
public GrinderScreen(GrinderContainer container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
this.backgroundHeight = 176;
}
@Override
public void drawFG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
this.textRenderer.draw(matrices, this.getGuiDisplayName(GuiText.GrindStone.getLocal()), 8, 6, 4210752);
this.textRenderer.draw(matrices, GuiText.inventory.getLocal(), 8, this.backgroundHeight - 96 + 3, 4210752);
}
@Override
public void drawBG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY, float partialTicks) {
this.bindTexture("guis/grinder.png");
drawTexture(matrices, offsetX, offsetY, 0, 0, this.backgroundWidth, this.backgroundHeight);
}
}
@@ -0,0 +1,48 @@
/*
* 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.client.gui.implementations;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
import appeng.client.gui.AEBaseScreen;
import appeng.container.implementations.QNBContainer;
import appeng.core.localization.GuiText;
public class QNBScreen extends AEBaseScreen<QNBContainer> {
public QNBScreen(QNBContainer container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
this.backgroundHeight = 166;
}
@Override
public void drawFG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
this.textRenderer.draw(matrices, this.getGuiDisplayName(GuiText.QuantumLinkChamber.getLocal()), 8, 6, 4210752);
this.textRenderer.draw(matrices, GuiText.inventory.getLocal(), 8, this.backgroundHeight - 96 + 3, 4210752);
}
@Override
public void drawBG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY, float partialTicks) {
this.bindTexture("guis/chest.png");
drawTexture(matrices, offsetX, offsetY, 0, 0, this.backgroundWidth, this.backgroundHeight);
}
}
@@ -0,0 +1,58 @@
/*
* 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.client.gui.implementations;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.Identifier;
import net.minecraft.text.Text;
import appeng.client.gui.AEBaseScreen;
import appeng.container.implementations.SkyChestContainer;
import appeng.core.AppEng;
import appeng.core.localization.GuiText;
public class SkyChestScreen extends AEBaseScreen<SkyChestContainer> {
private static final Identifier TEXTURE = new Identifier(AppEng.MOD_ID, "textures/guis/skychest.png");
public SkyChestScreen(SkyChestContainer container, PlayerInventory playerInv, Text title) {
super(container, playerInv, title);
this.backgroundHeight = 195;
}
@Override
public void drawFG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
this.textRenderer.draw(matrices, this.getGuiDisplayName(GuiText.SkyChest.getLocal()), 8, 8, 4210752);
this.textRenderer.draw(matrices, GuiText.inventory.getLocal(), 8, this.backgroundHeight - 96 + 2, 4210752);
}
@Override
public void drawBG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY, float partialTicks) {
bindTexture(TEXTURE);
drawTexture(matrices, offsetX, offsetY, 0, 0, this.backgroundWidth, this.backgroundHeight);
}
@Override
protected boolean enableSpaceClicking() {
// NOTE: previously checked for inventory tweaks mod (which no longer exists)
return true;
}
}
@@ -0,0 +1,69 @@
/*
* 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.client.gui.implementations;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.widgets.CommonButtons;
import appeng.container.implementations.WirelessContainer;
import appeng.core.localization.GuiText;
import appeng.util.Platform;
public class WirelessScreen extends AEBaseScreen<WirelessContainer> {
public WirelessScreen(WirelessContainer container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
this.backgroundHeight = 166;
}
@Override
public void init() {
super.init();
this.addButton(CommonButtons.togglePowerUnit(this.x - 18, this.y + 8));
}
@Override
public void drawFG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
this.textRenderer.draw(matrices, this.getGuiDisplayName(GuiText.Wireless.getLocal()), 8, 6, 4210752);
this.textRenderer.draw(matrices, GuiText.inventory.getLocal(), 8, this.backgroundHeight - 96 + 3, 4210752);
if (handler.getRange() > 0) {
final String firstMessage = GuiText.Range.getLocal() + ": " + (handler.getRange() / 10.0) + " m";
final String secondMessage = GuiText.PowerUsageRate.getLocal() + ": "
+ Platform.formatPowerLong(handler.getDrain(), true);
final int strWidth = Math.max(this.textRenderer.getWidth(firstMessage),
this.textRenderer.getWidth(secondMessage));
final int cOffset = (this.backgroundWidth / 2) - (strWidth / 2);
this.textRenderer.draw(matrices, firstMessage, cOffset, 20, 4210752);
this.textRenderer.draw(matrices, secondMessage, cOffset, 20 + 12, 4210752);
}
}
@Override
public void drawBG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY, float partialTicks) {
this.bindTexture("guis/wireless.png");
drawTexture(matrices, offsetX, offsetY, 0, 0, this.backgroundWidth, this.backgroundHeight);
}
}
@@ -0,0 +1,159 @@
/*
* 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.client.gui.widgets;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
/**
* A modified version of the Minecraft text field. You can initialize it over
* the full element span. The mouse click area is increased to the full element
* subtracted with the defined padding.
*
* The rendering does pay attention to the size of the '_' caret.
*/
public class AETextField extends TextFieldWidget {
private static final int PADDING = 2;
private final int _fontPad;
private int selectionColor = 0xFF00FF00;
/**
* Uses the values to instantiate a padded version of a text field. Pays
* attention to the '_' caret.
*
* @param fontRenderer renderer for the strings
* @param xPos absolute left position
* @param yPos absolute top position
* @param width absolute width
* @param height absolute height
*/
public AETextField(final TextRenderer fontRenderer, final int xPos, final int yPos, final int width,
final int height) {
super(fontRenderer, xPos + PADDING, yPos + PADDING, width - 2 * PADDING - (int) fontRenderer.getWidth("_"),
height - 2 * PADDING, LiteralText.EMPTY);
this._fontPad = (int) fontRenderer.getWidth("_");
}
@Override
public boolean mouseClicked(final double xPos, final double yPos, final int button) {
if (!super.mouseClicked(xPos, yPos, button)) {
return false;
}
final boolean requiresFocus = this.isMouseOver(xPos, yPos);
if (!this.isFocused()) {
this.setFocused(requiresFocus);
}
return true;
}
public void selectAll() {
this.setCursor(0);
this.setSelectionEnd(getText().length());
}
public void setSelectionColor(int color) {
this.selectionColor = color;
}
@Override
public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float partial) {
if (this.isVisible()) {
if (this.isFocused()) {
fill(matrices, this.x - PADDING + 1, this.y - PADDING + 1, this.x + this.width + this._fontPad + PADDING - 1,
this.y + this.height + PADDING - 1, 0xFF606060);
} else {
fill(matrices, this.x - PADDING + 1, this.y - PADDING + 1, this.x + this.width + this._fontPad + PADDING - 1,
this.y + this.height + PADDING - 1, 0xFFA8A8A8);
}
super.renderButton(matrices, mouseX, mouseY, partial);
}
}
@Override
public void drawSelectionHighlight(int startX, int startY, int endX, int endY) {
if (!this.isFocused()) {
return;
}
if (startX < endX) {
int i = startX;
startX = endX;
endX = i;
}
startX += 1;
endX -= 1;
if (startY < endY) {
int j = startY;
startY = endY;
endY = j;
}
startY -= PADDING;
if (endX > this.x + this.width) {
endX = this.x + this.width;
}
if (startX > this.x + this.width) {
startX = this.x + this.width;
}
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
float red = (this.selectionColor >> 16 & 255) / 255.0F;
float blue = (this.selectionColor >> 8 & 255) / 255.0F;
float green = (this.selectionColor & 255) / 255.0F;
float alpha = (this.selectionColor >> 24 & 255) / 255.0F;
RenderSystem.color4f(red, green, blue, alpha);
RenderSystem.disableTexture();
RenderSystem.enableColorLogicOp();
RenderSystem.logicOp(GlStateManager.LogicOp.OR_REVERSE);
bufferbuilder.begin(7, VertexFormats.POSITION);
bufferbuilder.vertex(startX, endY, 0.0D).next();
bufferbuilder.vertex(endX, endY, 0.0D).next();
bufferbuilder.vertex(endX, startY, 0.0D).next();
bufferbuilder.vertex(startX, startY, 0.0D).next();
tessellator.draw();
RenderSystem.disableColorLogicOp();
RenderSystem.enableTexture();
RenderSystem.color4f(1, 1, 1, 1);
}
@Override
public void setFocused(boolean focused) {
super.setFocused(focused);
}
}
@@ -0,0 +1,99 @@
/*
* 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.client.gui.widgets;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import appeng.api.config.ActionItems;
import appeng.core.localization.ButtonToolTips;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
public class ActionButton extends IconButton implements ITooltip {
private static final Pattern PATTERN_NEW_LINE = Pattern.compile("\\n", Pattern.LITERAL);
private final int iconIndex;
public ActionButton(final int x, final int y, final ActionItems action, Consumer<ActionItems> onPress) {
super(x, y, btn -> onPress.accept(action));
ButtonToolTips displayName;
ButtonToolTips displayValue;
switch (action) {
case WRENCH:
iconIndex = 66;
displayName = ButtonToolTips.PartitionStorage;
displayValue = ButtonToolTips.PartitionStorageHint;
break;
case CLOSE:
iconIndex = 6;
displayName = ButtonToolTips.Clear;
displayValue = ButtonToolTips.ClearSettings;
break;
case STASH:
iconIndex = 6;
displayName = ButtonToolTips.Stash;
displayValue = ButtonToolTips.StashDesc;
break;
case ENCODE:
iconIndex = 8;
displayName = ButtonToolTips.Encode;
displayValue = ButtonToolTips.EncodeDescription;
break;
case ENABLE_SUBSTITUTION:
iconIndex = 4 + 3 * 16;
displayName = ButtonToolTips.Substitutions;
displayValue = ButtonToolTips.SubstitutionsDescEnabled;
break;
case DISABLE_SUBSTITUTION:
iconIndex = 7 + 3 * 16;
displayName = ButtonToolTips.Substitutions;
displayValue = ButtonToolTips.SubstitutionsDescDisabled;
break;
default:
throw new IllegalArgumentException("Unknown ActionItem: " + action);
}
setMessage(buildMessage(displayName, displayValue));
}
@Override
protected int getIconIndex() {
return iconIndex;
}
private Text buildMessage(ButtonToolTips displayName, ButtonToolTips displayValue) {
String name = displayName.text().getString();
String value = displayValue.text().getString();
value = PATTERN_NEW_LINE.matcher(value).replaceAll("\n");
final StringBuilder sb = new StringBuilder(value);
int i = sb.lastIndexOf("\n");
if (i <= 0) {
i = 0;
}
while (i + 30 < sb.length() && (i = sb.lastIndexOf(" ", i + 30)) != -1) {
sb.replace(i, i + 1, "\n");
}
return new LiteralText(name + '\n' + sb);
}
}
@@ -0,0 +1,22 @@
package appeng.client.gui.widgets;
import appeng.api.config.PowerUnits;
import appeng.api.config.Settings;
import appeng.core.AEConfig;
public final class CommonButtons {
private CommonButtons() {
}
public static SettingToggleButton<PowerUnits> togglePowerUnit(int x, int y) {
return new SettingToggleButton<>(x, y, Settings.POWER_UNITS, AEConfig.instance().getSelectedPowerUnit(),
CommonButtons::togglePowerUnit);
}
private static void togglePowerUnit(SettingToggleButton<PowerUnits> button, boolean backwards) {
AEConfig.instance().nextPowerUnit(backwards);
button.set(AEConfig.instance().getSelectedPowerUnit());
}
}
@@ -0,0 +1,71 @@
package appeng.client.gui.widgets;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
public abstract class CustomSlotWidget extends DrawableHelper implements ITooltip {
private final int x;
private final int y;
private final int id;
public CustomSlotWidget(final int id, final int x, final int y) {
this.x = x;
this.y = y;
this.id = id;
}
public int getId() {
return this.id;
}
public boolean canClick(final PlayerEntity player) {
return true;
}
public void slotClicked(final ItemStack clickStack, final int mouseButton) {
}
public abstract void drawContent(final MinecraftClient mc, final int mouseX, final int mouseY, final float partialTicks);
public void drawBackground(int guileft, int guitop, int currentZIndex) {
}
@Override
public Text getMessage() {
return null;
}
@Override
public int xPos() {
return this.x;
}
@Override
public int yPos() {
return this.y;
}
@Override
public int getWidth() {
return 16;
}
@Override
public int getHeight() {
return 16;
}
@Override
public boolean isVisible() {
return false;
}
public boolean isSlotEnabled() {
return true;
}
}
@@ -0,0 +1,24 @@
/*
* 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.client.gui.widgets;
public interface IScrollSource {
int getCurrentScroll();
}
@@ -0,0 +1,31 @@
/*
* 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.client.gui.widgets;
import appeng.api.config.SortDir;
import appeng.api.config.SortOrder;
import appeng.api.config.ViewItems;
public interface ISortSource {
SortOrder getSortBy();
SortDir getSortDir();
ViewItems getSortDisplay();
}
@@ -0,0 +1,67 @@
/*
* 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.client.gui.widgets;
import net.minecraft.text.Text;
/**
* AEBaseGui controlled Tooltip Interface.
*/
public interface ITooltip {
/**
* returns the tooltip message.
*
* @return tooltip message
*/
Text getMessage();
/**
* x Location for the object that triggers the tooltip.
*
* @return xPosition
*/
int xPos();
/**
* y Location for the object that triggers the tooltip.
*
* @return yPosition
*/
int yPos();
/**
* Width of the object that triggers the tooltip.
*
* @return width
*/
int getWidth();
/**
* Height for the object that triggers the tooltip.
*
* @return height
*/
int getHeight();
/**
* @return true if button being drawn
*/
boolean isVisible();
}
@@ -0,0 +1,131 @@
/*
* 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.client.gui.widgets;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.util.Identifier;
public abstract class IconButton extends ButtonWidget implements ITooltip {
public static final Identifier TEXTURE_STATES = new Identifier("appliedenergistics2",
"textures/guis/states.png");
private boolean halfSize = false;
public IconButton(final int x, final int y, PressAction onPress) {
super(x, y, 16, 16, LiteralText.EMPTY, onPress);
}
public void setVisibility(final boolean vis) {
this.visible = vis;
this.active = vis;
}
@Override
public void renderButton(MatrixStack matrices, final int mouseX, final int mouseY, float partial) {
MinecraftClient minecraft = MinecraftClient.getInstance();
if (this.visible) {
final int iconIndex = this.getIconIndex();
TextureManager textureManager = minecraft.getTextureManager();
textureManager.bindTexture(TEXTURE_STATES);
RenderSystem.disableDepthTest();
RenderSystem.enableBlend(); // FIXME: This should be the _default_ state, but some vanilla widget disables
// it :|
if (this.halfSize) {
this.width = 8;
this.height = 8;
RenderSystem.pushMatrix();
RenderSystem.translatef(this.x, this.y, 0.0F);
RenderSystem.scalef(0.5f, 0.5f, 0.5f);
if (this.active) {
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
} else {
RenderSystem.color4f(0.5f, 0.5f, 0.5f, 1.0f);
}
final int uv_y = iconIndex / 16;
final int uv_x = iconIndex - uv_y * 16;
drawTexture(matrices, 0, 0, 256 - 16, 256 - 16, 16, 16);
drawTexture(matrices, 0, 0, uv_x * 16, uv_y * 16, 16, 16);
RenderSystem.popMatrix();
} else {
if (this.active) {
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
} else {
RenderSystem.color4f(0.5f, 0.5f, 0.5f, 1.0f);
}
final int uv_y = iconIndex / 16;
final int uv_x = iconIndex - uv_y * 16;
drawTexture(matrices, this.x, this.y, 256 - 16, 256 - 16, 16, 16);
drawTexture(matrices, this.x, this.y, uv_x * 16, uv_y * 16, 16, 16);
}
RenderSystem.enableDepthTest();
}
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
}
protected abstract int getIconIndex();
@Override
public int xPos() {
return this.x;
}
@Override
public int yPos() {
return this.y;
}
@Override
public int getWidth() {
return this.halfSize ? 8 : 16;
}
@Override
public int getHeight() {
return this.halfSize ? 8 : 16;
}
@Override
public boolean isVisible() {
return this.visible;
}
public boolean isHalfSize() {
return this.halfSize;
}
public void setHalfSize(final boolean halfSize) {
this.halfSize = halfSize;
}
}
@@ -0,0 +1,53 @@
/*
* 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.client.gui.widgets;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.text.LiteralText;
// FIXME: Fix this piece of crap (i.e. onChange listener)
public class NumberBox extends TextFieldWidget {
private final Class type;
public NumberBox(final TextRenderer fontRenderer, final int x, final int y, final int width, final int height,
final Class type) {
super(fontRenderer, x, y, width, height, new LiteralText("0"));
this.type = type;
}
@Override
public void write(final String selectedText) {
final String original = this.getText();
super.write(selectedText);
try {
if (this.type == int.class || this.type == Integer.class) {
Integer.parseInt(this.getText());
} else if (this.type == long.class || this.type == Long.class) {
Long.parseLong(this.getText());
} else if (this.type == double.class || this.type == Double.class) {
Double.parseDouble(this.getText());
}
} catch (final NumberFormatException e) {
this.setText(original);
}
}
}
@@ -0,0 +1,119 @@
/*
* 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.client.gui.widgets;
import appeng.container.interfaces.IProgressProvider;
import appeng.core.localization.GuiText;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public class ProgressBar extends AbstractButtonWidget implements ITooltip {
private final IProgressProvider source;
private final Identifier texture;
private final int fill_u;
private final int fill_v;
private final Direction layout;
private final Text titleName;
private Text fullMsg;
public ProgressBar(final IProgressProvider source, final String texture, final int posX, final int posY,
final int u, final int y, final int width, final int height, final Direction dir) {
this(source, texture, posX, posY, u, y, width, height, dir, null);
}
public ProgressBar(final IProgressProvider source, final String texture, final int posX, final int posY,
final int u, final int y, final int width, final int height, final Direction dir, final Text title) {
super(posX, posY, width, height, LiteralText.EMPTY);
this.source = source;
this.texture = new Identifier("appliedenergistics2", "textures/" + texture);
this.fill_u = u;
this.fill_v = y;
this.layout = dir;
this.titleName = title;
}
@Override
public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) {
if (this.visible) {
MinecraftClient.getInstance().getTextureManager().bindTexture(this.texture);
final int max = this.source.getMaxProgress();
final int current = this.source.getCurrentProgress();
if (this.layout == Direction.VERTICAL) {
final int diff = this.height - (max > 0 ? (this.height * current) / max : 0);
drawTexture(matrices, this.x, this.y + diff, this.fill_u, this.fill_v + diff, this.width,
this.height - diff);
} else {
final int diff = this.width - (max > 0 ? (this.width * current) / max : 0);
drawTexture(matrices, this.x, this.y, this.fill_u + diff, this.fill_v, this.width - diff,
this.height);
}
}
}
public void setFullMsg(final Text msg) {
this.fullMsg = msg;
}
@Override
public Text getMessage() {
if (this.fullMsg != null) {
return this.fullMsg;
}
Text text = this.titleName != null ? this.titleName : LiteralText.EMPTY;
return text.copy().append("\n" + this.source.getCurrentProgress() + " ")
.append(GuiText.Of.textComponent())
.append(" " + this.source.getMaxProgress());
}
@Override
public int xPos() {
return this.x - 2;
}
@Override
public int yPos() {
return this.y - 2;
}
@Override
public int getWidth() {
return this.width + 4;
}
@Override
public int getHeight() {
return this.height + 4;
}
@Override
public boolean isVisible() {
return true;
}
public enum Direction {
HORIZONTAL, VERTICAL
}
}
@@ -0,0 +1,135 @@
/*
* 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.client.gui.widgets;
import com.mojang.blaze3d.systems.RenderSystem;
import appeng.client.gui.AEBaseScreen;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.util.math.MatrixStack;
public class Scrollbar implements IScrollSource {
private int displayX = 0;
private int displayY = 0;
private int width = 12;
private int height = 16;
private int pageSize = 1;
private int maxScroll = 0;
private int minScroll = 0;
private int currentScroll = 0;
private final DrawableHelper drawable = new DrawableHelper(){};
public void draw(MatrixStack matrices, final AEBaseScreen<?> g) {
g.bindTexture("minecraft", "gui/container/creative_inventory/tabs.png");
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
drawable.setZOffset(g.getZOffset());
if (this.getRange() == 0) {
drawable.drawTexture(matrices, this.displayX, this.displayY, 232 + this.width, 0, this.width, 15);
} else {
final int offset = (this.currentScroll - this.minScroll) * (this.height - 15) / this.getRange();
drawable.drawTexture(matrices, this.displayX, offset + this.displayY, 232, 0, this.width, 15);
}
}
private int getRange() {
return this.maxScroll - this.minScroll;
}
public int getLeft() {
return this.displayX;
}
public Scrollbar setLeft(final int v) {
this.displayX = v;
return this;
}
public int getTop() {
return this.displayY;
}
public Scrollbar setTop(final int v) {
this.displayY = v;
return this;
}
public int getWidth() {
return this.width;
}
public Scrollbar setWidth(final int v) {
this.width = v;
return this;
}
public int getHeight() {
return this.height;
}
public Scrollbar setHeight(final int v) {
this.height = v;
return this;
}
public void setRange(final int min, final int max, final int pageSize) {
this.minScroll = min;
this.maxScroll = max;
this.pageSize = pageSize;
if (this.minScroll > this.maxScroll) {
this.maxScroll = this.minScroll;
}
this.applyRange();
}
private void applyRange() {
this.currentScroll = Math.max(Math.min(this.currentScroll, this.maxScroll), this.minScroll);
}
@Override
public int getCurrentScroll() {
return this.currentScroll;
}
public void click(final double x, final double y) {
if (this.getRange() == 0) {
return;
}
if (x > this.displayX && x <= this.displayX + this.width) {
if (y > this.displayY && y <= this.displayY + this.height) {
this.currentScroll = (int) (y - this.displayY);
this.currentScroll = this.minScroll + ((this.currentScroll * 2 * this.getRange() / this.height));
this.currentScroll = (this.currentScroll + 1) >> 1;
this.applyRange();
}
}
}
public void wheel(double delta) {
delta = Math.max(Math.min(-delta, 1), -1);
this.currentScroll += delta * this.pageSize;
this.applyRange();
}
}
@@ -0,0 +1,38 @@
/*
* 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.client.gui.widgets;
import appeng.api.config.Settings;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigButtonPacket;
/**
* Convenience button that automatically sends settings changes to the server.
*/
public class ServerSettingToggleButton<T extends Enum<T>> extends SettingToggleButton<T> {
public ServerSettingToggleButton(final int x, final int y, final Settings setting, final T val) {
super(x, y, setting, val, ServerSettingToggleButton::sendToServer);
}
private static <T extends Enum<T>> void sendToServer(SettingToggleButton<T> button, boolean backwards) {
NetworkHandler.instance().sendToServer(new ConfigButtonPacket(button.getSetting(), backwards));
}
}
@@ -0,0 +1,362 @@
/*
* 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.client.gui.widgets;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import appeng.api.config.AccessRestriction;
import appeng.api.config.CondenserOutput;
import appeng.api.config.FullnessMode;
import appeng.api.config.FuzzyMode;
import appeng.api.config.LevelType;
import appeng.api.config.OperationMode;
import appeng.api.config.PowerUnits;
import appeng.api.config.RedstoneMode;
import appeng.api.config.RelativeDirection;
import appeng.api.config.SchedulingMode;
import appeng.api.config.SearchBoxMode;
import appeng.api.config.Settings;
import appeng.api.config.SortDir;
import appeng.api.config.SortOrder;
import appeng.api.config.StorageFilter;
import appeng.api.config.TerminalStyle;
import appeng.api.config.ViewItems;
import appeng.api.config.YesNo;
import appeng.core.localization.ButtonToolTips;
import appeng.util.EnumCycler;
public class SettingToggleButton<T extends Enum<T>> extends IconButton {
private static final Pattern COMPILE = Pattern.compile("%s");
private static final Pattern PATTERN_NEW_LINE = Pattern.compile("\\n", Pattern.LITERAL);
private static Map<EnumPair, ButtonAppearance> appearances;
private final Settings buttonSetting;
private final IHandler<SettingToggleButton<T>> onPress;
private final EnumSet<T> validValues;
private String fillVar;
private T currentValue;
@FunctionalInterface
public interface IHandler<T extends SettingToggleButton<?>> {
void handle(T button, boolean backwards);
}
public SettingToggleButton(final int x, final int y, final Settings setting, final T val,
IHandler<SettingToggleButton<T>> onPress) {
this(x, y, setting, val, t -> true, onPress);
}
public SettingToggleButton(final int x, final int y, final Settings setting, final T val, Predicate<T> isValidValue,
IHandler<SettingToggleButton<T>> onPress) {
super(x, y, SettingToggleButton::onPress);
this.onPress = onPress;
// Build a list of values (in order) that are valid w.r.t. the given predicate
EnumSet<T> validValues = EnumSet.allOf(val.getDeclaringClass());
validValues.removeIf(isValidValue.negate());
validValues.removeIf(s -> !setting.getPossibleValues().contains(s));
this.validValues = validValues;
this.buttonSetting = setting;
this.currentValue = val;
if (appearances == null) {
appearances = new HashMap<>();
registerApp(16 * 7, Settings.CONDENSER_OUTPUT, CondenserOutput.TRASH, ButtonToolTips.CondenserOutput,
ButtonToolTips.Trash);
registerApp(16 * 7 + 1, Settings.CONDENSER_OUTPUT, CondenserOutput.MATTER_BALLS,
ButtonToolTips.CondenserOutput, ButtonToolTips.MatterBalls);
registerApp(16 * 7 + 2, Settings.CONDENSER_OUTPUT, CondenserOutput.SINGULARITY,
ButtonToolTips.CondenserOutput, ButtonToolTips.Singularity);
registerApp(16 * 9 + 1, Settings.ACCESS, AccessRestriction.READ, ButtonToolTips.IOMode,
ButtonToolTips.Read);
registerApp(16 * 9, Settings.ACCESS, AccessRestriction.WRITE, ButtonToolTips.IOMode, ButtonToolTips.Write);
registerApp(16 * 9 + 2, Settings.ACCESS, AccessRestriction.READ_WRITE, ButtonToolTips.IOMode,
ButtonToolTips.ReadWrite);
registerApp(16 * 10, Settings.POWER_UNITS, PowerUnits.AE, ButtonToolTips.PowerUnits,
PowerUnits.AE.textComponent());
registerApp(16 * 10 + 1, Settings.POWER_UNITS, PowerUnits.EU, ButtonToolTips.PowerUnits,
PowerUnits.EU.textComponent());
registerApp(16 * 10 + 4, Settings.POWER_UNITS, PowerUnits.RF, ButtonToolTips.PowerUnits,
PowerUnits.RF.textComponent());
registerApp(3, Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE, ButtonToolTips.RedstoneMode,
ButtonToolTips.AlwaysActive);
registerApp(0, Settings.REDSTONE_CONTROLLED, RedstoneMode.LOW_SIGNAL, ButtonToolTips.RedstoneMode,
ButtonToolTips.ActiveWithoutSignal);
registerApp(1, Settings.REDSTONE_CONTROLLED, RedstoneMode.HIGH_SIGNAL, ButtonToolTips.RedstoneMode,
ButtonToolTips.ActiveWithSignal);
registerApp(2, Settings.REDSTONE_CONTROLLED, RedstoneMode.SIGNAL_PULSE, ButtonToolTips.RedstoneMode,
ButtonToolTips.ActiveOnPulse);
registerApp(0, Settings.REDSTONE_EMITTER, RedstoneMode.LOW_SIGNAL, ButtonToolTips.RedstoneMode,
ButtonToolTips.EmitLevelsBelow);
registerApp(1, Settings.REDSTONE_EMITTER, RedstoneMode.HIGH_SIGNAL, ButtonToolTips.RedstoneMode,
ButtonToolTips.EmitLevelAbove);
registerApp(51, Settings.OPERATION_MODE, OperationMode.FILL, ButtonToolTips.TransferDirection,
ButtonToolTips.TransferToStorageCell);
registerApp(50, Settings.OPERATION_MODE, OperationMode.EMPTY, ButtonToolTips.TransferDirection,
ButtonToolTips.TransferToNetwork);
registerApp(51, Settings.IO_DIRECTION, RelativeDirection.LEFT, ButtonToolTips.TransferDirection,
ButtonToolTips.TransferToStorageCell);
registerApp(50, Settings.IO_DIRECTION, RelativeDirection.RIGHT, ButtonToolTips.TransferDirection,
ButtonToolTips.TransferToNetwork);
registerApp(48, Settings.SORT_DIRECTION, SortDir.ASCENDING, ButtonToolTips.SortOrder,
ButtonToolTips.ToggleSortDirection);
registerApp(49, Settings.SORT_DIRECTION, SortDir.DESCENDING, ButtonToolTips.SortOrder,
ButtonToolTips.ToggleSortDirection);
registerApp(16 * 2 + 3, Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_Auto);
registerApp(16 * 2 + 4, Settings.SEARCH_MODE, SearchBoxMode.MANUAL_SEARCH, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_Standard);
registerApp(16 * 2 + 5, Settings.SEARCH_MODE, SearchBoxMode.JEI_AUTOSEARCH, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_JEIAuto);
registerApp(16 * 2 + 6, Settings.SEARCH_MODE, SearchBoxMode.JEI_MANUAL_SEARCH, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_JEIStandard);
registerApp(16 * 2 + 7, Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH_KEEP, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_AutoKeep);
registerApp(16 * 2 + 8, Settings.SEARCH_MODE, SearchBoxMode.MANUAL_SEARCH_KEEP, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_StandardKeep);
registerApp(16 * 2 + 9, Settings.SEARCH_MODE, SearchBoxMode.JEI_AUTOSEARCH_KEEP, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_JEIAutoKeep);
registerApp(16 * 2 + 10, Settings.SEARCH_MODE, SearchBoxMode.JEI_MANUAL_SEARCH_KEEP,
ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_JEIStandardKeep);
registerApp(16 * 5 + 3, Settings.LEVEL_TYPE, LevelType.ENERGY_LEVEL, ButtonToolTips.LevelType,
ButtonToolTips.LevelType_Energy);
registerApp(16 * 4 + 3, Settings.LEVEL_TYPE, LevelType.ITEM_LEVEL, ButtonToolTips.LevelType,
ButtonToolTips.LevelType_Item);
registerApp(16 * 13, Settings.TERMINAL_STYLE, TerminalStyle.TALL, ButtonToolTips.TerminalStyle,
ButtonToolTips.TerminalStyle_Tall);
registerApp(16 * 13 + 1, Settings.TERMINAL_STYLE, TerminalStyle.SMALL, ButtonToolTips.TerminalStyle,
ButtonToolTips.TerminalStyle_Small);
registerApp(16 * 13 + 2, Settings.TERMINAL_STYLE, TerminalStyle.FULL, ButtonToolTips.TerminalStyle,
ButtonToolTips.TerminalStyle_Full);
registerApp(64, Settings.SORT_BY, SortOrder.NAME, ButtonToolTips.SortBy, ButtonToolTips.ItemName);
registerApp(65, Settings.SORT_BY, SortOrder.AMOUNT, ButtonToolTips.SortBy, ButtonToolTips.NumberOfItems);
// 68: Formerly sort by inventory tweaks
registerApp(69, Settings.SORT_BY, SortOrder.MOD, ButtonToolTips.SortBy, ButtonToolTips.Mod);
registerApp(16, Settings.VIEW_MODE, ViewItems.STORED, ButtonToolTips.View, ButtonToolTips.StoredItems);
registerApp(18, Settings.VIEW_MODE, ViewItems.ALL, ButtonToolTips.View, ButtonToolTips.StoredCraftable);
registerApp(19, Settings.VIEW_MODE, ViewItems.CRAFTABLE, ButtonToolTips.View, ButtonToolTips.Craftable);
registerApp(16 * 6, Settings.FUZZY_MODE, FuzzyMode.PERCENT_25, ButtonToolTips.FuzzyMode,
ButtonToolTips.FZPercent_25);
registerApp(16 * 6 + 1, Settings.FUZZY_MODE, FuzzyMode.PERCENT_50, ButtonToolTips.FuzzyMode,
ButtonToolTips.FZPercent_50);
registerApp(16 * 6 + 2, Settings.FUZZY_MODE, FuzzyMode.PERCENT_75, ButtonToolTips.FuzzyMode,
ButtonToolTips.FZPercent_75);
registerApp(16 * 6 + 3, Settings.FUZZY_MODE, FuzzyMode.PERCENT_99, ButtonToolTips.FuzzyMode,
ButtonToolTips.FZPercent_99);
registerApp(16 * 6 + 4, Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL, ButtonToolTips.FuzzyMode,
ButtonToolTips.FZIgnoreAll);
registerApp(80, Settings.FULLNESS_MODE, FullnessMode.EMPTY, ButtonToolTips.OperationMode,
ButtonToolTips.MoveWhenEmpty);
registerApp(81, Settings.FULLNESS_MODE, FullnessMode.HALF, ButtonToolTips.OperationMode,
ButtonToolTips.MoveWhenWorkIsDone);
registerApp(82, Settings.FULLNESS_MODE, FullnessMode.FULL, ButtonToolTips.OperationMode,
ButtonToolTips.MoveWhenFull);
registerApp(16 + 5, Settings.BLOCK, YesNo.YES, ButtonToolTips.InterfaceBlockingMode,
ButtonToolTips.Blocking);
registerApp(16 + 4, Settings.BLOCK, YesNo.NO, ButtonToolTips.InterfaceBlockingMode,
ButtonToolTips.NonBlocking);
registerApp(16 + 3, Settings.CRAFT_ONLY, YesNo.YES, ButtonToolTips.Craft, ButtonToolTips.CraftOnly);
registerApp(16 + 2, Settings.CRAFT_ONLY, YesNo.NO, ButtonToolTips.Craft, ButtonToolTips.CraftEither);
registerApp(16 * 11 + 2, Settings.CRAFT_VIA_REDSTONE, YesNo.YES, ButtonToolTips.EmitterMode,
ButtonToolTips.CraftViaRedstone);
registerApp(16 * 11 + 1, Settings.CRAFT_VIA_REDSTONE, YesNo.NO, ButtonToolTips.EmitterMode,
ButtonToolTips.EmitWhenCrafting);
registerApp(16 * 3 + 5, Settings.STORAGE_FILTER, StorageFilter.EXTRACTABLE_ONLY,
ButtonToolTips.ReportInaccessibleItems, ButtonToolTips.ReportInaccessibleItemsNo);
registerApp(16 * 3 + 6, Settings.STORAGE_FILTER, StorageFilter.NONE, ButtonToolTips.ReportInaccessibleItems,
ButtonToolTips.ReportInaccessibleItemsYes);
registerApp(16 * 14, Settings.PLACE_BLOCK, YesNo.YES, ButtonToolTips.BlockPlacement,
ButtonToolTips.BlockPlacementYes);
registerApp(16 * 14 + 1, Settings.PLACE_BLOCK, YesNo.NO, ButtonToolTips.BlockPlacement,
ButtonToolTips.BlockPlacementNo);
registerApp(16 * 15, Settings.SCHEDULING_MODE, SchedulingMode.DEFAULT, ButtonToolTips.SchedulingMode,
ButtonToolTips.SchedulingModeDefault);
registerApp(16 * 15 + 1, Settings.SCHEDULING_MODE, SchedulingMode.ROUNDROBIN, ButtonToolTips.SchedulingMode,
ButtonToolTips.SchedulingModeRoundRobin);
registerApp(16 * 15 + 2, Settings.SCHEDULING_MODE, SchedulingMode.RANDOM, ButtonToolTips.SchedulingMode,
ButtonToolTips.SchedulingModeRandom);
}
}
private static void onPress(ButtonWidget btn) {
if (btn instanceof SettingToggleButton) {
((SettingToggleButton<?>) btn).triggerPress();
}
}
private void triggerPress() {
boolean backwards = MinecraftClient.getInstance().mouse.wasRightButtonClicked();
onPress.handle(this, backwards);
}
private static void registerApp(final int iconIndex, final Settings setting, final Enum<?> val,
final ButtonToolTips title, final Text hint) {
final ButtonAppearance a = new ButtonAppearance();
a.displayName = title.text();
a.displayValue = hint;
a.index = iconIndex;
appearances.put(new EnumPair(setting, val), a);
}
private static void registerApp(final int iconIndex, final Settings setting, final Enum<?> val,
final ButtonToolTips title, final ButtonToolTips hint) {
registerApp(iconIndex, setting, val, title, hint.text());
}
@Override
protected int getIconIndex() {
if (this.buttonSetting != null && this.currentValue != null) {
final ButtonAppearance app = appearances.get(new EnumPair(this.buttonSetting, this.currentValue));
if (app == null) {
return 256 - 1;
}
return app.index;
}
return 256 - 1;
}
public Settings getSetting() {
return this.buttonSetting;
}
public T getCurrentValue() {
return this.currentValue;
}
public void set(final T e) {
if (this.currentValue != e) {
this.currentValue = e;
}
}
public T getNextValue(boolean backwards) {
return EnumCycler.rotateEnum(currentValue, backwards, validValues);
}
@Override
public Text getMessage() {
Text displayName = null;
Text displayValue = null;
if (this.buttonSetting != null && this.currentValue != null) {
final ButtonAppearance buttonAppearance = appearances
.get(new EnumPair(this.buttonSetting, this.currentValue));
if (buttonAppearance == null) {
return new LiteralText("No Such Message");
}
displayName = buttonAppearance.displayName;
displayValue = buttonAppearance.displayValue;
}
if (displayName != null) {
String name = displayName.getString();
String value = displayValue.getString();
if (this.fillVar != null) {
value = COMPILE.matcher(value).replaceFirst(this.fillVar);
}
value = PATTERN_NEW_LINE.matcher(value).replaceAll("\n");
final StringBuilder sb = new StringBuilder(value);
int i = sb.lastIndexOf("\n");
if (i <= 0) {
i = 0;
}
while (i + 30 < sb.length() && (i = sb.lastIndexOf(" ", i + 30)) != -1) {
sb.replace(i, i + 1, "\n");
}
return new LiteralText(name + '\n' + sb);
}
return null;
}
public String getFillVar() {
return this.fillVar;
}
public void setFillVar(final String fillVar) {
this.fillVar = fillVar;
}
private static final class EnumPair {
final Settings setting;
final Enum<?> value;
EnumPair(final Settings a, final Enum<?> b) {
this.setting = a;
this.value = b;
}
@Override
public int hashCode() {
return this.setting.hashCode() ^ this.value.hashCode();
}
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final EnumPair other = (EnumPair) obj;
return other.setting == this.setting && other.value == this.value;
}
}
private static class ButtonAppearance {
public int index;
public Text displayName;
public Text displayValue;
}
}
@@ -0,0 +1,128 @@
/*
* 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.client.gui.widgets;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public class TabButton extends ButtonWidget implements ITooltip {
public static final Identifier TEXTURE_STATES = new Identifier("appliedenergistics2",
"textures/guis/states.png");
private final ItemRenderer itemRenderer;
private int hideEdge = 0;
private int myIcon = -1;
private ItemStack myItem;
public TabButton(final int x, final int y, final int ico, final Text message, final ItemRenderer ir,
PressAction onPress) {
super(x, y, 22, 22, message, onPress);
this.myIcon = ico;
this.itemRenderer = ir;
}
/**
* Using itemstack as an icon
*
* @param x x pos of button
* @param y y pos of button
* @param ico used icon
* @param message mouse over message
* @param ir renderer
*/
public TabButton(final int x, final int y, final ItemStack ico, final Text message, final ItemRenderer ir,
PressAction onPress) {
super(x, y, 22, 22, message, onPress);
this.myItem = ico;
this.itemRenderer = ir;
}
@Override
public void renderButton(MatrixStack matrices, final int x, final int y, float partial) {
final MinecraftClient minecraft = MinecraftClient.getInstance();
if (this.visible) {
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
minecraft.getTextureManager().bindTexture(TEXTURE_STATES);
RenderSystem.enableAlphaTest();
int uv_x = (this.hideEdge > 0 ? 11 : 13);
final int offsetX = this.hideEdge > 0 ? 1 : 0;
drawTexture(matrices, this.x, this.y, uv_x * 16, 0, 25, 22);
if (this.myIcon >= 0) {
final int uv_y = this.myIcon / 16;
uv_x = this.myIcon - uv_y * 16;
drawTexture(matrices, offsetX + this.x + 3, this.y + 3, uv_x * 16, uv_y * 16, 16, 16);
}
RenderSystem.disableAlphaTest();
if (this.myItem != null) {
this.itemRenderer.zOffset = 100.0F;
this.itemRenderer.renderInGuiWithOverrides(this.myItem, offsetX + this.x + 3, this.y + 3);
this.itemRenderer.zOffset = 0.0F;
}
}
}
@Override
public int xPos() {
return this.x;
}
@Override
public int yPos() {
return this.y;
}
@Override
public int getWidth() {
return 22;
}
@Override
public int getHeight() {
return 22;
}
@Override
public boolean isVisible() {
return this.visible;
}
public int getHideEdge() {
return this.hideEdge;
}
public void setHideEdge(final int hideEdge) {
this.hideEdge = hideEdge;
}
}
@@ -0,0 +1,123 @@
/*
* 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.client.gui.widgets;
import java.util.regex.Pattern;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public class ToggleButton extends ButtonWidget implements ITooltip {
public static final Identifier TEXTURE_STATES = new Identifier("appliedenergistics2",
"textures/guis/states.png");
private static final Pattern PATTERN_NEW_LINE = Pattern.compile("\\n", Pattern.LITERAL);
private final int iconIdxOn;
private final int iconIdxOff;
private final Text displayName;
private final Text displayHint;
private boolean isActive;
public ToggleButton(final int x, final int y, final int on, final int off, final Text displayName,
final Text displayHint, PressAction onPress) {
super(x, y, 16, 16, LiteralText.EMPTY, onPress);
this.iconIdxOn = on;
this.iconIdxOff = off;
this.displayName = displayName;
this.displayHint = displayHint;
}
public void setState(final boolean isOn) {
this.isActive = isOn;
}
@Override
public void renderButton(MatrixStack matrices, final int mouseX, final int mouseY, final float partial) {
if (this.visible) {
final int iconIndex = this.getIconIndex();
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
MinecraftClient.getInstance().getTextureManager().bindTexture(TEXTURE_STATES);
final int uv_y = iconIndex / 16;
final int uv_x = iconIndex - uv_y * 16;
drawTexture(matrices, this.x, this.y, 256 - 16, 256 - 16, 16, 16);
drawTexture(matrices, this.x, this.y, uv_x * 16, uv_y * 16, 16, 16);
}
}
private int getIconIndex() {
return this.isActive ? this.iconIdxOn : this.iconIdxOff;
}
@Override
public Text getMessage() {
if (this.displayName != null) {
String name = this.displayName.getString();
String value = this.displayHint.getString();
value = PATTERN_NEW_LINE.matcher(value).replaceAll("\n");
final StringBuilder sb = new StringBuilder(value);
int i = sb.lastIndexOf("\n");
if (i <= 0) {
i = 0;
}
while (i + 30 < sb.length() && (i = sb.lastIndexOf(" ", i + 30)) != -1) {
sb.replace(i, i + 1, "\n");
}
return new LiteralText(name + '\n' + sb);
}
return null;
}
@Override
public int xPos() {
return this.x;
}
@Override
public int yPos() {
return this.y;
}
@Override
public int getWidth() {
return 16;
}
@Override
public int getHeight() {
return 16;
}
@Override
public boolean isVisible() {
return this.visible;
}
}
@@ -0,0 +1,68 @@
/*
* 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.client.me;
import javax.annotation.Nonnull;
import net.minecraft.text.Text;
import appeng.tile.inventory.AppEngInternalInventory;
public class ClientDCInternalInv implements Comparable<ClientDCInternalInv> {
private final String searchName;
private final String formattedName;
private final AppEngInternalInventory inventory;
private final long id;
private final long sortBy;
public ClientDCInternalInv(final int size, final long id, final long sortBy, final Text name) {
this.inventory = new AppEngInternalInventory(null, size);
this.searchName = name.getString().toLowerCase();
this.formattedName = name.getString(); // FIXME FABRIC no longer formatted!
this.id = id;
this.sortBy = sortBy;
}
public String getSearchName() {
return searchName;
}
public String getFormattedName() {
return formattedName;
}
@Override
public int compareTo(@Nonnull final ClientDCInternalInv o) {
return Long.compare(this.sortBy, o.sortBy);
}
public AppEngInternalInventory getInventory() {
return this.inventory;
}
public long getId() {
return this.id;
}
public boolean matchesSearch(String searchFilterLowerCase) {
return this.searchName.contains(searchFilterLowerCase);
}
}
@@ -0,0 +1,205 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2018, 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.client.me;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import net.minecraft.text.Text;
import appeng.api.AEApi;
import appeng.api.config.Settings;
import appeng.api.config.SortOrder;
import appeng.api.config.ViewItems;
import appeng.api.config.YesNo;
import appeng.api.storage.channels.IFluidStorageChannel;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IItemList;
import appeng.client.gui.widgets.IScrollSource;
import appeng.client.gui.widgets.ISortSource;
import appeng.core.AEConfig;
import appeng.fluids.util.FluidSorters;
import appeng.util.Platform;
import appeng.util.prioritylist.IPartitionList;
/**
* @author BrockWS
* @version rv6 - 22/05/2018
* @since rv6 22/05/2018
*/
public class FluidRepo {
private final IItemList<IAEFluidStack> list = AEApi.instance().storage()
.getStorageChannel(IFluidStorageChannel.class).createList();
private final ArrayList<IAEFluidStack> view = new ArrayList<>();
private final IScrollSource src;
private final ISortSource sortSrc;
private int rowSize = 9;
private String searchString = "";
private IPartitionList<IAEFluidStack> myPartitionList;
private boolean hasPower;
public FluidRepo(final IScrollSource src, final ISortSource sortSrc) {
this.src = src;
this.sortSrc = sortSrc;
}
public void updateView() {
this.view.clear();
this.view.ensureCapacity(this.list.size());
String innerSearch = this.searchString;
boolean searchMod = false;
if (innerSearch.startsWith("@")) {
searchMod = true;
innerSearch = innerSearch.substring(1);
}
Pattern m;
try {
m = Pattern.compile(innerSearch.toLowerCase(), Pattern.CASE_INSENSITIVE);
} catch (final Exception ignore1) {
try {
m = Pattern.compile(Pattern.quote(innerSearch.toLowerCase()), Pattern.CASE_INSENSITIVE);
} catch (final Exception ignore2) {
return;
}
}
final Enum viewMode = this.sortSrc.getSortDisplay();
final boolean needsZeroCopy = viewMode == ViewItems.CRAFTABLE;
final boolean terminalSearchToolTips = AEConfig.instance().getSearchTooltips() != YesNo.NO;
boolean notDone = false;
for (IAEFluidStack fs : this.list) {
if (this.myPartitionList != null && !this.myPartitionList.isListed(fs)) {
continue;
}
if (viewMode == ViewItems.CRAFTABLE && !fs.isCraftable()) {
continue;
}
if (viewMode == ViewItems.STORED && fs.getStackSize() == 0) {
continue;
}
final String dspName = searchMod ? Platform.getModId(fs) : Platform.getFluidDisplayName(fs).getString();
boolean foundMatchingFluidStack = false;
notDone = true;
if (m.matcher(dspName.toLowerCase()).find()) {
notDone = false;
foundMatchingFluidStack = true;
}
if (terminalSearchToolTips && notDone && !searchMod) {
final List<Text> tooltip = Platform.getTooltip(fs);
for (final Text line : tooltip) {
if (m.matcher(line.getString()).find()) {
foundMatchingFluidStack = true;
break;
}
}
}
if (foundMatchingFluidStack) {
if (needsZeroCopy) {
fs = fs.copy();
fs.setStackSize(0);
}
this.view.add(fs);
}
}
final Enum sortBy = this.sortSrc.getSortBy();
final Enum sortDir = this.sortSrc.getSortDir();
FluidSorters.setDirection((appeng.api.config.SortDir) sortDir);
if (sortBy == SortOrder.MOD) {
Collections.sort(this.view, FluidSorters.CONFIG_BASED_SORT_BY_MOD);
} else if (sortBy == SortOrder.AMOUNT) {
Collections.sort(this.view, FluidSorters.CONFIG_BASED_SORT_BY_SIZE);
} else {
Collections.sort(this.view, FluidSorters.CONFIG_BASED_SORT_BY_NAME);
}
}
public void postUpdate(final IAEFluidStack is) {
final IAEFluidStack st = this.list.findPrecise(is);
if (st != null) {
st.reset();
st.add(is);
} else {
this.list.add(is);
}
}
public IAEFluidStack getReferenceFluid(int idx) {
idx += this.src.getCurrentScroll() * this.rowSize;
if (idx >= this.view.size()) {
return null;
}
return this.view.get(idx);
}
public int size() {
return this.view.size();
}
public void clear() {
this.list.resetStatus();
}
public boolean hasPower() {
return this.hasPower;
}
public void setPower(final boolean hasPower) {
this.hasPower = hasPower;
}
public int getRowSize() {
return this.rowSize;
}
public void setRowSize(final int rowSize) {
this.rowSize = rowSize;
}
public String getSearchString() {
return this.searchString;
}
public void setSearchString(@Nonnull final String searchString) {
this.searchString = searchString;
}
}
@@ -0,0 +1,57 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2018, 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.client.me;
import appeng.api.storage.data.IAEFluidStack;
/**
* @author BrockWS
* @version rv6 - 22/05/2018
* @since rv6 22/05/2018
*/
public class InternalFluidSlotME {
private final int offset;
private final int xPos;
private final int yPos;
private final FluidRepo repo;
public InternalFluidSlotME(final FluidRepo def, final int offset, final int displayX, final int displayY) {
this.repo = def;
this.offset = offset;
this.xPos = displayX;
this.yPos = displayY;
}
IAEFluidStack getAEStack() {
return this.repo.getReferenceFluid(this.offset);
}
boolean hasPower() {
return this.repo.hasPower();
}
int getxPosition() {
return this.xPos;
}
int getyPosition() {
return this.yPos;
}
}
@@ -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.client.me;
import net.minecraft.item.ItemStack;
import appeng.api.storage.data.IAEItemStack;
public class InternalSlotME {
private final int offset;
private final int xPos;
private final int yPos;
private final ItemRepo repo;
public InternalSlotME(final ItemRepo def, final int offset, final int displayX, final int displayY) {
this.repo = def;
this.offset = offset;
this.xPos = displayX;
this.yPos = displayY;
}
ItemStack getStack() {
return this.getAEStack() == null ? ItemStack.EMPTY : this.getAEStack().asItemStackRepresentation();
}
IAEItemStack getAEStack() {
return this.repo.getReferenceItem(this.offset);
}
boolean hasPower() {
return this.repo.hasPower();
}
int getxPosition() {
return this.xPos;
}
int getyPosition() {
return this.yPos;
}
}
@@ -0,0 +1,228 @@
/*
* 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.client.me;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import appeng.api.AEApi;
import appeng.api.config.SearchBoxMode;
import appeng.api.config.SortOrder;
import appeng.api.config.ViewItems;
import appeng.api.config.YesNo;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.client.gui.widgets.IScrollSource;
import appeng.client.gui.widgets.ISortSource;
import appeng.core.AEConfig;
import appeng.integration.abstraction.JEIFacade;
import appeng.items.storage.ViewCellItem;
import appeng.util.ItemSorters;
import appeng.util.Platform;
import appeng.util.prioritylist.IPartitionList;
public class ItemRepo {
private final IItemList<IAEItemStack> list = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)
.createList();
private final ArrayList<IAEItemStack> view = new ArrayList<>();
private final IScrollSource src;
private final ISortSource sortSrc;
private int rowSize = 9;
private String searchString = "";
private IPartitionList<IAEItemStack> myPartitionList;
private String innerSearch = "";
private boolean hasPower;
public ItemRepo(final IScrollSource src, final ISortSource sortSrc) {
this.src = src;
this.sortSrc = sortSrc;
}
public IAEItemStack getReferenceItem(int idx) {
idx += this.src.getCurrentScroll() * this.rowSize;
if (idx >= this.view.size()) {
return null;
}
return this.view.get(idx);
}
void setSearch(final String search) {
this.searchString = search == null ? "" : search;
}
public void postUpdate(final IAEItemStack is) {
final IAEItemStack st = this.list.findPrecise(is);
if (st != null) {
st.reset();
st.add(is);
} else {
this.list.add(is);
}
}
public void setViewCell(final ItemStack[] list) {
this.myPartitionList = ViewCellItem.createFilter(list);
this.updateView();
}
public void updateView() {
this.view.clear();
this.view.ensureCapacity(this.list.size());
ViewItems viewMode = this.sortSrc.getSortDisplay();
SearchBoxMode searchMode = AEConfig.instance().getTerminalSearchMode();
final boolean needsZeroCopy = viewMode == ViewItems.CRAFTABLE;
if (searchMode == SearchBoxMode.JEI_AUTOSEARCH || searchMode == SearchBoxMode.JEI_MANUAL_SEARCH
|| searchMode == SearchBoxMode.JEI_AUTOSEARCH_KEEP
|| searchMode == SearchBoxMode.JEI_MANUAL_SEARCH_KEEP) {
this.updateJEI(this.searchString);
}
this.innerSearch = this.searchString;
final boolean terminalSearchToolTips = AEConfig.instance().getSearchTooltips() != YesNo.NO;
boolean searchMod = false;
if (this.innerSearch.startsWith("@")) {
searchMod = true;
this.innerSearch = this.innerSearch.substring(1);
}
Pattern m = null;
try {
m = Pattern.compile(this.innerSearch.toLowerCase(), Pattern.CASE_INSENSITIVE);
} catch (final Throwable ignore) {
try {
m = Pattern.compile(Pattern.quote(this.innerSearch.toLowerCase()), Pattern.CASE_INSENSITIVE);
} catch (final Throwable __) {
return;
}
}
boolean notDone = false;
for (IAEItemStack is : this.list) {
if (this.myPartitionList != null) {
if (!this.myPartitionList.isListed(is)) {
continue;
}
}
if (viewMode == ViewItems.CRAFTABLE && !is.isCraftable()) {
continue;
}
if (viewMode == ViewItems.STORED && is.getStackSize() == 0) {
continue;
}
final String dspName = searchMod ? Platform.getModId(is) : Platform.getItemDisplayName(is).getString();
boolean foundMatchingItemStack = false;
notDone = true;
if (m.matcher(dspName.toLowerCase()).find()) {
notDone = false;
foundMatchingItemStack = true;
}
if (terminalSearchToolTips && notDone && !searchMod) {
final List<Text> tooltip = Platform.getTooltip(is);
for (final Text line : tooltip) {
if (m.matcher(line.getString()).find()) {
foundMatchingItemStack = true;
notDone = false;
break;
}
}
}
if (foundMatchingItemStack) {
if (needsZeroCopy) {
is = is.copy();
is.setStackSize(0);
}
this.view.add(is);
}
}
final Enum SortBy = this.sortSrc.getSortBy();
final Enum SortDir = this.sortSrc.getSortDir();
ItemSorters.setDirection((appeng.api.config.SortDir) SortDir);
if (SortBy == SortOrder.MOD) {
Collections.sort(this.view, ItemSorters.CONFIG_BASED_SORT_BY_MOD);
} else if (SortBy == SortOrder.AMOUNT) {
Collections.sort(this.view, ItemSorters.CONFIG_BASED_SORT_BY_SIZE);
} else {
Collections.sort(this.view, ItemSorters.CONFIG_BASED_SORT_BY_NAME);
}
}
private void updateJEI(String filter) {
JEIFacade.instance().setSearchText(filter);
}
public int size() {
return this.view.size();
}
public void clear() {
this.list.resetStatus();
}
public boolean hasPower() {
return this.hasPower;
}
public void setPower(final boolean hasPower) {
this.hasPower = hasPower;
}
public int getRowSize() {
return this.rowSize;
}
public void setRowSize(final int rowSize) {
this.rowSize = rowSize;
}
public String getSearchString() {
return this.searchString;
}
public void setSearchString(@Nonnull final String searchString) {
this.searchString = searchString;
}
}
@@ -0,0 +1,86 @@
/*
* 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.client.me;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import appeng.container.slot.AppEngSlot;
import appeng.items.misc.EncodedPatternItem;
import appeng.util.Platform;
public class SlotDisconnected extends AppEngSlot {
private final ClientDCInternalInv mySlot;
public SlotDisconnected(final ClientDCInternalInv me, final int which, final int x, final int y) {
super(me.getInventory(), which, x, y);
this.mySlot = me;
}
@Override
public boolean canInsert(final ItemStack par1ItemStack) {
return false;
}
@Override
public void setStack(final ItemStack par1ItemStack) {
}
@Override
public boolean canTakeItems(final PlayerEntity par1PlayerEntity) {
return false;
}
@Override
public ItemStack getDisplayStack() {
if (Platform.isClient()) {
final ItemStack is = super.getStack();
if (!is.isEmpty() && is.getItem() instanceof EncodedPatternItem) {
final EncodedPatternItem iep = (EncodedPatternItem) is.getItem();
final ItemStack out = iep.getOutput(MinecraftClient.getInstance().world, is);
if (!out.isEmpty()) {
return out;
}
}
}
return super.getStack();
}
@Override
public boolean hasStack() {
return !this.getStack().isEmpty();
}
@Override
public int getMaxStackAmount() {
return 0;
}
@Override
public ItemStack takeStack(final int par1) {
return ItemStack.EMPTY;
}
public ClientDCInternalInv getSlot() {
return this.mySlot;
}
}
@@ -0,0 +1,91 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2018, 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.client.me;
import javax.annotation.Nonnull;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import appeng.api.storage.data.IAEFluidStack;
import appeng.fluids.container.slots.IMEFluidSlot;
/**
* @author BrockWS
* @version rv6 - 22/05/2018
* @since rv6 22/05/2018
*/
public class SlotFluidME extends Slot implements IMEFluidSlot {
private final InternalFluidSlotME slot;
public SlotFluidME(InternalFluidSlotME slot) {
super(null, 0, slot.getxPosition(), slot.getyPosition());
this.slot = slot;
}
@Override
public IAEFluidStack getAEFluidStack() {
if (this.slot.hasPower()) {
return this.slot.getAEStack();
}
return null;
}
@Override
public boolean canInsert(ItemStack stack) {
return false;
}
@Nonnull
@Override
public ItemStack getStack() {
return ItemStack.EMPTY;
}
@Override
public boolean hasStack() {
if (this.slot.hasPower()) {
return this.getAEFluidStack() != null;
}
return false;
}
@Override
public void setStack(final ItemStack par1ItemStack) {
}
@Override
public int getMaxStackAmount() {
return 0;
}
@Nonnull
@Override
public ItemStack takeStack(final int par1) {
return ItemStack.EMPTY;
}
@Override
public boolean canTakeItems(final PlayerEntity par1PlayerEntity) {
return false;
}
}
@@ -0,0 +1,82 @@
/*
* 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.client.me;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import appeng.api.storage.data.IAEItemStack;
public class SlotME extends Slot {
private final InternalSlotME mySlot;
public SlotME(final InternalSlotME me) {
super(null, 0, me.getxPosition(), me.getyPosition());
this.mySlot = me;
}
public IAEItemStack getAEStack() {
if (this.mySlot.hasPower()) {
return this.mySlot.getAEStack();
}
return null;
}
@Override
public boolean canInsert(ItemStack stack) {
return false;
}
@Override
public ItemStack getStack() {
if (this.mySlot.hasPower()) {
return this.mySlot.getStack();
}
return ItemStack.EMPTY;
}
@Override
public boolean hasStack() {
if (this.mySlot.hasPower()) {
return !this.getStack().isEmpty();
}
return false;
}
@Override
public void setStack(ItemStack stack) {
}
@Override
public int getMaxStackAmount() {
return 0;
}
@Override
public ItemStack takeStack(final int par1) {
return ItemStack.EMPTY;
}
@Override
public boolean canTakeItems(final PlayerEntity par1PlayerEntity) {
return false;
}
}
@@ -0,0 +1,92 @@
/*
* 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.client.render;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.AffineTransformation;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.util.math.Vector3f;
import appeng.api.storage.data.IAEItemStack;
import appeng.core.AEConfig;
import appeng.core.localization.GuiText;
import appeng.util.ISlimReadableNumberConverter;
import appeng.util.IWideReadableNumberConverter;
import appeng.util.ReadableNumberConverter;
/**
* @author AlgorithmX2
* @author thatsIch
* @version rv2
* @since rv0
*/
public class StackSizeRenderer {
private static final ISlimReadableNumberConverter SLIM_CONVERTER = ReadableNumberConverter.INSTANCE;
private static final IWideReadableNumberConverter WIDE_CONVERTER = ReadableNumberConverter.INSTANCE;
public void renderStackSize(TextRenderer fontRenderer, IAEItemStack aeStack, int xPos, int yPos) {
if (aeStack != null) {
if (aeStack.getStackSize() == 0 && aeStack.isCraftable()) {
final String craftLabelText = AEConfig.instance().isUseLargeFonts() ? GuiText.LargeFontCraft.getLocal()
: GuiText.SmallFontCraft.getLocal();
renderSizeLabel(fontRenderer, xPos, yPos, craftLabelText);
}
if (aeStack.getStackSize() > 0) {
final String stackSize = this.getToBeRenderedStackSize(aeStack.getStackSize());
renderSizeLabel(fontRenderer, xPos, yPos, stackSize);
}
}
}
public static void renderSizeLabel(TextRenderer fontRenderer, float xPos, float yPos, String text) {
final float scaleFactor = AEConfig.instance().isUseLargeFonts() ? 0.85f : 0.5f;
final float inverseScaleFactor = 1.0f / scaleFactor;
final int offset = AEConfig.instance().isUseLargeFonts() ? 0 : -1;
AffineTransformation tm = new AffineTransformation(new Vector3f(0, 0, 300), // Taken from
// ItemRenderer.renderItemOverlayIntoGUI
null, new Vector3f(scaleFactor, scaleFactor, scaleFactor), null);
RenderSystem.disableBlend();
final int X = (int) ((xPos + offset + 16.0f - fontRenderer.getWidth(text) * scaleFactor)
* inverseScaleFactor);
final int Y = (int) ((yPos + offset + 16.0f - 7.0f * scaleFactor) * inverseScaleFactor);
VertexConsumerProvider.Immediate buffer = VertexConsumerProvider.immediate(Tessellator.getInstance().getBuffer());
fontRenderer.draw(text, X, Y, 16777215, true, tm.getMatrix(), buffer, false, 0, 15728880);
buffer.draw();
RenderSystem.enableBlend();
}
private String getToBeRenderedStackSize(final long originalSize) {
if (AEConfig.instance().isUseLargeFonts()) {
return SLIM_CONVERTER.toSlimReadableForm(originalSize);
} else {
return WIDE_CONVERTER.toWideReadableForm(originalSize);
}
}
}
@@ -0,0 +1,46 @@
/*
* 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.client.render;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.client.color.block.BlockColorProvider;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockRenderView;
import appeng.api.util.AEColor;
/**
* Returns the shades of a single AE color for tint indices 0, 1, and 2.
*/
public class StaticBlockColor implements BlockColorProvider {
private final AEColor color;
public StaticBlockColor(AEColor color) {
this.color = color;
}
@Override
public int getColor(BlockState state, @Nullable BlockRenderView worldIn, @Nullable BlockPos pos, int tintIndex) {
return this.color.getVariantByTintIndex(tintIndex);
}
}
@@ -0,0 +1,135 @@
/*
* 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.client.render;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.Direction;
import appeng.api.storage.data.IAEItemStack;
import appeng.util.IWideReadableNumberConverter;
import appeng.util.ReadableNumberConverter;
/**
* Helper methods for rendering TESRs.
*/
public class TesrRenderHelper {
private static final IWideReadableNumberConverter NUMBER_CONVERTER = ReadableNumberConverter.INSTANCE;
/**
* Rotate the current coordinate system so it is on the face of the given block
* side. This can be used to render on the given face as if it was a 2D canvas.
*/
public static void rotateToFace(MatrixStack mStack, Direction face, byte spin) {
switch (face) {
case UP:
mStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(270));
mStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(-spin * 90.0F));
break;
case DOWN:
mStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(90.0F));
mStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(spin * -90.0F));
break;
case EAST:
mStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(90.0F));
break;
case WEST:
mStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(-90.0F));
break;
case NORTH:
mStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(180.0F));
break;
case SOUTH:
break;
default:
break;
}
}
// TODO, A different approach will have to be used for this from TESRs, -covers,
// i have ideas.
/**
* Render an item in 2D.
*/
public static void renderItem2d(MatrixStack matrixStack, VertexConsumerProvider buffers, ItemStack itemStack,
float scale, int combinedLightIn, int combinedOverlayIn) {
if (!itemStack.isEmpty()) {
matrixStack.push();
// Push it out of the block face a bit to avoid z-fighting
matrixStack.translate(0, 0, 0.01f);
// The Z-scaling by 0.0002 causes the model to be visually "flattened"
// This cannot replace a proper projection, but it's cheap and gives the desired
// effect at least from head-on
matrixStack.scale(scale, scale, 0.0002f);
MinecraftClient.getInstance().getItemRenderer().renderItem(itemStack, ModelTransformation.Mode.GUI,
combinedLightIn, OverlayTexture.DEFAULT_UV, matrixStack, buffers);
matrixStack.pop();
}
}
/**
* Render an item in 2D and the given text below it.
*
* @param matrixStack
* @param buffers
* @param spacing Specifies how far apart the item and the item stack
* amount are rendered.
* @param combinedLightIn
* @param combinedOverlayIn
*/
public static void renderItem2dWithAmount(MatrixStack matrixStack, VertexConsumerProvider buffers,
IAEItemStack itemStack, float itemScale, float spacing, int combinedLightIn, int combinedOverlayIn) {
final ItemStack renderStack = itemStack.asItemStackRepresentation();
TesrRenderHelper.renderItem2d(matrixStack, buffers, renderStack, itemScale, combinedLightIn, combinedOverlayIn);
final long stackSize = itemStack.getStackSize();
final String renderedStackSize = NUMBER_CONVERTER.toWideReadableForm(stackSize);
// Render the item count
final TextRenderer fr = MinecraftClient.getInstance().textRenderer;
final int width = fr.getWidth(renderedStackSize);
matrixStack.push();
matrixStack.translate(0.0f, spacing, 0.02f);
matrixStack.scale(1.0f / 62.0f, -1.0f / 62.0f, 1.0f / 62.0f);
matrixStack.scale(0.5f, 0.5f, 0);
matrixStack.translate(-0.5f * width, 0.0f, 0.5f);
fr.draw(renderedStackSize, 0, 0, -1, false, matrixStack.peek().getModel(), buffers, false, 0,
15728880);
matrixStack.pop();
}
}
@@ -0,0 +1,40 @@
/*
* 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.client.render.crafting;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.RenderLayer;
import net.fabricmc.api.EnvType;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
/**
* Rendering customization for the crafting cube.
*/
public class CraftingCubeRendering extends BlockRenderingCustomizer {
@Override
@Environment(EnvType.CLIENT)
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
rendering.renderType(RenderLayer.getCutout());
// Disable auto-rotation
rendering.modelCustomizer((loc, model) -> model);
}
}
@@ -0,0 +1,47 @@
package appeng.client.render.model;
import java.util.Objects;
import net.minecraft.util.math.Direction;
import appeng.block.storage.DriveSlotsState;
public class DriveModelData extends AEModelData {
private final DriveSlotsState slotsState;
public DriveModelData(Direction up, Direction forward, DriveSlotsState slotsState) {
super(up, forward);
this.slotsState = slotsState;
}
@Override
public boolean isCacheable() {
return false; // Too many combinations
}
public DriveSlotsState getSlotsState() {
return slotsState;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
DriveModelData that = (DriveModelData) o;
return slotsState.equals(that.slotsState);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), slotsState);
}
}
@@ -0,0 +1,54 @@
/*
* 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.client.render.renderable;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.render.model.json.Transformation;
import net.minecraft.item.ItemStack;
import org.apache.commons.lang3.tuple.Pair;
import java.util.function.Function;
public class ItemRenderable<T extends BlockEntity> implements Renderable<T> {
private final Function<T, Pair<ItemStack, Transformation>> f;
public ItemRenderable(Function<T, Pair<ItemStack, Transformation>> f) {
this.f = f;
}
@Override
public void renderTileEntityAt(T te, float partialTicks, net.minecraft.client.util.math.MatrixStack matrixStack,
VertexConsumerProvider buffers, int combinedLight, int combinedOverlay) {
Pair<ItemStack, Transformation> pair = this.f.apply(te);
if (pair != null && pair.getLeft() != null) {
matrixStack.push();
if (pair.getRight() != null) {
pair.getRight().apply(true, matrixStack); // FIXME: check left handed
}
MinecraftClient.getInstance().getItemRenderer().renderItem(pair.getLeft(),
ModelTransformation.Mode.GROUND, combinedLight, combinedOverlay, matrixStack, buffers);
matrixStack.pop();
}
}
}
@@ -0,0 +1,31 @@
/*
* 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.client.render.renderable;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.block.entity.BlockEntity;
public interface Renderable<T extends BlockEntity> {
void renderTileEntityAt(T te, float partialTicks, MatrixStack matrixStack, VertexConsumerProvider buffers,
int combinedLight, int combinedOverlay);
}
@@ -0,0 +1,37 @@
/*
* 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.client.render.spatial;
import net.fabricmc.api.EnvType;
import net.minecraft.client.render.RenderLayer;
import net.fabricmc.api.Environment;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
public class SpatialPylonRendering extends BlockRenderingCustomizer {
@Override
@Environment(EnvType.CLIENT)
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
rendering.renderType(RenderLayer.getCutout());
}
}
@@ -0,0 +1,72 @@
/*
* 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.client.render.tesr;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.TexturedRenderLayers;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.util.math.Quaternion;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import appeng.client.render.FacingToRotation;
import appeng.tile.grindstone.CrankBlockEntity;
/**
* This FastTESR only handles the animated model of the turning crank. When the
* crank is at rest, it is rendered using a normal model.
*/
@Environment(EnvType.CLIENT)
public class CrankTESR extends BlockEntityRenderer<CrankBlockEntity> {
public CrankTESR(BlockEntityRenderDispatcher rendererDispatcherIn) {
super(rendererDispatcherIn);
}
@Override
public void render(CrankBlockEntity te, float partialTicks, MatrixStack ms, VertexConsumerProvider buffers,
int combinedLightIn, int combinedOverlayIn) {
// Apply GL transformations relative to the center of the block: 1) TE rotation
// and 2) crank rotation
ms.push();
ms.translate(0.5, 0.5, 0.5);
FacingToRotation.get(te.getForward(), te.getUp()).push(ms);
ms.multiply(new Quaternion(0, te.getVisibleRotation(), 0, true));
ms.translate(-0.5, -0.5, -0.5);
BlockState blockState = te.getCachedState();
BlockRenderManager dispatcher = MinecraftClient.getInstance().getBlockRenderManager();
BakedModel model = dispatcher.getModel(blockState);
VertexConsumer buffer = buffers.getBuffer(TexturedRenderLayers.getEntityTranslucentCull());
dispatcher.getModelRenderer().render(ms.peek(), buffer, null, model, 1, 1, 1,
combinedLightIn, combinedOverlayIn);
ms.pop();
}
}
@@ -0,0 +1,143 @@
package appeng.client.render.tesr;
import java.util.EnumMap;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.Vector3f;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.block.storage.DriveSlotState;
import appeng.client.render.FacingToRotation;
import appeng.tile.storage.DriveBlockEntity;
/**
* Renders the drive cell status indicators.
*/
@Environment(EnvType.CLIENT)
public class DriveLedTileEntityRenderer extends BlockEntityRenderer<DriveBlockEntity> {
private static final EnumMap<DriveSlotState, Vector3f> STATE_COLORS;
// Color used for the cell indicator for blinking during recent activity
private static final Vector3f BLINK_COLOR = new Vector3f(1, 0.5f, 0.5f);
static {
STATE_COLORS = new EnumMap<>(DriveSlotState.class);
STATE_COLORS.put(DriveSlotState.OFFLINE, new Vector3f(0, 0, 0));
STATE_COLORS.put(DriveSlotState.ONLINE, new Vector3f(0, 1, 0));
STATE_COLORS.put(DriveSlotState.NOT_EMPTY, new Vector3f(0f, 0.667f, 1));
STATE_COLORS.put(DriveSlotState.TYPES_FULL, new Vector3f(1, 0.667f, 0));
STATE_COLORS.put(DriveSlotState.FULL, new Vector3f(1, 0, 0));
}
private static final float L = 14 / 16.f; // left (x-axis)
private static final float R = 13 / 16.f; // right (x-axis)
private static final float T = 14 / 16.f; // top (x-axis)
private static final float B = 12.999f / 16.f; // bottom (x-axis)
private static final float FR = 0.999f / 16.f; // front (z-axis)
private static final float BA = 1.499f / 16.f; // back (z-axis)
// Vertex data for the LED cuboid (has no back)
// Directions are when looking from the front onto the LED
private static final float[] LED_QUADS = {
// Front Face
R, T, FR, L, T, FR, L, B, FR, R, B, FR,
// Left Face
L, T, FR, L, T, BA, L, B, BA, L, B, FR,
// Right Face
R, T, BA, R, T, FR, R, B, FR, R, B, BA,
// Top Face
R, T, BA, L, T, BA, L, T, FR, R, T, FR,
// Bottom Face
R, B, FR, L, B, FR, L, B, BA, R, B, BA, };
private static final RenderLayer STATE = RenderLayer.of("ae_drive_leds", VertexFormats.POSITION_COLOR, 7,
32565, false, true, RenderLayer.MultiPhaseParameters.builder().build(false));
public DriveLedTileEntityRenderer(BlockEntityRenderDispatcher rendererDispatcherIn) {
super(rendererDispatcherIn);
}
@Override
public void render(DriveBlockEntity drive, float partialTicks, MatrixStack ms, VertexConsumerProvider buffers,
int combinedLightIn, int combinedOverlayIn) {
if (drive.getCellCount() != 10) {
throw new IllegalStateException("Expected drive to have 10 slots");
}
ms.push();
ms.translate(0.5, 0.5, 0.5);
FacingToRotation.get(drive.getForward(), drive.getUp()).push(ms);
ms.translate(-0.5, -0.5, -0.5);
VertexConsumer buffer = buffers.getBuffer(STATE);
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 2; col++) {
int slot = row * 2 + col;
Vector3f color = getColorForSlot(drive, slot, partialTicks);
if (color == null) {
continue;
}
ms.push();
// Position this drive model copy at the correct slot. The transform is based on
// the
// cell-model being in slot 0,0 at the top left of the drive.
float xOffset = -col * 8 / 16.0f;
float yOffset = -row * 3 / 16.0f;
ms.translate(xOffset, yOffset, 0);
for (int i = 0; i < LED_QUADS.length; i += 3) {
float x = LED_QUADS[i];
float y = LED_QUADS[i + 1];
float z = LED_QUADS[i + 2];
buffer.vertex(ms.peek().getModel(), x, y, z).color(color.getX(), color.getY(), color.getZ(), 1.f)
.next();
}
ms.pop();
}
}
ms.pop();
}
private Vector3f getColorForSlot(DriveBlockEntity drive, int slot, float partialTicks) {
DriveSlotState state = DriveSlotState.fromCellStatus(drive.getCellStatus(slot));
if (state == DriveSlotState.EMPTY) {
return null;
}
if (!drive.isPowered()) {
return STATE_COLORS.get(DriveSlotState.OFFLINE);
}
Vector3f col = STATE_COLORS.get(state);
if (drive.isCellBlinking(slot)) {
// 200 ms interval (100ms to get to red, then 100ms back)
long t = System.currentTimeMillis() % 200;
float f = (t - 100) / 200.0f + 0.5f;
f = easeInOutCubic(f);
col = col.copy();
col.lerp(BLINK_COLOR, f);
}
return col;
}
private static float easeInOutCubic(float x) {
return x < 0.5f ? 4 * x * x * x : 1 - (float) Math.pow(-2 * x + 2, 3) / 2;
}
}
@@ -0,0 +1,231 @@
package appeng.client.render.tesr;
import alexiil.mc.lib.attributes.item.FixedItemInv;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.item.Item;
import net.minecraft.tag.ItemTags;
import net.minecraft.tag.Tag;
import net.minecraft.util.math.Quaternion;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Identifier;
import appeng.api.features.InscriberProcessType;
import appeng.client.render.FacingToRotation;
import appeng.core.AppEng;
import appeng.recipes.handlers.InscriberRecipe;
import appeng.tile.misc.InscriberBlockEntity;
/**
* Renders the dynamic parts of an inscriber (the presses, the animation and the
* item being smashed)
*/
public final class InscriberTESR extends BlockEntityRenderer<InscriberBlockEntity> {
private static final float ITEM_RENDER_SCALE = 1.0f / 1.2f;
private static final SpriteIdentifier TEXTURE_INSIDE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "block/inscriber_inside"));
public static final ImmutableList<SpriteIdentifier> SPRITES = ImmutableList.of(
TEXTURE_INSIDE
);
public InscriberTESR(BlockEntityRenderDispatcher rendererDispatcherIn) {
super(rendererDispatcherIn);
}
@Override
public void render(InscriberBlockEntity tile, float partialTicks, MatrixStack ms, VertexConsumerProvider buffers,
int combinedLight, int combinedOverlay) {
// render inscriber
ms.push();
ms.translate(0.5F, 0.5F, 0.5F);
FacingToRotation.get(tile.getForward(), tile.getUp()).push(ms);
ms.translate(-0.5F, -0.5F, -0.5F);
// render sides of stamps
long absoluteProgress = 0;
if (tile.isSmash()) {
final long currentTime = System.currentTimeMillis();
absoluteProgress = currentTime - tile.getClientStart();
if (absoluteProgress > 800) {
tile.setSmash(false);
}
}
final float relativeProgress = absoluteProgress % 800 / 400.0f;
float progress = relativeProgress;
if (progress > 1.0f) {
progress = 1.0f - (easeDecompressMotion(progress - 1.0f));
} else {
progress = easeCompressMotion(progress);
}
float press = 0.2f;
press -= progress / 5.0f;
float middle = 0.5f;
middle += 0.02f;
final float TwoPx = 2.0f / 16.0f;
final float base = 0.4f;
final Sprite tas = TEXTURE_INSIDE.getSprite();
VertexConsumer buffer = buffers.getBuffer(RenderLayer.getSolid());
// Bottom of Top Stamp
addVertex(buffer, ms, tas, TwoPx, middle + press, TwoPx, 2, 13, combinedOverlay, combinedLight, Direction.DOWN);
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle + press, TwoPx, 14, 13, combinedOverlay, combinedLight,
Direction.DOWN);
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle + press, 1.0f - TwoPx, 14, 2, combinedOverlay, combinedLight,
Direction.DOWN);
addVertex(buffer, ms, tas, TwoPx, middle + press, 1.0f - TwoPx, 2, 2, combinedOverlay, combinedLight,
Direction.DOWN);
// Front of Top Stamp
addVertex(buffer, ms, tas, TwoPx, middle + base, TwoPx, 2, 3 - 16 * (press - base), combinedOverlay,
combinedLight, Direction.NORTH);
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle + base, TwoPx, 14, 3 - 16 * (press - base), combinedOverlay,
combinedLight, Direction.NORTH);
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle + press, TwoPx, 14, 3, combinedOverlay, combinedLight,
Direction.NORTH);
addVertex(buffer, ms, tas, TwoPx, middle + press, TwoPx, 2, 3, combinedOverlay, combinedLight, Direction.NORTH);
// Top of Bottom Stamp
middle -= 2.0f * 0.02f;
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle - press, TwoPx, 2, 13, combinedOverlay, combinedLight,
Direction.UP);
addVertex(buffer, ms, tas, TwoPx, middle - press, TwoPx, 14, 13, combinedOverlay, combinedLight, Direction.UP);
addVertex(buffer, ms, tas, TwoPx, middle - press, 1.0f - TwoPx, 14, 2, combinedOverlay, combinedLight,
Direction.UP);
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle - press, 1.0f - TwoPx, 2, 2, combinedOverlay, combinedLight,
Direction.UP);
// Front of Bottom Stamp
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle + -base, TwoPx, 2, 3 - 16 * (press - base), combinedOverlay,
combinedLight, Direction.NORTH);
addVertex(buffer, ms, tas, TwoPx, middle - base, TwoPx, 14, 3 - 16 * (press - base), combinedOverlay,
combinedLight, Direction.NORTH);
addVertex(buffer, ms, tas, TwoPx, middle - press, TwoPx, 14, 3, combinedOverlay, combinedLight,
Direction.NORTH);
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle - press, TwoPx, 2, 3, combinedOverlay, combinedLight,
Direction.NORTH);
// render items.
FixedItemInv tileInv = tile.getInternalInventory();
int items = 0;
if (!tileInv.getInvStack(0).isEmpty()) {
items++;
}
if (!tileInv.getInvStack(1).isEmpty()) {
items++;
}
if (!tileInv.getInvStack(2).isEmpty()) {
items++;
}
boolean renderPresses;
if (relativeProgress > 1.0f || items == 0) {
// When crafting completes, dont render the presses (they mave have been
// consumed, see below)
renderPresses = false;
ItemStack is = tileInv.getInvStack(3);
if (is.isEmpty()) {
final InscriberRecipe ir = tile.getTask();
if (ir != null) {
// The "PRESS" type will consume the presses so they should not render after
// completing
// the press animation
renderPresses = ir.getProcessType() == InscriberProcessType.INSCRIBE;
is = ir.getOutput().copy();
}
}
this.renderItem(ms, is, 0.0f, buffers, combinedLight, combinedOverlay);
} else {
renderPresses = true;
this.renderItem(ms, tileInv.getInvStack(2), 0.0f, buffers, combinedLight, combinedOverlay);
}
if (renderPresses) {
this.renderItem(ms, tileInv.getInvStack(0), press, buffers, combinedLight, combinedOverlay);
this.renderItem(ms, tileInv.getInvStack(1), -press, buffers, combinedLight, combinedOverlay);
}
ms.pop();
}
private static void addVertex(VertexConsumer vb, MatrixStack ms, Sprite sprite, float x, float y,
float z, double texU, double texV, int overlayUV, int lightmapUV, Direction front) {
vb.vertex(ms.peek().getModel(), x, y, z);
vb.color(1.0f, 1.0f, 1.0f, 1.0f);
vb.texture(sprite.getFrameU(texU), sprite.getFrameV(texV));
vb.overlay(overlayUV);
vb.light(lightmapUV);
vb.normal(ms.peek().getNormal(), front.getOffsetX(), front.getOffsetY(), front.getOffsetZ());
vb.next();
}
private static final Identifier TAG_STORAGE_BLOCKS = new Identifier("forge:storage_blocks");
private void renderItem(MatrixStack ms, final ItemStack stack, final float o, VertexConsumerProvider buffers,
int combinedLight, int combinedOverlay) {
if (!stack.isEmpty()) {
ms.push();
// move to center
ms.translate(0.5f, 0.5f + o, 0.5f);
ms.multiply(new Quaternion(90, 0, 0, true));
// set scale
ms.scale(ITEM_RENDER_SCALE, ITEM_RENDER_SCALE, ITEM_RENDER_SCALE);
ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer();
// heuristic to scale items down much further than blocks
Tag<Item> storageBlockTag = ItemTags.getContainer().get(TAG_STORAGE_BLOCKS);
if (storageBlockTag == null || !stack.getItem().isIn(storageBlockTag)) {
ms.scale(0.5f, 0.5f, 0.5f);
}
itemRenderer.renderItem(stack, ModelTransformation.Mode.FIXED, combinedLight, combinedOverlay, ms,
buffers);
ms.pop();
}
}
// See https://easings.net/#easeOutBack
private static float easeCompressMotion(float x) {
float c1 = 1.70158f;
float c3 = c1 + 1;
return (float) (1 + c3 * Math.pow(x - 1, 3) + c1 * Math.pow(x - 1, 2));
}
// See https://easings.net/#easeInQuint
private static float easeDecompressMotion(float x) {
return x * x * x * x * x;
}
}
@@ -0,0 +1,60 @@
/*
* 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.client.render.tesr;
import java.util.List;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.render.VertexConsumerProvider;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.client.render.FacingToRotation;
import appeng.client.render.renderable.Renderable;
import appeng.tile.AEBaseBlockEntity;
@Environment(EnvType.CLIENT)
public class ModularTESR<T extends AEBaseBlockEntity> extends BlockEntityRenderer<T> {
private final List<Renderable<? super T>> renderables;
@SafeVarargs
public ModularTESR(BlockEntityRenderDispatcher rendererDispatcherIn, Renderable<? super T>... renderables) {
super(rendererDispatcherIn);
this.renderables = ImmutableList.copyOf(renderables);
}
@Override
public void render(T te, float partialTicks, MatrixStack ms, VertexConsumerProvider buffers, int combinedLight,
int combinedOverlay) {
ms.push();
ms.translate(0.5, 0.5, 0.5);
FacingToRotation.get(te.getForward(), te.getUp()).push(ms);
ms.translate(-0.5, -0.5, -0.5);
for (Renderable<? super T> renderable : this.renderables) {
renderable.renderTileEntityAt(te, partialTicks, ms, buffers, combinedLight, combinedOverlay);
}
ms.pop();
}
}
File diff suppressed because it is too large Load Diff
@@ -18,7 +18,10 @@
package appeng.container;
import appeng.api.parts.IPartHost;
import appeng.api.util.AEPartLocation;
import appeng.api.util.DimensionalCoord;
import appeng.parts.AEBasePart;
import com.google.common.base.Preconditions;
import io.netty.handler.codec.DecoderException;
import net.minecraft.block.entity.BlockEntity;
@@ -123,12 +126,11 @@ public final class ContainerLocator {
throw new IllegalArgumentException("Could not find item held in hand " + hand + " in player inventory");
}
// FIXME FABRIC public static ContainerLocator forPart(AEBasePart part) {
// FIXME FABRIC IPartHost host = part.getHost();
// FIXME FABRIC DimensionalCoord pos = host.getLocation();
// FIXME FABRIC return new ContainerLocator(Type.PART, -1, pos.getWorld().getDimension().getType().getId(), pos.getBlockPos(),
// FIXME FABRIC part.getSide());
// FIXME FABRIC }
public static ContainerLocator forPart(AEBasePart part) {
IPartHost host = part.getHost();
DimensionalCoord pos = host.getLocation();
return new ContainerLocator(Type.PART, -1, pos.getWorld().getWorld(), pos.getBlockPos(), part.getSide());
}
public boolean hasItemIndex() {
return type == Type.PLAYER_INVENTORY || type == Type.PLAYER_INVENTORY_WITH_BLOCK_CONTEXT;
@@ -0,0 +1,37 @@
/*
* 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.container;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.screen.ScreenHandler;
/*
* Totally useless container that does nothing.
*/
public class ContainerNull extends ScreenHandler {
public ContainerNull() {
super(null, 0);
}
@Override
public boolean canUse(PlayerEntity player) {
return false;
}
}
@@ -0,0 +1,42 @@
package appeng.container;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.screen.ScreenHandlerType;
import appeng.core.AELog;
/**
* Allows opening containers generically.
*/
public final class ContainerOpener {
private ContainerOpener() {
}
private static final Map<ScreenHandlerType<? extends AEBaseContainer>, Opener<?>> registry = new HashMap<>();
public static <T extends AEBaseContainer> void addOpener(ScreenHandlerType<T> type, Opener<T> opener) {
registry.put(type, opener);
}
public static boolean openContainer(ScreenHandlerType<?> type, PlayerEntity player, ContainerLocator locator) {
Opener<?> opener = registry.get(type);
if (opener == null) {
AELog.warn("Trying to open container for unknown container type {}", type);
return false;
}
return opener.open(player, locator);
}
@FunctionalInterface
public interface Opener<T extends AEBaseContainer> {
boolean open(PlayerEntity player, ContainerLocator locator);
}
}
@@ -0,0 +1,35 @@
/*
* 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.container.guisync;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotates that this field should be synchronized between the server and
* client. Requires the field to be public.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface GuiSync {
int value();
}
@@ -0,0 +1,186 @@
/*
* 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.container.guisync;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.util.Objects;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.screen.ScreenHandlerListener;
import net.minecraft.text.Text;
import appeng.container.AEBaseContainer;
import appeng.core.AELog;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigValuePacket;
import appeng.core.sync.packets.ProgressBarPacket;
/**
* This class is responsible for synchronizing Container-fields from server to
* client.
*/
public class SyncData {
private final AEBaseContainer source;
private final Field field;
private final Class<?> fieldType;
private final int channel;
private final MethodHandle getter;
private final MethodHandle setter;
private Object clientVersion;
public SyncData(final AEBaseContainer container, final Field field, final GuiSync annotation) {
this.clientVersion = null;
this.source = container;
this.channel = annotation.value();
this.field = field;
this.fieldType = field.getType();
try {
this.getter = MethodHandles.publicLookup().unreflectGetter(field);
this.setter = MethodHandles.publicLookup().unreflectSetter(field);
} catch (IllegalAccessException e) {
throw new RuntimeException(
"Failed to get accessor for field " + field + ". Did you forget to make it public?");
}
}
public int getChannel() {
return this.channel;
}
public void tick(final ScreenHandlerListener c) {
try {
final Object val = this.getter.invoke(source);
if (!Objects.equals(val, this.clientVersion)) {
this.send(c, val);
}
} catch (Throwable e) {
AELog.debug(e);
}
}
private void send(final ScreenHandlerListener o, Object val) {
if (fieldType.isAssignableFrom(Text.class)) {
if (o instanceof ServerPlayerEntity) {
String json = "";
if (val != null) {
json = Text.Serializer.toJson((Text) val);
}
NetworkHandler.instance().sendTo(new ConfigValuePacket("SyncDat." + this.channel, json),
(ServerPlayerEntity) o);
}
}
// Types other than Text must be non-null
if (val == null) {
return;
}
if (fieldType.equals(String.class)) {
if (o instanceof ServerPlayerEntity) {
NetworkHandler.instance().sendTo(new ConfigValuePacket("SyncDat." + this.channel, (String) val),
(ServerPlayerEntity) o);
}
} else if (this.fieldType.isEnum()) {
o.onPropertyUpdate(this.source, this.channel, ((Enum<?>) val).ordinal());
} else if (val instanceof Long) {
if (o instanceof ServerPlayerEntity) {
NetworkHandler.instance().sendTo(new ProgressBarPacket(this.channel, (Long) val),
(ServerPlayerEntity) o);
}
} else if (fieldType.equals(Boolean.class) || fieldType.equals(boolean.class)) {
o.onPropertyUpdate(this.source, this.channel, ((Boolean) val) ? 1 : 0);
} else if (fieldType.equals(Integer.class) || fieldType.equals(int.class)) {
o.onPropertyUpdate(this.source, this.channel, (Integer) val);
} else {
throw new IllegalStateException("Unknown field type: " + fieldType);
}
this.clientVersion = val;
}
public void update(Object val) {
try {
final Object oldValue = this.getter.invoke(source);
if (val instanceof String) {
if (this.fieldType.isAssignableFrom(Text.class)) {
String json = (String) val;
Text text = null;
if (!json.isEmpty()) {
text = Text.Serializer.fromJson((String) val);
}
this.updateTextComponent(text);
} else {
this.updateString((String) val);
}
} else {
this.updateValue(oldValue, (Long) val);
}
} catch (Throwable e) {
AELog.debug(e);
}
}
private void updateString(final String val) {
try {
this.setter.invoke(source, val);
} catch (Throwable e) {
AELog.debug(e);
}
}
private void updateTextComponent(final Text val) {
try {
this.setter.invoke(source, val);
} catch (Throwable e) {
AELog.debug(e);
}
}
private void updateValue(final Object oldValue, final long val) {
try {
if (this.fieldType.isEnum()) {
Object e = this.fieldType.getEnumConstants()[(int) val];
this.setter.invoke(source, e);
} else {
if (this.fieldType.equals(int.class)) {
this.setter.invoke(source, (int) val);
} else if (this.fieldType.equals(long.class)) {
this.setter.invoke(source, val);
} else if (this.fieldType.equals(boolean.class)) {
this.setter.invoke(source, val == 1);
} else if (this.fieldType.equals(Integer.class)) {
this.setter.invoke(source, (int) val);
} else if (this.fieldType.equals(Long.class)) {
this.setter.invoke(source, val);
} else if (this.fieldType.equals(Boolean.class)) {
this.setter.invoke(source, val == 1);
}
}
this.source.onUpdate(this.field.getName(), oldValue, this.getter.invoke(source));
} catch (Throwable e) {
AELog.debug(e);
}
}
}
@@ -0,0 +1,241 @@
/*
* 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.container.implementations;
import java.util.Iterator;
import alexiil.mc.lib.attributes.item.FixedItemInv;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.screen.slot.Slot;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.screen.ScreenHandlerListener;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
import alexiil.mc.lib.attributes.item.impl.EmptyFixedItemInv;
import appeng.api.AEApi;
import appeng.api.config.CopyMode;
import appeng.api.config.FuzzyMode;
import appeng.api.config.Settings;
import appeng.api.implementations.items.IStorageCell;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.cells.ICellWorkbenchItem;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList;
import appeng.container.ContainerLocator;
import appeng.container.guisync.GuiSync;
import appeng.container.slot.FakeTypeOnlySlot;
import appeng.container.slot.OptionalRestrictedInputSlot;
import appeng.container.slot.RestrictedInputSlot;
import appeng.tile.misc.CellWorkbenchBlockEntity;
import appeng.util.EnumCycler;
import appeng.util.Platform;
import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.inv.WrapperSupplierItemHandler;
import appeng.util.iterators.NullIterator;
public class CellWorkbenchContainer extends UpgradeableContainer {
public static ScreenHandlerType<CellWorkbenchContainer> TYPE;
private static final ContainerHelper<CellWorkbenchContainer, CellWorkbenchBlockEntity> helper = new ContainerHelper<>(
CellWorkbenchContainer::new, CellWorkbenchBlockEntity.class);
private final CellWorkbenchBlockEntity workBench;
@GuiSync(2)
public CopyMode copyMode = CopyMode.CLEAR_ON_REMOVE;
private ItemStack prevStack = ItemStack.EMPTY;
private int lastUpgrades = 0;
public CellWorkbenchContainer(int id, final PlayerInventory ip, final CellWorkbenchBlockEntity te) {
super(TYPE, id, ip, te);
this.workBench = te;
}
public static CellWorkbenchContainer fromNetwork(int windowId, PlayerInventory inv, PacketByteBuf buf) {
return helper.fromNetwork(windowId, inv, buf);
}
public static boolean open(PlayerEntity player, ContainerLocator locator) {
return helper.open(player, locator);
}
public void setFuzzy(final FuzzyMode valueOf) {
final ICellWorkbenchItem cwi = this.workBench.getCell();
if (cwi != null) {
cwi.setFuzzyMode(this.workBench.getInventoryByName("cell").getInvStack(0), valueOf);
}
}
public void nextWorkBenchCopyMode() {
this.workBench.getConfigManager().putSetting(Settings.COPY_MODE, EnumCycler.next(this.getWorkBenchCopyMode()));
}
private CopyMode getWorkBenchCopyMode() {
return (CopyMode) this.workBench.getConfigManager().getSetting(Settings.COPY_MODE);
}
@Override
protected int getHeight() {
return 251;
}
@Override
protected void setupConfig() {
final FixedItemInv cell = this.getUpgradeable().getInventoryByName("cell");
this.addSlot(new RestrictedInputSlot(RestrictedInputSlot.PlacableItemType.WORKBENCH_CELL, cell, 0, 152, 8,
this.getPlayerInv()));
final FixedItemInv inv = this.getUpgradeable().getInventoryByName("config");
final WrapperSupplierItemHandler upgradeInventory = new WrapperSupplierItemHandler(
this::getCellUpgradeInventory);
int offset = 0;
final int y = 29;
final int x = 8;
for (int w = 0; w < 7; w++) {
for (int z = 0; z < 9; z++) {
this.addSlot(new FakeTypeOnlySlot(inv, offset, x + z * 18, y + w * 18));
offset++;
}
}
for (int zz = 0; zz < 3; zz++) {
for (int z = 0; z < 8; z++) {
final int iSLot = zz * 8 + z;
this.addSlot(new OptionalRestrictedInputSlot(RestrictedInputSlot.PlacableItemType.UPGRADES,
upgradeInventory, this, iSLot, 187 + zz * 18, 8 + 18 * z, iSLot, this.getPlayerInventory()));
}
}
}
@Override
public int availableUpgrades() {
final ItemStack is = this.workBench.getInventoryByName("cell").getInvStack(0);
if (this.prevStack != is) {
this.prevStack = is;
this.lastUpgrades = this.getCellUpgradeInventory().getSlotCount();
}
return this.lastUpgrades;
}
@Override
public void sendContentUpdates() {
final ItemStack is = this.workBench.getInventoryByName("cell").getInvStack(0);
if (Platform.isServer()) {
for (final ScreenHandlerListener listener : this.getListeners()) {
if (this.prevStack != is) {
// if the bars changed an item was probably made, so just send shit!
for (int i = 0; i < this.slots.size(); i++) {
Slot s = this.slots.get(i);
if (s instanceof OptionalRestrictedInputSlot) {
final OptionalRestrictedInputSlot sri = (OptionalRestrictedInputSlot) s;
listener.onSlotUpdate(this, i, sri.getStack());
}
}
if (listener instanceof ServerPlayerEntity) {
((ServerPlayerEntity) listener).skipPacketSlotUpdates = false;
}
}
}
this.setCopyMode(this.getWorkBenchCopyMode());
this.setFuzzyMode(this.getWorkBenchFuzzyMode());
}
this.prevStack = is;
this.standardDetectAndSendChanges();
}
@Override
public boolean isSlotEnabled(final int idx) {
return idx < this.availableUpgrades();
}
public FixedItemInv getCellUpgradeInventory() {
final FixedItemInv upgradeInventory = this.workBench.getCellUpgradeInventory();
return upgradeInventory == null ? EmptyFixedItemInv.INSTANCE : upgradeInventory;
}
@Override
public void onUpdate(final String field, final Object oldValue, final Object newValue) {
if (field.equals("copyMode")) {
this.workBench.getConfigManager().putSetting(Settings.COPY_MODE, this.getCopyMode());
}
super.onUpdate(field, oldValue, newValue);
}
public void clear() {
ItemHandlerUtil.clear(this.getUpgradeable().getInventoryByName("config"));
this.sendContentUpdates();
}
private FuzzyMode getWorkBenchFuzzyMode() {
final ICellWorkbenchItem cwi = this.workBench.getCell();
if (cwi != null) {
return cwi.getFuzzyMode(this.workBench.getInventoryByName("cell").getInvStack(0));
}
return FuzzyMode.IGNORE_ALL;
}
public void partition() {
final FixedItemInv inv = this.getUpgradeable().getInventoryByName("config");
final ItemStack is = this.getUpgradeable().getInventoryByName("cell").getInvStack(0);
final IStorageChannel channel = is.getItem() instanceof IStorageCell
? ((IStorageCell) is.getItem()).getChannel()
: AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);
final IMEInventory cellInv = AEApi.instance().registries().cell().getCellInventory(is, null, channel);
Iterator<IAEStack> i = new NullIterator<>();
if (cellInv != null) {
final IItemList list = cellInv.getAvailableItems(channel.createList());
i = list.iterator();
}
for (int x = 0; x < inv.getSlotCount(); x++) {
if (i.hasNext()) {
// TODO: check if ok
final ItemStack g = i.next().asItemStackRepresentation();
ItemHandlerUtil.setStackInSlot(inv, x, g);
} else {
ItemHandlerUtil.setStackInSlot(inv, x, ItemStack.EMPTY);
}
}
this.sendContentUpdates();
}
public CopyMode getCopyMode() {
return this.copyMode;
}
private void setCopyMode(final CopyMode copyMode) {
this.copyMode = copyMode;
}
}

Some files were not shown because too many files have changed in this diff Show More