Working in part placement

This commit is contained in:
Sebastian Hartte
2020-07-01 21:27:37 +02:00
parent 8e031ca8d6
commit f2e3d81fd7
134 changed files with 1553 additions and 1494 deletions
@@ -109,7 +109,7 @@ public class ChargerBlock extends AEBaseTileBlock<ChargerBlockEntity> {
final double zOff = 0.0;
for (int bolts = 0; bolts < 3; bolts++) {
if (AppEng.proxy.shouldAddParticles(r)) {
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);
}
@@ -71,7 +71,7 @@ public class QuartzGrowthAcceleratorBlock extends AEBaseTileBlock<QuartzGrowthAc
final QuartzGrowthAcceleratorBlockEntity cga = this.getBlockEntity(w, pos);
if (cga != null && cga.isPowered() && AppEng.proxy.shouldAddParticles(r)) {
if (cga != null && cga.isPowered() && AppEng.instance().shouldAddParticles(r)) {
final double d0 = r.nextFloat() - 0.5F;
final double d1 = r.nextFloat() - 0.5F;
@@ -1,388 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.networking;
import java.util.EnumSet;
import java.util.List;
import java.util.Random;
import javax.annotation.Nullable;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.util.DyeColor;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.*;
import net.minecraft.util.hit.HitResult.Type;
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.WorldView;
import net.minecraft.world.World;
import appeng.api.parts.IFacadeContainer;
import appeng.api.parts.IFacadePart;
import appeng.api.parts.PartItemStack;
import appeng.api.parts.SelectedPart;
import appeng.api.util.AEColor;
import appeng.api.util.AEPartLocation;
import appeng.block.AEBaseTileBlock;
import appeng.client.render.cablebus.CableBusBakedModel;
import appeng.client.render.cablebus.CableBusBreakingParticle;
import appeng.client.render.cablebus.CableBusRenderState;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ClickPacket;
import appeng.helpers.AEGlassMaterial;
import appeng.integration.abstraction.IAEFacade;
import appeng.parts.ICableBusContainer;
import appeng.parts.NullCableBusContainer;
import appeng.tile.AEBaseBlockEntity;
import appeng.tile.networking.CableBusBlockEntity;
import appeng.util.Platform;
public class CableBusBlock extends AEBaseTileBlock<CableBusBlockEntity> implements IAEFacade {
private static final ICableBusContainer NULL_CABLE_BUS = new NullCableBusContainer();
public CableBusBlock() {
super(defaultProps(AEGlassMaterial.INSTANCE)
.nonOpaque()
.dropsNothing().variableOpacity());
}
@Override
public boolean isTranslucent(BlockState state, BlockView reader, BlockPos pos) {
return true;
}
@Override
public void randomDisplayTick(final BlockState state, final World worldIn, final BlockPos pos, final Random rand) {
this.cb(worldIn, pos).randomDisplayTick(worldIn, pos, rand);
}
@Override
public void onNeighborChange(BlockState state, WorldView w, BlockPos pos, BlockPos neighbor) {
this.cb(w, pos).onneighborUpdate(w, pos, neighbor);
}
@Override
public int getWeakRedstonePower(final BlockState state, final BlockView w, final BlockPos pos, final Direction side) {
return this.cb(w, pos).isProvidingWeakPower(side.getOpposite()); // TODO:
// IS
// OPPOSITE!?
}
@Override
public boolean canProvidePower(final BlockState state) {
return true;
}
@Override
public void onEntityCollision(BlockState state, World w, BlockPos pos, Entity entityIn) {
this.cb(w, pos).onEntityCollision(entityIn);
}
@Override
public int getStrongPower(final BlockState state, final BlockView w, final BlockPos pos, final Direction side) {
return this.cb(w, pos).isProvidingStrongPower(side.getOpposite()); // TODO:
// IS
// OPPOSITE!?
}
@Override
public int getLightValue(final BlockState state, final BlockView world, final BlockPos pos) {
if (state.getBlock() != this) {
return state.getLuminance();
}
return this.cb(world, pos).getLightValue();
}
@Override
public boolean isLadder(BlockState state, WorldView world, BlockPos pos, LivingEntity entity) {
return this.cb(world, pos).isLadder(entity);
}
@Override
public boolean isReplaceable(BlockState state, ItemPlacementContext useContext) {
// FIXME: Potentially check the fluid one too
return super.isReplaceable(state, useContext) && this.cb(useContext.getWorld(), useContext.getPos()).isEmpty();
}
@Override
public boolean removedByPlayer(BlockState state, World world, BlockPos pos, PlayerEntity player,
boolean willHarvest, IFluidState fluid) {
if (player.abilities.isCreativeMode) {
final AEBaseBlockEntity tile = this.getBlockEntity(world, pos);
if (tile != null) {
tile.disableDrops();
}
// maybe ray trace?
}
return super.removedByPlayer(state, world, pos, player, willHarvest, fluid);
}
@Override
public boolean canConnectRedstone(final BlockState state, final BlockView w, final BlockPos pos,
Direction side) {
if (side == null) {
side = Direction.UP;
}
return this.cb(w, pos).canConnectRedstone(EnumSet.of(side));
}
@Override
public ItemStack getPickBlock(BlockState state, HitResult target, BlockView world, BlockPos pos,
PlayerEntity player) {
final Vec3d v3 = target.getPos().subtract(pos.getX(), pos.getY(), pos.getZ());
final SelectedPart sp = this.cb(world, pos).selectPart(v3);
if (sp.part != null) {
return sp.part.getItemStack(PartItemStack.PICK);
} else if (sp.facade != null) {
return sp.facade.getItemStack();
}
return ItemStack.EMPTY;
}
@Override
@Environment(EnvType.CLIENT)
public boolean addHitEffects(final BlockState state, final World world, final HitResult target,
final ParticleManager effectRenderer) {
// Half the particle rate. Since we're spawning concentrated on a specific spot,
// our particle effect otherwise looks too strong
if (Platform.getRandom().nextBoolean()) {
return true;
}
if (target.getType() != Type.BLOCK) {
return false;
}
BlockPos blockPos = new BlockPos(target.getPos().x, target.getPos().y, target.getPos().z);
ICableBusContainer cb = this.cb(world, blockPos);
// Our built-in model has the actual baked sprites we need
BakedModel model = MinecraftClient.getInstance().getBlockRenderManager()
.getModelForState(this.getDefaultState());
// We cannot add the effect if we don't have the model
if (!(model instanceof CableBusBakedModel)) {
return true;
}
CableBusBakedModel cableBusModel = (CableBusBakedModel) model;
CableBusRenderState renderState = cb.getRenderState();
// Spawn a particle for one of the particle textures
Sprite texture = Platform.pickRandom(cableBusModel.getParticleTextures(renderState));
if (texture != null) {
double x = target.getPos().x;
double y = target.getPos().y;
double z = target.getPos().z;
// FIXME: Check how this looks, probably like shit, maybe provide parts the
// ability to supply particle textures???
effectRenderer
.addEffect(new CableBusBreakingParticle(world, x, y, z, texture).multiplyParticleScaleBy(0.8F));
}
return true;
}
@Environment(EnvType.CLIENT)
@Override
public boolean addDestroyEffects(BlockState state, World world, BlockPos pos, ParticleManager effectRenderer) {
ICableBusContainer cb = this.cb(world, pos);
// Our built-in model has the actual baked sprites we need
BakedModel model = MinecraftClient.getInstance().getBlockRenderManager()
.getModelForState(this.getDefaultState());
// We cannot add the effect if we dont have the model
if (!(model instanceof CableBusBakedModel)) {
return true;
}
CableBusBakedModel cableBusModel = (CableBusBakedModel) model;
CableBusRenderState renderState = cb.getRenderState();
List<Sprite> textures = cableBusModel.getParticleTextures(renderState);
if (!textures.isEmpty()) {
// Shamelessly inspired by ParticleManager.addBlockDestroyEffects
for (int j = 0; j < 4; ++j) {
for (int k = 0; k < 4; ++k) {
for (int l = 0; l < 4; ++l) {
// Randomly select one of the textures if the cable bus has more than just one
// possibility here
final Sprite texture = Platform.pickRandom(textures);
final double x = pos.getX() + (j + 0.5D) / 4.0D;
final double y = pos.getY() + (k + 0.5D) / 4.0D;
final double z = pos.getZ() + (l + 0.5D) / 4.0D;
// FIXME: Check how this looks, probably like shit, maybe provide parts the
// ability to supply particle textures???
Particle effect = new CableBusBreakingParticle(world, x, y, z, x - pos.getX() - 0.5D,
y - pos.getY() - 0.5D, z - pos.getZ() - 0.5D, texture);
effectRenderer.addEffect(effect);
}
}
}
}
return true;
}
@Override
public void neighborUpdate(BlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
if (Platform.isServer()) {
this.cb(world, pos).onneighborUpdate(world, pos, fromPos);
}
}
private ICableBusContainer cb(final BlockView w, final BlockPos pos) {
final BlockEntity te = w.getBlockEntity(pos);
ICableBusContainer out = null;
if (te instanceof CableBusBlockEntity) {
out = ((CableBusBlockEntity) te).getCableBus();
}
return out == null ? NULL_CABLE_BUS : out;
}
@Nullable
private IFacadeContainer fc(final BlockView w, final BlockPos pos) {
final BlockEntity te = w.getBlockEntity(pos);
IFacadeContainer out = null;
if (te instanceof CableBusBlockEntity) {
out = ((CableBusBlockEntity) te).getCableBus().getFacadeContainer();
}
return out;
}
@Override
public void onBlockClicked(BlockState state, World worldIn, BlockPos pos, PlayerEntity player) {
if (worldIn.isClient()) {
final HitResult rtr = MinecraftClient.getInstance().objectMouseOver;
if (rtr instanceof BlockHitResult) {
BlockHitResult brtr = (BlockHitResult) rtr;
if (brtr.getPos().equals(pos)) {
final Vec3d hitVec = rtr.getPos().subtract(new Vec3d(pos));
if (this.cb(worldIn, pos).clicked(player, Hand.MAIN_HAND, hitVec)) {
NetworkHandler.instance().sendToServer(new ClickPacket(pos, brtr.getSide(), (float) hitVec.x,
(float) hitVec.y, (float) hitVec.z, Hand.MAIN_HAND, true));
}
}
}
}
}
public void onBlockClickPacket(World worldIn, BlockPos pos, PlayerEntity playerIn, Hand hand, Vec3d hitVec) {
this.cb(worldIn, pos).clicked(playerIn, hand, hitVec);
}
@Override
public ActionResult onActivated(final World w, final BlockPos pos, final PlayerEntity player, final Hand hand,
final @Nullable ItemStack heldItem, final BlockHitResult hit) {
// Transform from world into block space
Vec3d hitVec = hit.getPos();
Vec3d hitInBlock = new Vec3d(hitVec.x - pos.getX(), hitVec.y - pos.getY(), hitVec.z - pos.getZ());
return this.cb(w, pos).activate(player, hand, hitInBlock) ? ActionResult.SUCCESS : ActionResult.PASS;
}
public boolean recolorBlock(final BlockView world, final BlockPos pos, final Direction side,
final DyeColor color, final PlayerEntity who) {
try {
return this.cb(world, pos).recolourBlock(side, AEColor.values()[color.ordinal()], who);
} catch (final Throwable ignored) {
}
return false;
}
@Override
@Environment(EnvType.CLIENT)
public void appendStacks(ItemGroup group, DefaultedList<ItemStack> itemStacks) {
// do nothing
}
@Override
public BlockState getFacadeState(BlockView world, BlockPos pos, Direction side) {
if (side != null) {
IFacadeContainer container = this.fc(world, pos);
if (container != null) {
IFacadePart facade = container.getFacade(AEPartLocation.fromFacing(side));
if (facade != null) {
return facade.getBlockState();
}
}
}
return world.getBlockState(pos);
}
@Override
public VoxelShape getOutlineShape(BlockState state, BlockView w, BlockPos pos, ShapeContext context) {
CableBusBlockEntity te = getBlockEntity(w, pos);
if (te == null) {
return VoxelShapes.empty();
} else {
return te.getCableBus().getShape();
}
}
@Override
public VoxelShape getCollisionShape(BlockState state, BlockView w, BlockPos pos, ShapeContext context) {
CableBusBlockEntity te = getBlockEntity(w, pos);
if (te == null) {
return VoxelShapes.empty();
} else {
return te.getCableBus().getCollisionShape(context.getEntity());
}
}
}
@@ -1,58 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.networking;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.color.block.BlockColorProvider;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ILightReader;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.api.util.AEColor;
import appeng.parts.CableBusContainer;
import appeng.tile.networking.CableBusBlockEntity;
/**
* Exposes the cable bus color as tint indices 0 (dark variant), 1 (medium
* variant) and 2 (bright variant).
*/
@Environment(EnvType.CLIENT)
public class CableBusColor implements BlockColorProvider {
@Override
public int getColor(BlockState state, @Nullable ILightReader worldIn, @Nullable BlockPos pos, int color) {
AEColor busColor = AEColor.TRANSPARENT;
if (worldIn != null && pos != null) {
BlockEntity tileEntity = worldIn.getBlockEntity(pos);
if (tileEntity instanceof CableBusBlockEntity) {
CableBusContainer container = ((CableBusBlockEntity) tileEntity).getCableBus();
busColor = container.getColor();
}
}
return busColor.getVariantByTintIndex(color);
}
}
@@ -1,43 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.block.networking;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
/**
* Customizes the rendering behavior for cable busses, which are the biggest
* multipart of AE2.
*/
public class CableBusRendering extends BlockRenderingCustomizer {
@Override
@Environment(EnvType.CLIENT)
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
// FIXME This is straight up impossible in Vanilla, and questionable if it's actually needed.
// FIXME rendering.renderType(rt -> true);
rendering.blockColor(new CableBusColor());
rendering.modelCustomizer((loc, model) -> model);
}
}
@@ -64,8 +64,8 @@ public class QuantumLinkChamberBlock extends QuantumBaseBlock {
final QuantumBridgeBlockEntity bridge = this.getBlockEntity(w, pos);
if (bridge != null) {
if (bridge.hasQES()) {
if (AppEng.proxy.shouldAddParticles(rand)) {
AppEng.proxy.spawnEffect(EffectType.Energy, w, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5,
if (AppEng.instance().shouldAddParticles(rand)) {
AppEng.instance().spawnEffect(EffectType.Energy, w, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5,
null);
}
}
@@ -44,7 +44,7 @@ class NullSpatialDimension implements ISpatialDimension {
@Override
public BlockPos getCellDimensionSize(DimensionType cellDim) {
return BlockPos.ZERO;
return BlockPos.ORIGIN;
}
@Override
+1 -18
View File
@@ -113,27 +113,10 @@ public class ClientHelper extends ServerHelper {
}
}
@Override
public HitResult getRTR() {
return MinecraftClient.getInstance().objectMouseOver;
}
@Override
public void postInit() {
}
@Override
public CableRenderMode getRenderMode() {
if (Platform.isServer()) {
return super.getRenderMode();
}
final MinecraftClient mc = MinecraftClient.getInstance();
final PlayerEntity player = mc.player;
return this.renderModeForPlayer(player);
}
private void postPlayerRender(final RenderLivingEvent.Pre p) {
// FIXME final PlayerColor player = TickHandler.INSTANCE.getPlayerColors().get( p.getEntity().getEntityId() );
@@ -149,7 +132,7 @@ public class ClientHelper extends ServerHelper {
}
private void spawnVibrant(final World w, final double x, final double y, final double z) {
if (AppEng.proxy.shouldAddParticles(Platform.getRandom())) {
if (AppEng.instance().shouldAddParticles(Platform.getRandom())) {
final double d0 = (Platform.getRandomFloat() - 0.5F) * 0.26D;
final double d1 = (Platform.getRandomFloat() - 0.5F) * 0.26D;
final double d2 = (Platform.getRandomFloat() - 0.5F) * 0.26D;
@@ -31,6 +31,7 @@ import com.google.common.collect.Lists;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.InputUtil;
import net.minecraft.util.Formatting;
@@ -44,7 +45,6 @@ import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.util.InputMappings;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
@@ -692,7 +692,7 @@ public abstract class AEBaseScreen<T extends AEBaseContainer> extends ContainerS
final Tessellator tessellator = Tessellator.getInstance();
final BufferBuilder vb = tessellator.getBuffer();
vb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
vb.begin(GL11.GL_QUADS, VertexFormats.POSITION_TEX_COLOR);
final float f1 = 0.00390625F;
final float f = 0.00390625F;
@@ -183,7 +183,7 @@ public class InterfaceTerminalScreen extends AEBaseScreen<InterfaceTerminalConta
InputUtil.Key input = InputMappings.getInputByCode(keyCode, scanCode);
if (keyCode != GLFW.GLFW_KEY_ESCAPE) {
if (AppEng.proxy.isActionKey(ActionKey.TOGGLE_FOCUS, input)) {
if (AppEng.instance().isActionKey(ActionKey.TOGGLE_FOCUS, input)) {
this.searchField.setFocused2(!this.searchField.isFocused());
return true;
}
@@ -387,7 +387,7 @@ public class MEMonitorableScreen<T extends MEMonitorableContainer> extends AEBas
InputUtil.Key input = InputMappings.getInputByCode(keyCode, scanCode);
if (keyCode != GLFW.GLFW_KEY_ESCAPE && !this.checkHotbarKeys(input)) {
if (AppEng.proxy.isActionKey(ActionKey.TOGGLE_FOCUS, input)) {
if (AppEng.instance().isActionKey(ActionKey.TOGGLE_FOCUS, input)) {
this.searchField.setFocused2(!this.searchField.isFocused());
return true;
}
@@ -87,7 +87,7 @@ public class QuartzKnifeScreen extends AEBaseScreen<QuartzKnifeContainer> {
InputUtil.Key input = InputMappings.getInputByCode(keyCode, scanCode);
if (keyCode != GLFW.GLFW_KEY_ESCAPE && !this.checkHotbarKeys(input)) {
if (AppEng.proxy.isActionKey(ActionKey.TOGGLE_FOCUS, input)) {
if (AppEng.instance().isActionKey(ActionKey.TOGGLE_FOCUS, input)) {
this.name.setFocused2(!this.name.isFocused());
return true;
}
@@ -23,9 +23,9 @@ import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
/**
* A modified version of the Minecraft text field. You can initialize it over
@@ -138,7 +138,7 @@ public class AETextField extends TextFieldWidget {
RenderSystem.disableTexture();
RenderSystem.enableColorLogicOp();
RenderSystem.logicOp(GlStateManager.LogicOp.OR_REVERSE);
bufferbuilder.begin(7, DefaultVertexFormats.POSITION);
bufferbuilder.begin(7, VertexFormats.POSITION);
bufferbuilder.pos(startX, endY, 0.0D).endVertex();
bufferbuilder.pos(endX, endY, 0.0D).endVertex();
bufferbuilder.pos(endX, startY, 0.0D).endVertex();
@@ -24,7 +24,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.color.block.BlockColorProvider;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ILightReader;
import net.minecraft.world.BlockRenderView;
import appeng.api.implementations.tiles.IColorableTile;
import appeng.api.util.AEColor;
@@ -37,7 +37,7 @@ public class ColorableTileBlockColor implements BlockColorProvider {
public static final ColorableTileBlockColor INSTANCE = new ColorableTileBlockColor();
@Override
public int getColor(BlockState state, @Nullable ILightReader worldIn, @Nullable BlockPos pos, int tintIndex) {
public int getColor(BlockState state, @Nullable BlockRenderView worldIn, @Nullable BlockPos pos, int tintIndex) {
AEColor color = AEColor.TRANSPARENT; // Default to a neutral color
if (worldIn != null && pos != null) {
@@ -22,9 +22,13 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
@@ -42,36 +46,27 @@ import appeng.client.render.cablebus.FacadeBuilder;
*
* @author covers1624
*/
public class FacadeBakedItemModel extends DelegateBakedModel {
public class FacadeBakedItemModel extends ForwardingBakedModel implements FabricBakedModel {
private final ItemStack textureStack;
private final FacadeBuilder facadeBuilder;
private List<BakedQuad> quads = null;
protected FacadeBakedItemModel(BakedModel base, ItemStack textureStack, FacadeBuilder facadeBuilder) {
super(base);
this.wrapped = base;
this.textureStack = textureStack;
this.facadeBuilder = facadeBuilder;
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
return getQuads(state, side, rand, EmptyModelData.INSTANCE);
}
public void emitItemQuads(ItemStack stack, Supplier<Random> randomSupplier, RenderContext context) {
super.emitItemQuads(stack, randomSupplier, context);
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand,
IModelData data) {
if (side != null) {
return Collections.emptyList();
}
if (quads == null) {
quads = new ArrayList<>();
quads.addAll(this.facadeBuilder.buildFacadeItemQuads(this.textureStack, Direction.NORTH));
quads.addAll(this.getBaseModel().getQuads(state, side, rand, data));
quads = Collections.unmodifiableList(quads);
}
return quads;
}
@Override
@@ -20,6 +20,7 @@ package appeng.client.render;
import java.util.Random;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
@@ -30,7 +31,6 @@ import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.math.Quaternion;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.world.ClientWorld;
import net.minecraftforge.client.IRenderHandler;
import net.minecraftforge.client.SkyRenderHandler;
@@ -85,7 +85,7 @@ public class SpatialSkyRender implements SkyRenderHandler {
matrixStack.multiply(rotation);
RenderSystem.disableTexture();
VertexBuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
VertexBuffer.begin(GL11.GL_QUADS, VertexFormats.POSITION);
VertexBuffer.pos(-100.0D, -100.0D, -100.0D).endVertex();
VertexBuffer.pos(-100.0D, -100.0D, 100.0D).endVertex();
VertexBuffer.pos(100.0D, -100.0D, 100.0D).endVertex();
@@ -123,7 +123,7 @@ public class SpatialSkyRender implements SkyRenderHandler {
private void renderTwinkles() {
final Tessellator tessellator = Tessellator.getInstance();
final BufferBuilder vb = tessellator.getBuffer();
vb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
vb.begin(GL11.GL_QUADS, VertexFormats.POSITION);
for (int i = 0; i < 50; ++i) {
double iX = this.random.nextFloat() * 2.0F - 1.0F;
@@ -23,7 +23,7 @@ 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.ILightReader;
import net.minecraft.world.BlockRenderView;
import appeng.api.util.AEColor;
@@ -39,7 +39,7 @@ public class StaticBlockColor implements BlockColorProvider {
}
@Override
public int getColor(BlockState state, @Nullable ILightReader worldIn, @Nullable BlockPos pos, int tintIndex) {
public int getColor(BlockState state, @Nullable BlockRenderView worldIn, @Nullable BlockPos pos, int tintIndex) {
return this.color.getVariantByTintIndex(tintIndex);
}
@@ -1,42 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render;
import net.minecraft.client.color.item.ItemColorProvider;
import net.minecraft.item.ItemStack;
import appeng.api.util.AEColor;
/**
* Returns the shades of a single AE color for tint indices 0, 1, and 2.
*/
public class StaticItemColor implements ItemColorProvider {
private final AEColor color;
public StaticItemColor(AEColor color) {
this.color = color;
}
@Override
public int getColor(ItemStack stack, int tintIndex) {
return this.color.getVariantByTintIndex(tintIndex);
}
}
@@ -1,727 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import java.util.function.Function;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Identifier;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import appeng.core.AppEng;
/**
* A helper class that builds quads for cable connections.
*/
class CableBuilder {
// Textures for the cable core types, one per type/color pair
private final EnumMap<CableCoreType, EnumMap<AEColor, Sprite>> coreTextures;
// Textures for rendering the actual connection cubes, one per type/color pair
private final EnumMap<AECableType, EnumMap<AEColor, Sprite>> connectionTextures;
private final SmartCableTextures smartCableTextures;
CableBuilder(Function<SpriteIdentifier, Sprite> bakedTextureGetter) {
this.coreTextures = new EnumMap<>(CableCoreType.class);
for (CableCoreType type : CableCoreType.values()) {
EnumMap<AEColor, Sprite> colorTextures = new EnumMap<>(AEColor.class);
for (AEColor color : AEColor.values()) {
colorTextures.put(color, bakedTextureGetter.apply(type.getTexture(color)));
}
this.coreTextures.put(type, colorTextures);
}
this.connectionTextures = new EnumMap<>(AECableType.class);
for (AECableType type : AECableType.VALIDCABLES) {
EnumMap<AEColor, Sprite> colorTextures = new EnumMap<>(AEColor.class);
for (AEColor color : AEColor.values()) {
colorTextures.put(color, bakedTextureGetter.apply(getConnectionTexture(type, color)));
}
this.connectionTextures.put(type, colorTextures);
}
this.smartCableTextures = new SmartCableTextures(bakedTextureGetter);
}
static SpriteIdentifier getConnectionTexture(AECableType cableType, AEColor color) {
String textureFolder;
switch (cableType) {
case GLASS:
textureFolder = "parts/cable/glass/";
break;
case COVERED:
textureFolder = "parts/cable/covered/";
break;
case SMART:
textureFolder = "parts/cable/smart/";
break;
case DENSE_COVERED:
textureFolder = "parts/cable/dense_covered/";
break;
case DENSE_SMART:
textureFolder = "parts/cable/dense_smart/";
break;
default:
throw new IllegalStateException("Cable type " + cableType + " does not support connections.");
}
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, textureFolder + color.name().toLowerCase()));
}
/**
* Adds the core of a cable to the given list of quads.
*
* The type of cable core is automatically deduced from the given cable type.
*/
public void addCableCore(AECableType cableType, AEColor color, List<BakedQuad> quadsOut) {
switch (cableType) {
case GLASS:
this.addCableCore(CableCoreType.GLASS, color, quadsOut);
break;
case COVERED:
case SMART:
this.addCableCore(CableCoreType.COVERED, color, quadsOut);
break;
case DENSE_COVERED:
case DENSE_SMART:
this.addCableCore(CableCoreType.DENSE, color, quadsOut);
break;
default:
}
}
public void addCableCore(CableCoreType coreType, AEColor color, List<BakedQuad> quadsOut) {
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
Sprite texture = this.coreTextures.get(coreType).get(color);
cubeBuilder.setTexture(texture);
switch (coreType) {
case GLASS:
cubeBuilder.addCube(6, 6, 6, 10, 10, 10);
break;
case COVERED:
cubeBuilder.addCube(5, 5, 5, 11, 11, 11);
break;
case DENSE:
cubeBuilder.addCube(3, 3, 3, 13, 13, 13);
break;
}
}
public void addGlassConnection(Direction facing, AEColor cableColor, AECableType connectionType,
boolean cableBusAdjacent, List<BakedQuad> quadsOut) {
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
// We render all faces except the one on the connection side
cubeBuilder.setDrawFaces(EnumSet.complementOf(EnumSet.of(facing)));
// For to-machine connections, use a thicker end-cap for the connection
if (connectionType != AECableType.GLASS && !cableBusAdjacent) {
Sprite texture = this.connectionTextures.get(AECableType.COVERED).get(cableColor);
cubeBuilder.setTexture(texture);
this.addBigCoveredCableSizedCube(facing, cubeBuilder);
}
Sprite texture = this.connectionTextures.get(AECableType.GLASS).get(cableColor);
cubeBuilder.setTexture(texture);
switch (facing) {
case DOWN:
cubeBuilder.addCube(6, 0, 6, 10, 6, 10);
break;
case EAST:
cubeBuilder.addCube(10, 6, 6, 16, 10, 10);
break;
case NORTH:
cubeBuilder.addCube(6, 6, 0, 10, 10, 6);
break;
case SOUTH:
cubeBuilder.addCube(6, 6, 10, 10, 10, 16);
break;
case UP:
cubeBuilder.addCube(6, 10, 6, 10, 16, 10);
break;
case WEST:
cubeBuilder.addCube(0, 6, 6, 6, 10, 10);
break;
}
}
public void addStraightGlassConnection(Direction facing, AEColor cableColor, List<BakedQuad> quadsOut) {
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
// We render all faces except the connection caps. We can do this because the
// glass cable is the smallest one
// and its ends will always be covered by something
cubeBuilder.setDrawFaces(EnumSet.complementOf(EnumSet.of(facing, facing.getOpposite())));
Sprite texture = this.connectionTextures.get(AECableType.GLASS).get(cableColor);
cubeBuilder.setTexture(texture);
switch (facing) {
case DOWN:
case UP:
cubeBuilder.addCube(6, 0, 6, 10, 16, 10);
break;
case NORTH:
case SOUTH:
cubeBuilder.addCube(6, 6, 0, 10, 10, 16);
break;
case EAST:
case WEST:
cubeBuilder.addCube(0, 6, 6, 16, 10, 10);
break;
}
}
public void addConstrainedGlassConnection(Direction facing, AEColor cableColor, int distanceFromEdge,
List<BakedQuad> quadsOut) {
// Glass connections reach only 6 voxels from the edge
if (distanceFromEdge >= 6) {
return;
}
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
Sprite texture = this.connectionTextures.get(AECableType.GLASS).get(cableColor);
cubeBuilder.setTexture(texture);
switch (facing) {
case DOWN:
cubeBuilder.addCube(6, distanceFromEdge, 6, 10, 6, 10);
break;
case EAST:
cubeBuilder.addCube(10, 6, 6, 16 - distanceFromEdge, 10, 10);
break;
case NORTH:
cubeBuilder.addCube(6, 6, distanceFromEdge, 10, 10, 6);
break;
case SOUTH:
cubeBuilder.addCube(6, 6, 10, 10, 10, 16 - distanceFromEdge);
break;
case UP:
cubeBuilder.addCube(6, 10, 6, 10, 16 - distanceFromEdge, 10);
break;
case WEST:
cubeBuilder.addCube(distanceFromEdge, 6, 6, 6, 10, 10);
break;
}
}
public void addCoveredConnection(Direction facing, AEColor cableColor, AECableType connectionType,
boolean cableBusAdjacent, List<BakedQuad> quadsOut) {
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
// We render all faces except the one on the connection side
cubeBuilder.setDrawFaces(EnumSet.complementOf(EnumSet.of(facing)));
Sprite texture = this.connectionTextures.get(AECableType.COVERED).get(cableColor);
cubeBuilder.setTexture(texture);
// Draw a covered connection, if anything but glass is requested
if (connectionType != AECableType.GLASS && !cableBusAdjacent) {
this.addBigCoveredCableSizedCube(facing, cubeBuilder);
}
addCoveredCableSizedCube(facing, cubeBuilder);
}
public void addStraightCoveredConnection(Direction facing, AEColor cableColor, List<BakedQuad> quadsOut) {
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
Sprite texture = this.connectionTextures.get(AECableType.COVERED).get(cableColor);
cubeBuilder.setTexture(texture);
setStraightCableUVs(cubeBuilder, facing, 5, 11);
addStraightCoveredCableSizedCube(facing, cubeBuilder);
}
private static void setStraightCableUVs(CubeBuilder cubeBuilder, Direction facing, int x, int y) {
switch (facing) {
case DOWN:
case UP:
cubeBuilder.setCustomUv(Direction.NORTH, x, 0, y, x);
cubeBuilder.setCustomUv(Direction.EAST, x, 0, y, x);
cubeBuilder.setCustomUv(Direction.SOUTH, x, 0, y, x);
cubeBuilder.setCustomUv(Direction.WEST, x, 0, y, x);
break;
case EAST:
case WEST:
cubeBuilder.setCustomUv(Direction.UP, 0, x, x, y);
cubeBuilder.setCustomUv(Direction.DOWN, 0, x, x, y);
cubeBuilder.setCustomUv(Direction.NORTH, 0, x, x, y);
cubeBuilder.setCustomUv(Direction.SOUTH, 0, x, x, y);
break;
case NORTH:
case SOUTH:
cubeBuilder.setCustomUv(Direction.UP, x, 0, y, x);
cubeBuilder.setCustomUv(Direction.DOWN, x, 0, y, x);
cubeBuilder.setCustomUv(Direction.EAST, 0, x, x, y);
cubeBuilder.setCustomUv(Direction.WEST, 0, x, x, y);
break;
}
}
public void addConstrainedCoveredConnection(Direction facing, AEColor cableColor, int distanceFromEdge,
List<BakedQuad> quadsOut) {
// The core of a covered cable reaches up to 5 voxels from the block edge, so
// drawing a connection can only occur from there onwards
if (distanceFromEdge >= 5) {
return;
}
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
Sprite texture = this.connectionTextures.get(AECableType.COVERED).get(cableColor);
cubeBuilder.setTexture(texture);
addCoveredCableSizedCube(facing, distanceFromEdge, cubeBuilder);
}
public void addSmartConnection(Direction facing, AEColor cableColor, AECableType connectionType,
boolean cableBusAdjacent, int channels, List<BakedQuad> quadsOut) {
if (connectionType == AECableType.COVERED || connectionType == AECableType.GLASS) {
this.addCoveredConnection(facing, cableColor, connectionType, cableBusAdjacent, quadsOut);
return;
}
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
// We render all faces except the one on the connection side
cubeBuilder.setDrawFaces(EnumSet.complementOf(EnumSet.of(facing)));
Sprite texture = this.connectionTextures.get(AECableType.SMART).get(cableColor);
cubeBuilder.setTexture(texture);
Sprite oddChannel = this.smartCableTextures.getOddTextureForChannels(channels);
Sprite evenChannel = this.smartCableTextures.getEvenTextureForChannels(channels);
// For to-machine connections, use a thicker end-cap for the connection
if (connectionType != AECableType.GLASS && !cableBusAdjacent) {
this.addBigCoveredCableSizedCube(facing, cubeBuilder);
// Render the channel indicators brightly lit at night
cubeBuilder.setRenderFullBright(true);
cubeBuilder.setTexture(oddChannel);
cubeBuilder.setColorRGB(cableColor.blackVariant);
this.addBigCoveredCableSizedCube(facing, cubeBuilder);
cubeBuilder.setTexture(evenChannel);
cubeBuilder.setColorRGB(cableColor.whiteVariant);
this.addBigCoveredCableSizedCube(facing, cubeBuilder);
// Reset back to normal rendering for the rest
cubeBuilder.setRenderFullBright(false);
cubeBuilder.setTexture(texture);
}
addCoveredCableSizedCube(facing, cubeBuilder);
// Render the channel indicators brightly lit at night
cubeBuilder.setRenderFullBright(true);
cubeBuilder.setTexture(oddChannel);
cubeBuilder.setColorRGB(cableColor.blackVariant);
addCoveredCableSizedCube(facing, cubeBuilder);
cubeBuilder.setTexture(evenChannel);
cubeBuilder.setColorRGB(cableColor.whiteVariant);
addCoveredCableSizedCube(facing, cubeBuilder);
}
public void addStraightSmartConnection(Direction facing, AEColor cableColor, int channels,
List<BakedQuad> quadsOut) {
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
Sprite texture = this.connectionTextures.get(AECableType.SMART).get(cableColor);
cubeBuilder.setTexture(texture);
setStraightCableUVs(cubeBuilder, facing, 5, 11);
addStraightCoveredCableSizedCube(facing, cubeBuilder);
Sprite oddChannel = this.smartCableTextures.getOddTextureForChannels(channels);
Sprite evenChannel = this.smartCableTextures.getEvenTextureForChannels(channels);
// Render the channel indicators brightly lit at night
cubeBuilder.setRenderFullBright(true);
cubeBuilder.setTexture(oddChannel);
cubeBuilder.setColorRGB(cableColor.blackVariant);
addStraightCoveredCableSizedCube(facing, cubeBuilder);
cubeBuilder.setTexture(evenChannel);
cubeBuilder.setColorRGB(cableColor.whiteVariant);
addStraightCoveredCableSizedCube(facing, cubeBuilder);
}
public void addConstrainedSmartConnection(Direction facing, AEColor cableColor, int distanceFromEdge, int channels,
List<BakedQuad> quadsOut) {
// Same as with covered cables, the smart cable's core extends up to 5 voxels
// away from the edge.
// Drawing a connection to any point before that point is fruitless
if (distanceFromEdge >= 5) {
return;
}
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
Sprite texture = this.connectionTextures.get(AECableType.SMART).get(cableColor);
cubeBuilder.setTexture(texture);
addCoveredCableSizedCube(facing, distanceFromEdge, cubeBuilder);
Sprite oddChannel = this.smartCableTextures.getOddTextureForChannels(channels);
Sprite evenChannel = this.smartCableTextures.getEvenTextureForChannels(channels);
// Render the channel indicators brightly lit at night
cubeBuilder.setRenderFullBright(true);
cubeBuilder.setTexture(oddChannel);
cubeBuilder.setColorRGB(cableColor.blackVariant);
addCoveredCableSizedCube(facing, distanceFromEdge, cubeBuilder);
cubeBuilder.setTexture(evenChannel);
cubeBuilder.setColorRGB(cableColor.whiteVariant);
addCoveredCableSizedCube(facing, distanceFromEdge, cubeBuilder);
}
public void addDenseCoveredConnection(Direction facing, AEColor cableColor, AECableType connectionType,
boolean cableBusAdjacent, List<BakedQuad> quadsOut) {
// Dense cables only render their connections as dense if the adjacent blocks
// actually wants that
if (connectionType == AECableType.COVERED || connectionType == AECableType.SMART
|| connectionType == AECableType.GLASS) {
this.addCoveredConnection(facing, cableColor, connectionType, cableBusAdjacent, quadsOut);
return;
}
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
// We render all faces except the one on the connection side
cubeBuilder.setDrawFaces(EnumSet.complementOf(EnumSet.of(facing)));
Sprite texture = this.connectionTextures.get(AECableType.DENSE_COVERED).get(cableColor);
cubeBuilder.setTexture(texture);
addDenseCableSizedCube(facing, cubeBuilder);
// Reset back to normal rendering for the rest
cubeBuilder.setRenderFullBright(false);
cubeBuilder.setTexture(texture);
}
public void addDenseSmartConnection(Direction facing, AEColor cableColor, AECableType connectionType,
boolean cableBusAdjacent, int channels, List<BakedQuad> quadsOut) {
// Dense cables only render their connections as dense if the adjacent blocks
// actually wants that
if (connectionType == AECableType.SMART) {
this.addSmartConnection(facing, cableColor, connectionType, cableBusAdjacent, channels, quadsOut);
return;
} else if (connectionType == AECableType.COVERED || connectionType == AECableType.GLASS) {
this.addCoveredConnection(facing, cableColor, connectionType, cableBusAdjacent, quadsOut);
return;
} else if (connectionType == AECableType.DENSE_COVERED) {
this.addDenseCoveredConnection(facing, cableColor, connectionType, cableBusAdjacent, quadsOut);
return;
}
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
// We render all faces except the one on the connection side
cubeBuilder.setDrawFaces(EnumSet.complementOf(EnumSet.of(facing)));
Sprite texture = this.connectionTextures.get(AECableType.DENSE_SMART).get(cableColor);
cubeBuilder.setTexture(texture);
addDenseCableSizedCube(facing, cubeBuilder);
// Dense cables show used channels in groups of 4, rounded up
channels = (channels + 3) / 4;
Sprite oddChannel = this.smartCableTextures.getOddTextureForChannels(channels);
Sprite evenChannel = this.smartCableTextures.getEvenTextureForChannels(channels);
// Render the channel indicators brightly lit at night
cubeBuilder.setRenderFullBright(true);
cubeBuilder.setTexture(oddChannel);
cubeBuilder.setColorRGB(cableColor.blackVariant);
addDenseCableSizedCube(facing, cubeBuilder);
cubeBuilder.setTexture(evenChannel);
cubeBuilder.setColorRGB(cableColor.whiteVariant);
addDenseCableSizedCube(facing, cubeBuilder);
// Reset back to normal rendering for the rest
cubeBuilder.setRenderFullBright(false);
cubeBuilder.setTexture(texture);
}
public void addStraightDenseCoveredConnection(Direction facing, AEColor cableColor, List<BakedQuad> quadsOut) {
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
Sprite texture = this.connectionTextures.get(AECableType.DENSE_COVERED).get(cableColor);
cubeBuilder.setTexture(texture);
setStraightCableUVs(cubeBuilder, facing, 5, 11);
addStraightDenseCableSizedCube(facing, cubeBuilder);
}
public void addStraightDenseSmartConnection(Direction facing, AEColor cableColor, int channels,
List<BakedQuad> quadsOut) {
CubeBuilder cubeBuilder = new CubeBuilder(quadsOut);
Sprite texture = this.connectionTextures.get(AECableType.DENSE_SMART).get(cableColor);
cubeBuilder.setTexture(texture);
setStraightCableUVs(cubeBuilder, facing, 5, 11);
addStraightDenseCableSizedCube(facing, cubeBuilder);
// Dense cables show used channels in groups of 4, rounded up
channels = (channels + 3) / 4;
Sprite oddChannel = this.smartCableTextures.getOddTextureForChannels(channels);
Sprite evenChannel = this.smartCableTextures.getEvenTextureForChannels(channels);
// Render the channel indicators brightly lit at night
cubeBuilder.setRenderFullBright(true);
cubeBuilder.setTexture(oddChannel);
cubeBuilder.setColorRGB(cableColor.blackVariant);
addStraightDenseCableSizedCube(facing, cubeBuilder);
cubeBuilder.setTexture(evenChannel);
cubeBuilder.setColorRGB(cableColor.whiteVariant);
addStraightDenseCableSizedCube(facing, cubeBuilder);
}
private static void addDenseCableSizedCube(Direction facing, CubeBuilder cubeBuilder) {
switch (facing) {
case DOWN:
cubeBuilder.addCube(4, 0, 4, 12, 5, 12);
break;
case EAST:
cubeBuilder.addCube(11, 4, 4, 16, 12, 12);
break;
case NORTH:
cubeBuilder.addCube(4, 4, 0, 12, 12, 5);
break;
case SOUTH:
cubeBuilder.addCube(4, 4, 11, 12, 12, 16);
break;
case UP:
cubeBuilder.addCube(4, 11, 4, 12, 16, 12);
break;
case WEST:
cubeBuilder.addCube(0, 4, 4, 5, 12, 12);
break;
}
}
// Adds a cube to the given cube builder that has the size of a dense cable
// connection and spans the entire block
// for the given direction
private static void addStraightDenseCableSizedCube(Direction facing, CubeBuilder cubeBuilder) {
switch (facing) {
case DOWN:
case UP:
cubeBuilder.setUvRotation(Direction.EAST, 3);
cubeBuilder.addCube(3, 0, 3, 13, 16, 13);
cubeBuilder.setUvRotation(Direction.EAST, 0);
break;
case EAST:
case WEST:
cubeBuilder.setUvRotation(Direction.SOUTH, 3);
cubeBuilder.setUvRotation(Direction.NORTH, 3);
cubeBuilder.addCube(0, 3, 3, 16, 13, 13);
cubeBuilder.setUvRotation(Direction.SOUTH, 0);
cubeBuilder.setUvRotation(Direction.NORTH, 0);
break;
case NORTH:
case SOUTH:
cubeBuilder.setUvRotation(Direction.EAST, 3);
cubeBuilder.setUvRotation(Direction.WEST, 3);
cubeBuilder.addCube(3, 3, 0, 13, 13, 16);
cubeBuilder.setUvRotation(Direction.EAST, 0);
cubeBuilder.setUvRotation(Direction.WEST, 0);
break;
}
}
// Adds a cube to the given cube builder that has the size of a covered cable
// connection from the core of the cable
// to the given face
private static void addCoveredCableSizedCube(Direction facing, CubeBuilder cubeBuilder) {
switch (facing) {
case DOWN:
cubeBuilder.addCube(6, 0, 6, 10, 5, 10);
break;
case EAST:
cubeBuilder.addCube(11, 6, 6, 16, 10, 10);
break;
case NORTH:
cubeBuilder.addCube(6, 6, 0, 10, 10, 5);
break;
case SOUTH:
cubeBuilder.addCube(6, 6, 11, 10, 10, 16);
break;
case UP:
cubeBuilder.addCube(6, 11, 6, 10, 16, 10);
break;
case WEST:
cubeBuilder.addCube(0, 6, 6, 5, 10, 10);
break;
}
}
// Adds a cube to the given cube builder that has the size of a covered cable
// connection and spans the entire block
// for the given direction
private static void addStraightCoveredCableSizedCube(Direction facing, CubeBuilder cubeBuilder) {
switch (facing) {
case DOWN:
case UP:
cubeBuilder.setUvRotation(Direction.EAST, 3);
cubeBuilder.addCube(5, 0, 5, 11, 16, 11);
cubeBuilder.setUvRotation(Direction.EAST, 0);
break;
case EAST:
case WEST:
cubeBuilder.setUvRotation(Direction.SOUTH, 3);
cubeBuilder.setUvRotation(Direction.NORTH, 3);
cubeBuilder.addCube(0, 5, 5, 16, 11, 11);
cubeBuilder.setUvRotation(Direction.SOUTH, 0);
cubeBuilder.setUvRotation(Direction.NORTH, 0);
break;
case NORTH:
case SOUTH:
cubeBuilder.setUvRotation(Direction.EAST, 3);
cubeBuilder.setUvRotation(Direction.WEST, 3);
cubeBuilder.addCube(5, 5, 0, 11, 11, 16);
cubeBuilder.setUvRotation(Direction.EAST, 0);
cubeBuilder.setUvRotation(Direction.WEST, 0);
break;
}
}
private static void addCoveredCableSizedCube(Direction facing, int distanceFromEdge, CubeBuilder cubeBuilder) {
switch (facing) {
case DOWN:
cubeBuilder.addCube(6, distanceFromEdge, 6, 10, 5, 10);
break;
case EAST:
cubeBuilder.addCube(11, 6, 6, 16 - distanceFromEdge, 10, 10);
break;
case NORTH:
cubeBuilder.addCube(6, 6, distanceFromEdge, 10, 10, 5);
break;
case SOUTH:
cubeBuilder.addCube(6, 6, 11, 10, 10, 16 - distanceFromEdge);
break;
case UP:
cubeBuilder.addCube(6, 11, 6, 10, 16 - distanceFromEdge, 10);
break;
case WEST:
cubeBuilder.addCube(distanceFromEdge, 6, 6, 5, 10, 10);
break;
}
}
/**
* This renders a slightly bigger covered cable connection to the specified
* side. This is used to connect cable cores with adjacent machines that do not
* want to be connected to using a glass cable connection. This applies to most
* machines (interfaces, etc.)
*/
private void addBigCoveredCableSizedCube(Direction facing, CubeBuilder cubeBuilder) {
switch (facing) {
case DOWN:
cubeBuilder.addCube(5, 0, 5, 11, 4, 11);
break;
case EAST:
cubeBuilder.addCube(12, 5, 5, 16, 11, 11);
break;
case NORTH:
cubeBuilder.addCube(5, 5, 0, 11, 11, 4);
break;
case SOUTH:
cubeBuilder.addCube(5, 5, 12, 11, 11, 16);
break;
case UP:
cubeBuilder.addCube(5, 12, 5, 11, 16, 11);
break;
case WEST:
cubeBuilder.addCube(0, 5, 5, 4, 11, 11);
break;
}
}
// Get all textures needed for building the actual cable quads
public static List<SpriteIdentifier> getTextures() {
List<SpriteIdentifier> locations = new ArrayList<>();
for (CableCoreType coreType : CableCoreType.values()) {
for (AEColor color : AEColor.values()) {
locations.add(coreType.getTexture(color));
}
}
for (AECableType cableType : AECableType.VALIDCABLES) {
for (AEColor color : AEColor.values()) {
locations.add(getConnectionTexture(cableType, color));
}
}
Collections.addAll(locations, SmartCableTextures.SMART_CHANNELS_TEXTURES);
return locations;
}
public Sprite getCoreTexture(CableCoreType coreType, AEColor color) {
return this.coreTextures.get(coreType).get(color);
}
}
@@ -1,348 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.RenderLayer;
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.renderer.texture.MissingTextureSprite;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.client.model.data.EmptyModelData;
import appeng.api.parts.IPartModel;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
public class CableBusBakedModel implements BakedModel {
private static final Map<CableBusRenderState, List<BakedQuad>> CABLE_MODEL_CACHE = new HashMap<>();
private final CableBuilder cableBuilder;
private final FacadeBuilder facadeBuilder;
private final Map<Identifier, BakedModel> partModels;
private final Sprite particleTexture;
CableBusBakedModel(CableBuilder cableBuilder, FacadeBuilder facadeBuilder,
Map<Identifier, BakedModel> partModels, Sprite particleTexture) {
this.cableBuilder = cableBuilder;
this.facadeBuilder = facadeBuilder;
this.partModels = partModels;
this.particleTexture = particleTexture;
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
return getQuads(state, side, rand, EmptyModelData.INSTANCE);
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand,
IModelData data) {
CableBusRenderState renderState = data.getData(CableBusRenderState.PROPERTY);
if (renderState == null || side != null) {
return Collections.emptyList();
}
RenderLayer layer = MinecraftForgeClient.getRenderLayer();
List<BakedQuad> quads = new ArrayList<>();
// The core parts of the cable will only be rendered in the CUTOUT layer.
// Facades will add them selves to what ever the block would be rendered with,
// except when transparent facades are enabled, they are forced to TRANSPARENT.
if (layer == RenderLayer.getCutout()) {
// First, handle the cable at the center of the cable bus
final List<BakedQuad> cableModel = CABLE_MODEL_CACHE.computeIfAbsent(renderState, k -> {
final List<BakedQuad> model = new ArrayList<>();
this.addCableQuads(renderState, model);
return model;
});
quads.addAll(cableModel);
// Then handle attachments
for (Direction facing : Direction.values()) {
final IPartModel partModel = renderState.getAttachments().get(facing);
if (partModel == null) {
continue;
}
IModelData partModelData = renderState.getPartModelData().get(facing);
if (partModelData == null) {
partModelData = EmptyModelData.INSTANCE;
}
for (Identifier model : partModel.getModels()) {
BakedModel bakedModel = this.partModels.get(model);
if (bakedModel == null) {
throw new IllegalStateException("Trying to use an unregistered part model: " + model);
}
List<BakedQuad> partQuads = bakedModel.getQuads(state, null, rand, partModelData);
// Rotate quads accordingly
QuadRotator rotator = new QuadRotator();
partQuads = rotator.rotateQuads(partQuads, facing, Direction.UP);
quads.addAll(partQuads);
}
}
}
this.facadeBuilder.buildFacadeQuads(layer, renderState, rand, quads, this.partModels::get);
return quads;
}
// Determines whether a cable is connected to exactly two sides that are
// opposite each other
private static boolean isStraightLine(AECableType cableType, EnumMap<Direction, AECableType> sides) {
final Iterator<Entry<Direction, AECableType>> it = sides.entrySet().iterator();
if (!it.hasNext()) {
return false; // No connections
}
final Entry<Direction, AECableType> nextConnection = it.next();
final Direction firstSide = nextConnection.getKey();
final AECableType firstType = nextConnection.getValue();
if (!it.hasNext()) {
return false; // Only a single connection
}
if (firstSide.getOpposite() != it.next().getKey()) {
return false; // Connected to two sides that are not opposite each other
}
if (it.hasNext()) {
return false; // Must not have any other connection points
}
final AECableType secondType = sides.get(firstSide.getOpposite());
return firstType == secondType && cableType == firstType && cableType == secondType;
}
private void addCableQuads(CableBusRenderState renderState, List<BakedQuad> quadsOut) {
AECableType cableType = renderState.getCableType();
if (cableType == AECableType.NONE) {
return;
}
AEColor cableColor = renderState.getCableColor();
EnumMap<Direction, AECableType> connectionTypes = renderState.getConnectionTypes();
// If the connection is straight, no busses are attached, and no covered core
// has been forced (in case of glass
// cables), then render the cable as a simplified straight line.
boolean noAttachments = !renderState.getAttachments().values().stream()
.anyMatch(IPartModel::requireCableConnection);
if (noAttachments && isStraightLine(cableType, connectionTypes)) {
Direction facing = connectionTypes.keySet().iterator().next();
switch (cableType) {
case GLASS:
this.cableBuilder.addStraightGlassConnection(facing, cableColor, quadsOut);
break;
case COVERED:
this.cableBuilder.addStraightCoveredConnection(facing, cableColor, quadsOut);
break;
case SMART:
this.cableBuilder.addStraightSmartConnection(facing, cableColor,
renderState.getChannelsOnSide().get(facing), quadsOut);
break;
case DENSE_COVERED:
this.cableBuilder.addStraightDenseCoveredConnection(facing, cableColor, quadsOut);
break;
case DENSE_SMART:
this.cableBuilder.addStraightDenseSmartConnection(facing, cableColor,
renderState.getChannelsOnSide().get(facing), quadsOut);
break;
default:
break;
}
return; // Don't render the other form of connection
}
this.cableBuilder.addCableCore(renderState.getCoreType(), cableColor, quadsOut);
// Render all internal connections to attachments
EnumMap<Direction, Integer> attachmentConnections = renderState.getAttachmentConnections();
for (Direction facing : attachmentConnections.keySet()) {
int distance = attachmentConnections.get(facing);
int channels = renderState.getChannelsOnSide().get(facing);
switch (cableType) {
case GLASS:
this.cableBuilder.addConstrainedGlassConnection(facing, cableColor, distance, quadsOut);
break;
case COVERED:
this.cableBuilder.addConstrainedCoveredConnection(facing, cableColor, distance, quadsOut);
break;
case SMART:
this.cableBuilder.addConstrainedSmartConnection(facing, cableColor, distance, channels, quadsOut);
break;
case DENSE_COVERED:
case DENSE_SMART:
// Dense cables do not render connections to parts since none can be attached
break;
default:
break;
}
}
// Render all outgoing connections using the appropriate type
for (final Entry<Direction, AECableType> connection : connectionTypes.entrySet()) {
final Direction facing = connection.getKey();
final AECableType connectionType = connection.getValue();
final boolean cableBusAdjacent = renderState.getCableBusAdjacent().contains(facing);
final int channels = renderState.getChannelsOnSide().get(facing);
switch (cableType) {
case GLASS:
this.cableBuilder.addGlassConnection(facing, cableColor, connectionType, cableBusAdjacent,
quadsOut);
break;
case COVERED:
this.cableBuilder.addCoveredConnection(facing, cableColor, connectionType, cableBusAdjacent,
quadsOut);
break;
case SMART:
this.cableBuilder.addSmartConnection(facing, cableColor, connectionType, cableBusAdjacent, channels,
quadsOut);
break;
case DENSE_COVERED:
this.cableBuilder.addDenseCoveredConnection(facing, cableColor, connectionType, cableBusAdjacent,
quadsOut);
break;
case DENSE_SMART:
this.cableBuilder.addDenseSmartConnection(facing, cableColor, connectionType, cableBusAdjacent,
channels, quadsOut);
break;
default:
break;
}
}
}
/**
* Gets a list of texture sprites appropriate for particles (digging, etc.)
* given the render state for a cable bus.
*/
public List<Sprite> getParticleTextures(CableBusRenderState renderState) {
CableCoreType coreType = CableCoreType.fromCableType(renderState.getCableType());
AEColor cableColor = renderState.getCableColor();
List<Sprite> result = new ArrayList<>();
if (coreType != null) {
result.add(this.cableBuilder.getCoreTexture(coreType, cableColor));
}
// If no core is present, just use the first part that comes into play
for (Direction side : renderState.getAttachments().keySet()) {
IPartModel partModel = renderState.getAttachments().get(side);
for (Identifier model : partModel.getModels()) {
BakedModel bakedModel = this.partModels.get(model);
if (bakedModel == null) {
throw new IllegalStateException("Trying to use an unregistered part model: " + model);
}
Sprite particleTexture = bakedModel.getSprite();
// If a part sub-model has no particle texture (indicated by it being the
// missing texture),
// don't add it, so we don't get ugly missing texture break particles.
if (!isMissingTexture(particleTexture)) {
result.add(particleTexture);
}
}
}
return result;
}
private boolean isMissingTexture(Sprite particleTexture) {
return particleTexture instanceof MissingTextureSprite;
}
@Override
public boolean useAmbientOcclusion() {
return true;
}
@Override
public boolean hasDepth() {
return false;
}
@Override
public boolean isSideLit() {
return false;// TODO
}
@Override
public boolean isBuiltin() {
return false;
}
@Override
public Sprite getSprite() {
return this.particleTexture;
}
@Override
public ModelTransformation getTransformation() {
return ModelTransformation.DEFAULT;
}
@Override
public ModelOverrideList getOverrides() {
return ModelOverrideList.EMPTY;
}
public static void clearCache() {
CABLE_MODEL_CACHE.clear();
}
}
@@ -1,57 +0,0 @@
package appeng.client.render.cablebus;
import net.minecraft.client.particle.ParticleTextureSheet;
import net.minecraft.client.particle.SpriteBillboardParticle;
import net.minecraft.client.texture.Sprite;
import net.minecraft.world.World;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
// Derived from Vanilla's BreakingParticle, but allows
// a texture to be specified directly rather than via an itemstack
@Environment(EnvType.CLIENT)
public class CableBusBreakingParticle extends SpriteBillboardParticle {
private final float field_217571_C;
private final float field_217572_F;
public CableBusBreakingParticle(World world, double x, double y, double z, double speedX, double speedY,
double speedZ, Sprite sprite) {
super(world, x, y, z, speedX, speedY, speedZ);
this.setSprite(sprite);
this.gravityStrength = 1.0F;
this.particleScale /= 2.0F;
this.field_217571_C = this.rand.nextFloat() * 3.0F;
this.field_217572_F = this.rand.nextFloat() * 3.0F;
}
public CableBusBreakingParticle(World world, double x, double y, double z, Sprite sprite) {
this(world, x, y, z, 0, 0, 0, sprite);
}
@Override
public ParticleTextureSheet getRenderType() {
return ParticleTextureSheet.TERRAIN_SHEET;
}
@Override
protected float getMinU() {
return this.sprite.getInterpolatedU((this.field_217571_C + 1.0F) / 4.0F * 16.0F);
}
@Override
protected float getMaxU() {
return this.sprite.getInterpolatedU(this.field_217571_C / 4.0F * 16.0F);
}
@Override
protected float getMinV() {
return this.sprite.getInterpolatedV(this.field_217572_F / 4.0F * 16.0F);
}
@Override
protected float getMaxV() {
return this.sprite.getInterpolatedV((this.field_217572_F + 1.0F) / 4.0F * 16.0F);
}
}
@@ -1,94 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.cablebus;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.IModelTransform;
import net.minecraft.client.render.model.IUnbakedModel;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import appeng.api.util.AEColor;
import appeng.core.AELog;
import appeng.core.features.registries.PartModels;
/**
* The built-in model for the cable bus block.
*/
public class CableBusModel implements IModelGeometry<CableBusModel> {
private final PartModels partModels;
public CableBusModel(PartModels partModels) {
this.partModels = partModels;
}
@Override
public BakedModel bake(IModelConfiguration owner, ModelLoader bakery,
Function<SpriteIdentifier, Sprite> spriteGetter, IModelTransform modelTransform,
ModelOverrideList overrides, Identifier modelLocation) {
Map<Identifier, BakedModel> partModels = this.loadPartModels(bakery, spriteGetter, modelTransform);
CableBuilder cableBuilder = new CableBuilder(spriteGetter);
FacadeBuilder facadeBuilder = new FacadeBuilder();
// This should normally not be used, but we *have* to provide a particle texture
// or otherwise damage models will
// crash
Sprite particleTexture = cableBuilder.getCoreTexture(CableCoreType.GLASS, AEColor.TRANSPARENT);
return new CableBusBakedModel(cableBuilder, facadeBuilder, partModels, particleTexture);
}
@Override
public Collection<SpriteIdentifier> getTextures(IModelConfiguration owner,
Function<Identifier, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return Collections.unmodifiableList(CableBuilder.getTextures());
}
private Map<Identifier, BakedModel> loadPartModels(ModelLoader bakery,
Function<SpriteIdentifier, Sprite> spriteGetterIn, IModelTransform transformIn) {
ImmutableMap.Builder<Identifier, BakedModel> result = ImmutableMap.builder();
for (Identifier location : this.partModels.getModels()) {
BakedModel bakedModel = bakery.getBakedModel(location, transformIn, spriteGetterIn);
if (bakedModel == null) {
AELog.warn("Failed to bake part model {}", location);
} else {
result.put(location, bakedModel);
}
}
return result.build();
}
}
@@ -1,29 +0,0 @@
package appeng.client.render.cablebus;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import net.minecraft.resources.IResourceManager;
import net.minecraftforge.client.model.IModelLoader;
import appeng.core.features.registries.PartModels;
public class CableBusModelLoader implements IModelLoader<CableBusModel> {
private final PartModels partModels;
public CableBusModelLoader(PartModels partModels) {
this.partModels = partModels;
}
@Override
public void onResourceManagerReload(IResourceManager resourceManager) {
CableBusBakedModel.clearCache();
}
@Override
public CableBusModel read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
return new CableBusModel(partModels);
}
}
@@ -1,216 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.cablebus;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ILightReader;
import net.minecraftforge.client.model.data.ModelProperty;
import appeng.api.parts.IPartModel;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
/**
* This class captures the entire rendering state needed for a cable bus and
* transports it to the rendering thread for processing.
*/
public class CableBusRenderState {
public static final ModelProperty<CableBusRenderState> PROPERTY = new ModelProperty<>();
// The cable type used for rendering the outgoing connections to other blocks
// and attached parts
private AECableType cableType = AECableType.NONE;
// The type to use for rendering the core of the cable.
private CableCoreType coreType;
private AEColor cableColor = AEColor.TRANSPARENT;
// Describes the outgoing connections of this cable bus to other blocks, and how
// they should be rendered
private EnumMap<Direction, AECableType> connectionTypes = new EnumMap<>(Direction.class);
// Indicate on which sides signified by connectionTypes above, there is another
// cable bus. If a side is connected,
// but it is absent from this
// set, then it means that there is a Grid host, but not a cable bus on that
// side (i.e. an interface, a controller,
// etc.)
private EnumSet<Direction> cableBusAdjacent = EnumSet.noneOf(Direction.class);
// Specifies the number of channels used for the connection to a given side.
// Only contains entries if
// connections contains a corresponding entry.
private EnumMap<Direction, Integer> channelsOnSide = new EnumMap<>(Direction.class);
private EnumMap<Direction, IPartModel> attachments = new EnumMap<>(Direction.class);
// For each attachment, this contains the distance from the edge until which a
// cable connection should be drawn
private EnumMap<Direction, Integer> attachmentConnections = new EnumMap<>(Direction.class);
// Contains the facade to use for each side that has a facade attached
private EnumMap<Direction, FacadeRenderState> facades = new EnumMap<>(Direction.class);
// Used for Facades.
private WeakReference<ILightReader> world;
private BlockPos pos;
// Contains the bounding boxes of all parts on the cable bus to allow facades to
// cut out holes for the parts. This
// list is only populated if there are
// facades on this cable bus
private List<Box> boundingBoxes = new ArrayList<>();
// Additional model data passed to the part models
private EnumMap<Direction, IModelData> partModelData = new EnumMap<>(Direction.class);
public CableCoreType getCoreType() {
return this.coreType;
}
public void setCoreType(CableCoreType coreType) {
this.coreType = coreType;
}
public AECableType getCableType() {
return this.cableType;
}
public void setCableType(AECableType cableType) {
this.cableType = cableType;
}
public AEColor getCableColor() {
return this.cableColor;
}
public void setCableColor(AEColor cableColor) {
this.cableColor = cableColor;
}
public EnumMap<Direction, Integer> getChannelsOnSide() {
return this.channelsOnSide;
}
public EnumMap<Direction, AECableType> getConnectionTypes() {
return this.connectionTypes;
}
public void setConnectionTypes(EnumMap<Direction, AECableType> connectionTypes) {
this.connectionTypes = connectionTypes;
}
public void setChannelsOnSide(EnumMap<Direction, Integer> channelsOnSide) {
this.channelsOnSide = channelsOnSide;
}
public EnumSet<Direction> getCableBusAdjacent() {
return this.cableBusAdjacent;
}
public void setCableBusAdjacent(EnumSet<Direction> cableBusAdjacent) {
this.cableBusAdjacent = cableBusAdjacent;
}
public EnumMap<Direction, IPartModel> getAttachments() {
return this.attachments;
}
public EnumMap<Direction, Integer> getAttachmentConnections() {
return this.attachmentConnections;
}
public EnumMap<Direction, FacadeRenderState> getFacades() {
return this.facades;
}
public ILightReader getWorld() {
return this.world.get();
}
public void setWorld(ILightReader world) {
this.world = new WeakReference<>(world);
}
public BlockPos getPos() {
return this.pos;
}
public void setPos(BlockPos pos) {
this.pos = pos;
}
public List<Box> getBoundingBoxes() {
return this.boundingBoxes;
}
public EnumMap<Direction, IModelData> getPartModelData() {
return this.partModelData;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.attachmentConnections == null) ? 0 : this.attachmentConnections.hashCode());
result = prime * result + ((this.cableBusAdjacent == null) ? 0 : this.cableBusAdjacent.hashCode());
result = prime * result + ((this.cableColor == null) ? 0 : this.cableColor.hashCode());
result = prime * result + ((this.cableType == null) ? 0 : this.cableType.hashCode());
result = prime * result + ((this.channelsOnSide == null) ? 0 : this.channelsOnSide.hashCode());
result = prime * result + ((this.connectionTypes == null) ? 0 : this.connectionTypes.hashCode());
result = prime * result + ((this.coreType == null) ? 0 : this.coreType.hashCode());
result = prime * result + ((this.partModelData == null) ? 0 : this.partModelData.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final CableBusRenderState other = (CableBusRenderState) obj;
return this.cableColor == other.cableColor && this.cableType == other.cableType
&& this.coreType == other.coreType
&& Objects.equals(this.attachmentConnections, other.attachmentConnections)
&& Objects.equals(this.cableBusAdjacent, other.cableBusAdjacent)
&& Objects.equals(this.channelsOnSide, other.channelsOnSide)
&& Objects.equals(this.connectionTypes, other.connectionTypes)
&& Objects.equals(this.partModelData, other.partModelData);
}
}
@@ -1,80 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.cablebus;
import java.util.EnumMap;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.util.Identifier;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import appeng.core.AppEng;
/**
* AE can render the core of a cable (the core that connections are made to, in
* case the cable is not a straight line) in three different ways: - Glass -
* Covered (also used by the Smart Cable) - Dense
*/
public enum CableCoreType {
GLASS("parts/cable/core/glass"), COVERED("parts/cable/core/covered"), DENSE("parts/cable/core/dense_smart");
private static final Map<AECableType, CableCoreType> cableMapping = generateCableMapping();
/**
* Creates the mapping that assigns a cable core type to an AE cable type.
*/
private static Map<AECableType, CableCoreType> generateCableMapping() {
Map<AECableType, CableCoreType> result = new EnumMap<>(AECableType.class);
result.put(AECableType.GLASS, CableCoreType.GLASS);
result.put(AECableType.COVERED, CableCoreType.COVERED);
result.put(AECableType.SMART, CableCoreType.COVERED);
result.put(AECableType.DENSE_COVERED, CableCoreType.DENSE);
result.put(AECableType.DENSE_SMART, CableCoreType.DENSE);
return ImmutableMap.copyOf(result);
}
private final String textureFolder;
CableCoreType(String textureFolder) {
this.textureFolder = textureFolder;
}
/**
* @return The type of core that should be rendered when the given cable isn't
* straight and needs to have a core to attach connections to. Is null
* for the NULL cable.
*/
public static CableCoreType fromCableType(AECableType cableType) {
return cableMapping.get(cableType);
}
public SpriteIdentifier getTexture(AEColor color) {
return new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, this.textureFolder + "/" + color.name().toLowerCase()));
}
}
@@ -1,466 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import com.google.common.base.Preconditions;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
/**
* Builds the quads for a cube.
*/
public class CubeBuilder {
private final List<BakedQuad> output;
private final EnumMap<Direction, Sprite> textures = new EnumMap<>(Direction.class);
private EnumSet<Direction> drawFaces = EnumSet.allOf(Direction.class);
private final EnumMap<Direction, Vector4f> customUv = new EnumMap<>(Direction.class);
private byte[] uvRotations = new byte[Direction.values().length];
private int color = 0xFFFFFFFF;
private boolean useStandardUV = false;
private boolean renderFullBright;
public CubeBuilder(List<BakedQuad> output) {
this.output = output;
}
public CubeBuilder() {
this(new ArrayList<>(6));
}
public void addCube(float x1, float y1, float z1, float x2, float y2, float z2) {
x1 /= 16.0f;
y1 /= 16.0f;
z1 /= 16.0f;
x2 /= 16.0f;
y2 /= 16.0f;
z2 /= 16.0f;
for (Direction face : this.drawFaces) {
this.putFace(face, x1, y1, z1, x2, y2, z2);
}
}
public void addQuad(Direction face, float x1, float y1, float z1, float x2, float y2, float z2) {
this.putFace(face, x1, y1, z1, x2, y2, z2);
}
private static final class UvVector {
float u1;
float u2;
float v1;
float v2;
}
private void putFace(Direction face, float x1, float y1, float z1, float x2, float y2, float z2) {
Sprite texture = this.textures.get(face);
BakedQuadBuilder builder = new BakedQuadBuilder(texture);
builder.setQuadOrientation(face);
builder.setQuadTint(-1);
builder.setApplyDiffuseLighting(true);
UvVector uv = new UvVector();
// The user might have set specific UV coordinates for this face
Vector4f customUv = this.customUv.get(face);
if (customUv != null) {
uv.u1 = texture.getInterpolatedU(customUv.getX());
uv.v1 = texture.getInterpolatedV(customUv.getY());
uv.u2 = texture.getInterpolatedU(customUv.getZ());
uv.v2 = texture.getInterpolatedV(customUv.getW());
} else if (this.useStandardUV) {
uv = this.getStandardUv(face, texture, x1, y1, z1, x2, y2, z2);
} else {
uv = this.getDefaultUv(face, texture, x1, y1, z1, x2, y2, z2);
}
switch (face) {
case DOWN:
this.putVertexTR(builder, face, x2, y1, z1, uv);
this.putVertexBR(builder, face, x2, y1, z2, uv);
this.putVertexBL(builder, face, x1, y1, z2, uv);
this.putVertexTL(builder, face, x1, y1, z1, uv);
break;
case UP:
this.putVertexTL(builder, face, x1, y2, z1, uv);
this.putVertexBL(builder, face, x1, y2, z2, uv);
this.putVertexBR(builder, face, x2, y2, z2, uv);
this.putVertexTR(builder, face, x2, y2, z1, uv);
break;
case NORTH:
this.putVertexBR(builder, face, x2, y2, z1, uv);
this.putVertexTR(builder, face, x2, y1, z1, uv);
this.putVertexTL(builder, face, x1, y1, z1, uv);
this.putVertexBL(builder, face, x1, y2, z1, uv);
break;
case SOUTH:
this.putVertexBL(builder, face, x1, y2, z2, uv);
this.putVertexTL(builder, face, x1, y1, z2, uv);
this.putVertexTR(builder, face, x2, y1, z2, uv);
this.putVertexBR(builder, face, x2, y2, z2, uv);
break;
case WEST:
this.putVertexTL(builder, face, x1, y1, z1, uv);
this.putVertexTR(builder, face, x1, y1, z2, uv);
this.putVertexBR(builder, face, x1, y2, z2, uv);
this.putVertexBL(builder, face, x1, y2, z1, uv);
break;
case EAST:
this.putVertexBR(builder, face, x2, y2, z1, uv);
this.putVertexBL(builder, face, x2, y2, z2, uv);
this.putVertexTL(builder, face, x2, y1, z2, uv);
this.putVertexTR(builder, face, x2, y1, z1, uv);
break;
}
this.output.add(builder.build());
}
private UvVector getDefaultUv(Direction face, Sprite texture, float x1, float y1, float z1, float x2,
float y2, float z2) {
UvVector uv = new UvVector();
switch (face) {
case DOWN:
uv.u1 = texture.getInterpolatedU(x1 * 16);
uv.v1 = texture.getInterpolatedV(z1 * 16);
uv.u2 = texture.getInterpolatedU(x2 * 16);
uv.v2 = texture.getInterpolatedV(z2 * 16);
break;
case UP:
uv.u1 = texture.getInterpolatedU(x1 * 16);
uv.v1 = texture.getInterpolatedV(z1 * 16);
uv.u2 = texture.getInterpolatedU(x2 * 16);
uv.v2 = texture.getInterpolatedV(z2 * 16);
break;
case NORTH:
uv.u1 = texture.getInterpolatedU(x1 * 16);
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
uv.u2 = texture.getInterpolatedU(x2 * 16);
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
break;
case SOUTH:
uv.u1 = texture.getInterpolatedU(x1 * 16);
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
uv.u2 = texture.getInterpolatedU(x2 * 16);
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
break;
case WEST:
uv.u1 = texture.getInterpolatedU(z1 * 16);
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
uv.u2 = texture.getInterpolatedU(z2 * 16);
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
break;
case EAST:
uv.u1 = texture.getInterpolatedU(z2 * 16);
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
uv.u2 = texture.getInterpolatedU(z1 * 16);
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
break;
}
return uv;
}
private UvVector getStandardUv(Direction face, Sprite texture, float x1, float y1, float z1, float x2,
float y2, float z2) {
UvVector uv = new UvVector();
switch (face) {
case DOWN:
uv.u1 = texture.getInterpolatedU(x1 * 16);
uv.v1 = texture.getInterpolatedV(16 - z1 * 16);
uv.u2 = texture.getInterpolatedU(x2 * 16);
uv.v2 = texture.getInterpolatedV(16 - z2 * 16);
break;
case UP:
uv.u1 = texture.getInterpolatedU(x1 * 16);
uv.v1 = texture.getInterpolatedV(z1 * 16);
uv.u2 = texture.getInterpolatedU(x2 * 16);
uv.v2 = texture.getInterpolatedV(z2 * 16);
break;
case NORTH:
uv.u1 = texture.getInterpolatedU(16 - x1 * 16);
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
uv.u2 = texture.getInterpolatedU(16 - x2 * 16);
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
break;
case SOUTH:
uv.u1 = texture.getInterpolatedU(x1 * 16);
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
uv.u2 = texture.getInterpolatedU(x2 * 16);
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
break;
case WEST:
uv.u1 = texture.getInterpolatedU(z1 * 16);
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
uv.u2 = texture.getInterpolatedU(z2 * 16);
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
break;
case EAST:
uv.u1 = texture.getInterpolatedU(16 - z2 * 16);
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
uv.u2 = texture.getInterpolatedU(16 - z1 * 16);
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
break;
}
return uv;
}
// uv.u1, uv.v1
private void putVertexTL(BakedQuadBuilder builder, Direction face, float x, float y, float z, UvVector uv) {
float u, v;
switch (this.uvRotations[face.ordinal()]) {
default:
case 0:
u = uv.u1;
v = uv.v1;
break;
case 1: // 90° clockwise
u = uv.u1;
v = uv.v2;
break;
case 2: // 180° clockwise
u = uv.u2;
v = uv.v2;
break;
case 3: // 270° clockwise
u = uv.u2;
v = uv.v1;
break;
}
this.putVertex(builder, face, x, y, z, u, v);
}
// uv.u2, uv.v1
private void putVertexTR(BakedQuadBuilder builder, Direction face, float x, float y, float z, UvVector uv) {
float u, v;
switch (this.uvRotations[face.ordinal()]) {
default:
case 0:
u = uv.u2;
v = uv.v1;
break;
case 1: // 90° clockwise
u = uv.u1;
v = uv.v1;
break;
case 2: // 180° clockwise
u = uv.u1;
v = uv.v2;
break;
case 3: // 270° clockwise
u = uv.u2;
v = uv.v2;
break;
}
this.putVertex(builder, face, x, y, z, u, v);
}
// uv.u2, uv.v2
private void putVertexBR(BakedQuadBuilder builder, Direction face, float x, float y, float z, UvVector uv) {
float u;
float v;
switch (this.uvRotations[face.ordinal()]) {
default:
case 0:
u = uv.u2;
v = uv.v2;
break;
case 1: // 90° clockwise
u = uv.u2;
v = uv.v1;
break;
case 2: // 180° clockwise
u = uv.u1;
v = uv.v1;
break;
case 3: // 270° clockwise
u = uv.u1;
v = uv.v2;
break;
}
this.putVertex(builder, face, x, y, z, u, v);
}
// uv.u1, uv.v2
private void putVertexBL(BakedQuadBuilder builder, Direction face, float x, float y, float z, UvVector uv) {
float u;
float v;
switch (this.uvRotations[face.ordinal()]) {
default:
case 0:
u = uv.u1;
v = uv.v2;
break;
case 1: // 90° clockwise
u = uv.u2;
v = uv.v2;
break;
case 2: // 180° clockwise
u = uv.u2;
v = uv.v1;
break;
case 3: // 270° clockwise
u = uv.u1;
v = uv.v1;
break;
}
this.putVertex(builder, face, x, y, z, u, v);
}
private void putVertex(BakedQuadBuilder builder, Direction face, float x, float y, float z, float u, float v) {
VertexFormat format = builder.getVertexFormat();
List<VertexFormatElement> elements = format.getElements();
for (int i = 0; i < elements.size(); i++) {
VertexFormatElement e = elements.get(i);
switch (e.getUsage()) {
case POSITION:
builder.put(i, x, y, z);
break;
case NORMAL:
builder.put(i, face.getOffsetX(), face.getOffsetY(), face.getOffsetZ());
break;
case COLOR:
// Color format is RGBA
float r = (this.color >> 16 & 0xFF) / 255f;
float g = (this.color >> 8 & 0xFF) / 255f;
float b = (this.color & 0xFF) / 255f;
float a = (this.color >> 24 & 0xFF) / 255f;
builder.put(i, r, g, b, a);
break;
case UV:
if (e.getIndex() == 0) {
builder.put(i, u, v);
break;
} else if (e.getIndex() == 2 && renderFullBright) {
// Force Brightness to 15, this is for full bright mode
// this vertex element will only be present in that case
final float lightMapU = (float) (15 * 0x20) / 0xFFFF;
final float lightMapV = (float) (15 * 0x20) / 0xFFFF;
builder.put(i, lightMapU, lightMapV);
break;
}
default:
builder.put(i);
break;
}
}
}
public void setTexture(Sprite texture) {
for (Direction face : Direction.values()) {
this.textures.put(face, texture);
}
}
public void setTextures(Sprite up, Sprite down, Sprite north,
Sprite south, Sprite east, Sprite west) {
this.textures.put(Direction.UP, up);
this.textures.put(Direction.DOWN, down);
this.textures.put(Direction.NORTH, north);
this.textures.put(Direction.SOUTH, south);
this.textures.put(Direction.EAST, east);
this.textures.put(Direction.WEST, west);
}
public void setTexture(Direction facing, Sprite sprite) {
this.textures.put(facing, sprite);
}
public void setDrawFaces(EnumSet<Direction> drawFaces) {
this.drawFaces = drawFaces;
}
public void setColor(int color) {
this.color = color;
}
/**
* Sets the vertex color for future vertices to the given RGB value, and forces
* the alpha component to 255.
*/
public void setColorRGB(int color) {
this.setColor(color | 0xFF000000);
}
public void setColorRGB(float r, float g, float b) {
this.setColorRGB((int) (r * 255) << 16 | (int) (g * 255) << 8 | (int) (b * 255));
}
public void setRenderFullBright(boolean renderFullBright) {
this.renderFullBright = renderFullBright;
}
public void setCustomUv(Direction facing, float u1, float v1, float u2, float v2) {
this.customUv.put(facing, new Vector4f(u1, v1, u2, v2));
}
public void setUvRotation(Direction facing, int rotation) {
if (rotation == 2) {
rotation = 3;
} else if (rotation == 3) {
rotation = 2;
}
Preconditions.checkArgument(rotation >= 0 && rotation <= 3, "rotation");
this.uvRotations[facing.ordinal()] = (byte) rotation;
}
/**
* CubeBuilder uses UV optimized for cables by default. This switches to
* standard UV coordinates.
*/
public void useStandardUV() {
this.useStandardUV = true;
}
public List<BakedQuad> getOutput() {
return this.output;
}
}
@@ -25,7 +25,7 @@ import net.minecraft.block.entity.BlockEntity;
import net.minecraft.fluid.IFluidState;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ILightReader;
import net.minecraft.world.BlockRenderView;
import net.minecraft.world.level.ColorResolver;
import net.minecraft.world.lighting.WorldLightManager;
@@ -35,14 +35,14 @@ import net.minecraft.world.lighting.WorldLightManager;
*
* @author covers1624
*/
public class FacadeBlockAccess implements ILightReader {
public class FacadeBlockAccess implements BlockRenderView {
private final ILightReader world;
private final BlockRenderView world;
private final BlockPos pos;
private final Direction side;
private final BlockState state;
public FacadeBlockAccess(ILightReader world, BlockPos pos, Direction side, BlockState state) {
public FacadeBlockAccess(BlockRenderView world, BlockPos pos, Direction side, BlockState state) {
this.world = world;
this.pos = pos;
this.side = side;
@@ -69,8 +69,8 @@ public class FacadeBlockAccess implements ILightReader {
}
@Override
public WorldLightManager getLightManager() {
return world.getLightManager();
public WorldLightManager getLightingProvider() {
return world.getLightingProvider();
}
@Override
@@ -1,435 +0,0 @@
/*
* 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.render.cablebus;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ILightReader;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.data.EmptyModelData;
import appeng.api.AEApi;
import appeng.api.util.AEAxisAlignedBB;
import appeng.parts.misc.CableAnchorPart;
import appeng.thirdparty.codechicken.lib.model.CachedFormat;
import appeng.thirdparty.codechicken.lib.model.Quad;
import appeng.thirdparty.codechicken.lib.model.pipeline.BakedPipeline;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadAlphaOverride;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadClamper;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadCornerKicker;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadFaceStripper;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadReInterpolator;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadTinter;
/**
* The FacadeBuilder builds for facades..
*
* @author covers1624
*/
public class FacadeBuilder {
public static final double THICK_THICKNESS = 2D / 16D;
public static final double THIN_THICKNESS = 1D / 16D;
public static final Box[] THICK_FACADE_BOXES = new Box[] {
new Box(0.0, 0.0, 0.0, 1.0, THICK_THICKNESS, 1.0),
new Box(0.0, 1.0 - THICK_THICKNESS, 0.0, 1.0, 1.0, 1.0),
new Box(0.0, 0.0, 0.0, 1.0, 1.0, THICK_THICKNESS),
new Box(0.0, 0.0, 1.0 - THICK_THICKNESS, 1.0, 1.0, 1.0),
new Box(0.0, 0.0, 0.0, THICK_THICKNESS, 1.0, 1.0),
new Box(1.0 - THICK_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0) };
public static final Box[] THIN_FACADE_BOXES = new Box[] {
new Box(0.0, 0.0, 0.0, 1.0, THIN_THICKNESS, 1.0),
new Box(0.0, 1.0 - THIN_THICKNESS, 0.0, 1.0, 1.0, 1.0),
new Box(0.0, 0.0, 0.0, 1.0, 1.0, THIN_THICKNESS),
new Box(0.0, 0.0, 1.0 - THIN_THICKNESS, 1.0, 1.0, 1.0),
new Box(0.0, 0.0, 0.0, THIN_THICKNESS, 1.0, 1.0),
new Box(1.0 - THIN_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0) };
private final ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial(() -> BakedPipeline.builder()
// Clamper is responsible for clamping the vertex to the bounds specified.
.addElement("clamper", QuadClamper.FACTORY)
// Strips faces if they match a mask.
.addElement("face_stripper", QuadFaceStripper.FACTORY)
// Kicks the edge inner corners in, solves Z fighting
.addElement("corner_kicker", QuadCornerKicker.FACTORY)
// Re-Interpolates the UV's for the quad.
.addElement("interp", QuadReInterpolator.FACTORY)
// Tints the quad if we need it to. Disabled by default.
.addElement("tinter", QuadTinter.FACTORY, false)
// Overrides the quad's alpha if we are forcing transparent facades.
.addElement("transparent", QuadAlphaOverride.FACTORY, false, e -> e.setAlphaOverride(0x4C / 255F)).build()//
);
private final ThreadLocal<Quad> collectors = ThreadLocal.withInitial(Quad::new);
public void buildFacadeQuads(RenderLayer layer, CableBusRenderState renderState, Random rand, List<BakedQuad> quads,
Function<Identifier, BakedModel> modelLookup) {
BakedPipeline pipeline = this.pipelines.get();
Quad collectorQuad = this.collectors.get();
boolean transparent = AEApi.instance().partHelper().getCableRenderMode().transparentFacades;
Map<Direction, FacadeRenderState> facadeStates = renderState.getFacades();
List<Box> partBoxes = renderState.getBoundingBoxes();
Set<Direction> sidesWithParts = renderState.getAttachments().keySet();
ILightReader parentWorld = renderState.getWorld();
BlockPos pos = renderState.getPos();
BlockColors blockColors = MinecraftClient.getInstance().getBlockColors();
boolean thinFacades = isUseThinFacades(partBoxes);
for (Entry<Direction, FacadeRenderState> entry : facadeStates.entrySet()) {
Direction side = entry.getKey();
int sideIndex = side.ordinal();
FacadeRenderState facadeRenderState = entry.getValue();
boolean renderStilt = !sidesWithParts.contains(side);
if (layer == RenderLayer.getCutout() && renderStilt) {
for (Identifier part : CableAnchorPart.FACADE_MODELS.getModels()) {
BakedModel partModel = modelLookup.apply(part);
QuadRotator rotator = new QuadRotator();
quads.addAll(rotator.rotateQuads(gatherQuads(partModel, null, rand, EmptyModelData.INSTANCE), side,
Direction.UP));
}
}
// If we are forcing transparency and this isn't the Translucent layer.
if (transparent && layer != RenderLayer.getTranslucent()) {
continue;
}
BlockState blockState = facadeRenderState.getSourceBlock();
// If we aren't forcing transparency let the block decide if it should render.
if (!transparent && layer != null) {
if (!RenderTypeLookup.canRenderInLayer(blockState, layer)) {
continue;
}
}
Box fullBounds = thinFacades ? THIN_FACADE_BOXES[sideIndex] : THICK_FACADE_BOXES[sideIndex];
Box facadeBox = fullBounds;
// If we are a transparent facade, we need to modify out BB.
if (facadeRenderState.isTransparent()) {
double offset = thinFacades ? THIN_THICKNESS : THICK_THICKNESS;
AEAxisAlignedBB tmpBB = null;
for (Direction face : Direction.values()) {
// Only faces that aren't on our axis
if (face.getAxis() != side.getAxis()) {
FacadeRenderState otherState = facadeStates.get(face);
if (otherState != null && !otherState.isTransparent()) {
if (tmpBB == null) {
tmpBB = AEAxisAlignedBB.fromBounds(facadeBox);
}
switch (face) {
case DOWN:
tmpBB.minY += offset;
break;
case UP:
tmpBB.maxY -= offset;
break;
case NORTH:
tmpBB.minZ += offset;
break;
case SOUTH:
tmpBB.maxZ -= offset;
break;
case WEST:
tmpBB.minX += offset;
break;
case EAST:
tmpBB.maxX -= offset;
break;
default:
throw new RuntimeException("Switch falloff. " + String.valueOf(face));
}
}
}
}
if (tmpBB != null) {
facadeBox = tmpBB.getBoundingBox();
}
}
AEAxisAlignedBB cutOutBox = getCutOutBox(facadeBox, partBoxes);
List<Box> holeStrips = getBoxes(facadeBox, cutOutBox, side.getAxis());
ILightReader facadeAccess = new FacadeBlockAccess(parentWorld, pos, side, blockState);
BlockRenderManager dispatcher = MinecraftClient.getInstance().getBlockRenderManager();
BakedModel model = dispatcher.getModelForState(blockState);
IModelData modelData = model.getModelData(facadeAccess, pos, blockState, EmptyModelData.INSTANCE);
List<BakedQuad> modelQuads = new ArrayList<>();
// If we are forcing transparent facades, fake the render layer, and grab all
// quads.
if (transparent || layer == null) {
for (RenderLayer forcedLayer : RenderLayer.getBlockRenderTypes()) {
// Check if the block renders on the layer we want to force.
if (RenderTypeLookup.canRenderInLayer(blockState, forcedLayer)) {
// Force the layer and gather quads.
ForgeHooksClient.setRenderLayer(forcedLayer);
modelQuads.addAll(gatherQuads(model, blockState, rand, modelData));
}
}
// Reset.
ForgeHooksClient.setRenderLayer(layer);
} else {
modelQuads.addAll(gatherQuads(model, blockState, rand, modelData));
}
// No quads.. Cool, next!
if (modelQuads.isEmpty()) {
continue;
}
// Grab out pipeline elements.
QuadClamper clamper = pipeline.getElement("clamper", QuadClamper.class);
QuadFaceStripper edgeStripper = pipeline.getElement("face_stripper", QuadFaceStripper.class);
QuadTinter tinter = pipeline.getElement("tinter", QuadTinter.class);
QuadCornerKicker kicker = pipeline.getElement("corner_kicker", QuadCornerKicker.class);
// Set global element states.
// calculate the side mask.
int facadeMask = 0;
for (Entry<Direction, FacadeRenderState> ent : facadeStates.entrySet()) {
Direction s = ent.getKey();
if (s.getAxis() != side.getAxis()) {
FacadeRenderState otherState = ent.getValue();
if (!otherState.isTransparent()) {
facadeMask |= 1 << s.ordinal();
}
}
}
// Setup the edge stripper.
edgeStripper.setBounds(fullBounds);
edgeStripper.setMask(facadeMask);
// Setup the kicker.
kicker.setSide(sideIndex);
kicker.setFacadeMask(facadeMask);
kicker.setBox(fullBounds);
kicker.setThickness(thinFacades ? THIN_THICKNESS : THICK_THICKNESS);
for (BakedQuad quad : modelQuads) {
// lookup the format in CachedFormat.
CachedFormat format = CachedFormat.lookup(DefaultVertexFormats.BLOCK);
// If this quad has a tint index, setup the tinter.
if (quad.hasTintIndex()) {
tinter.setTint(blockColors.getColor(blockState, facadeAccess, pos, quad.getColorIndex()));
}
for (Box box : holeStrips) {
// setup the clamper for this box
clamper.setClampBounds(box);
// Reset the pipeline, clears all enabled/disabled states.
pipeline.reset(format);
// Reset out collector.
collectorQuad.reset(format);
// Enable / disable the optional elements
pipeline.setElementState("tinter", quad.hasTintIndex());
pipeline.setElementState("transparent", transparent);
// Prepare the pipeline for a quad.
pipeline.prepare(collectorQuad);
// Pipe our quad into the pipeline.
quad.pipe(pipeline);
// Check if the collector got any data.
if (collectorQuad.full) {
// Add the result.
quads.add(collectorQuad.bake());
}
}
}
}
}
/**
* This is slow, so should be cached.
*
* @return The model.
*/
public List<BakedQuad> buildFacadeItemQuads(ItemStack textureItem, Direction side) {
List<BakedQuad> facadeQuads = new ArrayList<>();
BakedModel model = MinecraftClient.getInstance().getItemRenderer().getItemModelWithOverrides(textureItem, null,
null);
List<BakedQuad> modelQuads = gatherQuads(model, null, new Random(), EmptyModelData.INSTANCE);
BakedPipeline pipeline = this.pipelines.get();
Quad collectorQuad = this.collectors.get();
// Grab pipeline elements.
QuadClamper clamper = pipeline.getElement("clamper", QuadClamper.class);
QuadTinter tinter = pipeline.getElement("tinter", QuadTinter.class);
for (BakedQuad quad : modelQuads) {
// Lookup the CachedFormat for this quads format.
CachedFormat format = CachedFormat.lookup(DefaultVertexFormats.BLOCK);
// Reset the pipeline.
pipeline.reset(format);
// Reset the collector.
collectorQuad.reset(format);
// If we have a tint index, setup the tinter and enable it.
if (quad.hasTintIndex()) {
tinter.setTint(MinecraftClient.getInstance().getItemColors().getColor(textureItem, quad.getColorIndex()));
pipeline.enableElement("tinter");
}
// Disable elements we don't need for items.
pipeline.disableElement("face_stripper");
pipeline.disableElement("corner_kicker");
// Setup the clamper
clamper.setClampBounds(THICK_FACADE_BOXES[side.ordinal()]);
// Prepare the pipeline.
pipeline.prepare(collectorQuad);
// Pipe our quad into the pipeline.
quad.pipe(pipeline);
// Check the collector for data and add the quad if there was.
if (collectorQuad.full) {
facadeQuads.add(collectorQuad.bake());
}
}
return facadeQuads;
}
// Helper to gather all quads from a model into a list.
private static List<BakedQuad> gatherQuads(BakedModel model, BlockState state, Random rand, IModelData data) {
List<BakedQuad> modelQuads = new ArrayList<>();
for (Direction face : Direction.values()) {
modelQuads.addAll(model.getQuads(state, face, rand, data));
}
modelQuads.addAll(model.getQuads(state, null, rand, data));
return modelQuads;
}
/**
* Given the actual facade bounding box, and the bounding boxes of all parts,
* determine the biggest union of AABB that intersect with the facade's bounding
* box. This AABB will need to be "cut out" when the facade is rendered.
*/
@Nullable
private static AEAxisAlignedBB getCutOutBox(Box facadeBox, List<Box> partBoxes) {
AEAxisAlignedBB b = null;
for (Box bb : partBoxes) {
if (bb.intersects(facadeBox)) {
if (b == null) {
b = AEAxisAlignedBB.fromBounds(bb);
} else {
b.maxX = Math.max(b.maxX, bb.maxX);
b.maxY = Math.max(b.maxY, bb.maxY);
b.maxZ = Math.max(b.maxZ, bb.maxZ);
b.minX = Math.min(b.minX, bb.minX);
b.minY = Math.min(b.minY, bb.minY);
b.minZ = Math.min(b.minZ, bb.minZ);
}
}
}
return b;
}
/**
* Generates the box segments around the specified hole. If the specified hole
* is null, a Singleton of the Facade box is returned.
*
* @param fb The Facade's box.
* @param hole The hole to 'cut'.
* @param axis The axis the facade is on.
*
* @return The box segments.
*/
private static List<Box> getBoxes(Box fb, AEAxisAlignedBB hole, Axis axis) {
if (hole == null) {
return Collections.singletonList(fb);
}
List<Box> boxes = new ArrayList<>();
switch (axis) {
case Y:
boxes.add(new Box(fb.minX, fb.minY, fb.minZ, hole.minX, fb.maxY, fb.maxZ));
boxes.add(new Box(hole.maxX, fb.minY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ));
boxes.add(new Box(hole.minX, fb.minY, fb.minZ, hole.maxX, fb.maxY, hole.minZ));
boxes.add(new Box(hole.minX, fb.minY, hole.maxZ, hole.maxX, fb.maxY, fb.maxZ));
break;
case Z:
boxes.add(new Box(fb.minX, fb.minY, fb.minZ, fb.maxX, hole.minY, fb.maxZ));
boxes.add(new Box(fb.minX, hole.maxY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ));
boxes.add(new Box(fb.minX, hole.minY, fb.minZ, hole.minX, hole.maxY, fb.maxZ));
boxes.add(new Box(hole.maxX, hole.minY, fb.minZ, fb.maxX, hole.maxY, fb.maxZ));
break;
case X:
boxes.add(new Box(fb.minX, fb.minY, fb.minZ, fb.maxX, hole.minY, fb.maxZ));
boxes.add(new Box(fb.minX, hole.maxY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ));
boxes.add(new Box(fb.minX, hole.minY, fb.minZ, fb.maxX, hole.maxY, hole.minZ));
boxes.add(new Box(fb.minX, hole.minY, hole.maxZ, fb.maxX, hole.maxY, fb.maxZ));
break;
default:
// should never happen.
throw new RuntimeException("switch falloff. " + String.valueOf(axis));
}
return boxes;
}
/**
* Determines if any of the part's bounding boxes intersects with the outside 2
* voxel wide layer. If so, we should use thinner facades (1 voxel deep).
*/
private static boolean isUseThinFacades(List<Box> partBoxes) {
final double min = 2.0 / 16.0;
final double max = 14.0 / 16.0;
for (Box bb : partBoxes) {
int o = 0;
o += bb.maxX > max ? 1 : 0;
o += bb.maxY > max ? 1 : 0;
o += bb.maxZ > max ? 1 : 0;
o += bb.minX < min ? 1 : 0;
o += bb.minY < min ? 1 : 0;
o += bb.minZ < min ? 1 : 0;
if (o >= 2) {
return true;
}
}
return false;
}
}
@@ -1,28 +0,0 @@
package appeng.client.render.cablebus;
import net.minecraft.block.BlockState;
/**
* Captures the state required to render a facade properly.
*/
public class FacadeRenderState {
// The block state to use for rendering this facade
private final BlockState sourceBlock;
private final boolean transparent;
public FacadeRenderState(BlockState sourceBlock, boolean transparent) {
this.sourceBlock = sourceBlock;
this.transparent = transparent;
}
public BlockState getSourceBlock() {
return this.sourceBlock;
}
public boolean isTransparent() {
return this.transparent;
}
}
@@ -9,18 +9,17 @@ import java.util.concurrent.ExecutionException;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
import appeng.api.util.AEColor;
import appeng.util.Platform;
public class P2PTunnelFrequencyBakedModel implements IDynamicBakedModel {
public class P2PTunnelFrequencyBakedModel implements FabricBakedModel {
private final Sprite texture;
@@ -1,94 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.Direction;
import appeng.client.render.FacingToRotation;
import appeng.thirdparty.codechicken.lib.model.CachedFormat;
import appeng.thirdparty.codechicken.lib.model.Quad;
import appeng.thirdparty.codechicken.lib.model.pipeline.BakedPipeline;
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadMatrixTransformer;
/**
* Assuming a default-orientation of forward=NORTH and up=UP, this class rotates
* a given list of quads to the desired facing
*/
public class QuadRotator {
private static final ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial(() -> //
BakedPipeline.builder()//
.addElement("transformer", QuadMatrixTransformer.FACTORY)//
.build());
private static final ThreadLocal<Quad> collectors = ThreadLocal.withInitial(Quad::new);
public List<BakedQuad> rotateQuads(List<BakedQuad> quads, Direction newForward, Direction newUp) {
if (newForward == Direction.NORTH && newUp == Direction.UP) {
return quads; // This is the default orientation
}
FacingToRotation rotation = getRotation(newForward, newUp);
if (rotation.isRedundant()) {
return quads;
}
List<BakedQuad> result = new ArrayList<>(quads.size());
CachedFormat format = CachedFormat.lookup(DefaultVertexFormats.BLOCK);
BakedPipeline pipeline = pipelines.get();
Quad collector = collectors.get();
QuadMatrixTransformer transformer = pipeline.getElement("transformer", QuadMatrixTransformer.class);
// FIXME: Temporary rotation fix
Matrix4f mat = new Matrix4f();
mat.setTranslation(-0.5f, -0.5f, -0.5f);
mat.multiplyBackward(rotation.getMat());
mat.translate(new Vector3f(0.5f, 0.5f, 0.5f));
for (BakedQuad quad : quads) {
pipeline.reset(format);
collector.reset(format);
transformer.setMatrix(mat);
pipeline.prepare(collector);
quad.pipe(pipeline);
result.add(collector.bake());
}
return result;
}
private FacingToRotation getRotation(Direction forward, Direction up) {
// Sanitize forward/up
if (forward.getAxis() == up.getAxis()) {
if (up.getAxis() == Direction.Axis.Y) {
up = Direction.NORTH;
} else {
up = Direction.UP;
}
}
return FacingToRotation.get(forward, up);
}
}
@@ -1,85 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.cablebus;
import java.util.Arrays;
import java.util.function.Function;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import appeng.core.AppEng;
/**
* Manages the channel textures for smart cables.
*/
public class SmartCableTextures {
public static final SpriteIdentifier[] SMART_CHANNELS_TEXTURES = Arrays
.stream(new Identifier[] { new Identifier(AppEng.MOD_ID, "parts/cable/smart/channels_00"), //
new Identifier(AppEng.MOD_ID, "parts/cable/smart/channels_01"), //
new Identifier(AppEng.MOD_ID, "parts/cable/smart/channels_02"), //
new Identifier(AppEng.MOD_ID, "parts/cable/smart/channels_03"), //
new Identifier(AppEng.MOD_ID, "parts/cable/smart/channels_04"), //
new Identifier(AppEng.MOD_ID, "parts/cable/smart/channels_10"), //
new Identifier(AppEng.MOD_ID, "parts/cable/smart/channels_11"), //
new Identifier(AppEng.MOD_ID, "parts/cable/smart/channels_12"), //
new Identifier(AppEng.MOD_ID, "parts/cable/smart/channels_13"), //
new Identifier(AppEng.MOD_ID, "parts/cable/smart/channels_14")//
}).map(e -> new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX, e)).toArray(SpriteIdentifier[]::new);
// Textures used to display channels on smart cables. There's two sets of 5
// textures each, and
// one of each set are composed together to get even/odd colored channels
private final Sprite[] textures;
public SmartCableTextures(Function<SpriteIdentifier, Sprite> bakedTextureGetter) {
this.textures = Arrays.stream(SMART_CHANNELS_TEXTURES)//
.map(bakedTextureGetter)//
.toArray(Sprite[]::new);
}
/**
* The odd variant is used for displaying channels 1-4 as in use.
*/
public Sprite getOddTextureForChannels(int channels) {
if (channels < 0) {
return this.textures[0];
} else if (channels <= 4) {
return this.textures[channels];
} else {
return this.textures[4];
}
}
/**
* The odd variant is used for displaying channels 5-8 as in use.
*/
public Sprite getEvenTextureForChannels(int channels) {
if (channels < 5) {
return this.textures[5];
} else if (channels <= 8) {
return this.textures[1 + channels];
} else {
return this.textures[9];
}
}
}
@@ -32,18 +32,18 @@ import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormatElement;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.ILightReader;
import net.minecraft.world.BlockRenderView;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
@@ -174,8 +174,8 @@ public class AutoRotatingBakedModel implements BakedModel {
@Nonnull
@Override
public IModelData getModelData(@Nonnull ILightReader world, @Nonnull BlockPos pos, @Nonnull BlockState state,
@Nonnull IModelData tileData) {
public IModelData getModelData(@Nonnull BlockRenderView world, @Nonnull BlockPos pos, @Nonnull BlockState state,
@Nonnull IModelData tileData) {
return this.parent.getModelData(world, pos, state, tileData);
}
@@ -205,9 +205,9 @@ public class AutoRotatingBakedModel implements BakedModel {
for (int v = 0; v < 4; v++) {
for (int e = 0; e < elements.size(); e++) {
VertexFormatElement element = elements.get(e);
if (element.getUsage() == VertexFormatElement.Usage.POSITION) {
if (element.getType() == VertexFormatElement.Usage.POSITION) {
this.parent.put(e, this.transform(this.quadData[e][v]));
} else if (element.getUsage() == VertexFormatElement.Usage.NORMAL) {
} else if (element.getType() == VertexFormatElement.Usage.NORMAL) {
this.parent.put(e, this.transformNormal(this.quadData[e][v]));
} else {
this.parent.put(e, this.quadData[e][v]);
@@ -28,6 +28,7 @@ import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.item.Item;
@@ -73,7 +74,7 @@ public class DriveBakedModel extends DelegateBakedModel {
// 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;
transform.setTranslation(xOffset, yOffset, 0);
transform.addToLastColumn(new Vector3f(xOffset, yOffset, 0));
int slot = row * 2 + col;
@@ -32,20 +32,20 @@ import javax.annotation.Nullable;
import com.google.common.base.Strings;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormatElement;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelOverrideList;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.BlockRenderView;
import net.minecraft.world.BlockView;
import net.minecraft.world.ILightReader;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
import net.minecraftforge.client.model.data.ModelDataMap;
@@ -240,7 +240,7 @@ class GlassBakedModel implements IDynamicBakedModel {
VertexFormat vertexFormat = builder.getVertexFormat();
for (int e = 0; e < vertexFormat.getElements().size(); e++) {
VertexFormatElement el = vertexFormat.getElements().get(e);
switch (el.getUsage()) {
switch (el.getType()) {
case POSITION:
builder.put(e, (float) x, (float) y, (float) z, 1.0f);
break;
@@ -252,8 +252,8 @@ class GlassBakedModel implements IDynamicBakedModel {
break;
case UV:
if (el.getIndex() == 0) {
u = sprite.getInterpolatedU(u);
v = sprite.getInterpolatedV(v);
u = sprite.getFrameU(u);
v = sprite.getFrameV(v);
builder.put(e, u, v, 0f, 1f);
break;
}
@@ -305,8 +305,8 @@ class GlassBakedModel implements IDynamicBakedModel {
@Nonnull
@Override
public IModelData getModelData(@Nonnull ILightReader world, @Nonnull BlockPos pos, @Nonnull BlockState state,
@Nonnull IModelData tileData) {
public IModelData getModelData(@Nonnull BlockRenderView world, @Nonnull BlockPos pos, @Nonnull BlockState state,
@Nonnull IModelData tileData) {
EnumSet<Direction> flushWith = EnumSet.noneOf(Direction.class);
// Test every direction for another glass block
@@ -20,11 +20,11 @@ package appeng.client.render.model;
import java.util.List;
import net.minecraft.client.render.VertexFormatElement;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.pipeline.QuadGatheringTransformer;
@@ -48,9 +48,9 @@ final class MatrixVertexTransformer extends QuadGatheringTransformer {
for (int v = 0; v < 4; v++) {
for (int e = 0; e < count; e++) {
VertexFormatElement element = elements.get(e);
if (element.getUsage() == VertexFormatElement.Usage.POSITION) {
if (element.getType() == VertexFormatElement.Usage.POSITION) {
this.parent.put(e, this.transform(this.quadData[e][v], element.getElementCount()));
} else if (element.getUsage() == VertexFormatElement.Usage.NORMAL) {
} else if (element.getType() == VertexFormatElement.Usage.NORMAL) {
this.parent.put(e, this.transformNormal(this.quadData[e][v]));
} else {
this.parent.put(e, this.quadData[e][v]);
@@ -61,7 +61,7 @@ public class CrankTESR extends BlockEntityRenderer<CrankBlockEntity> {
BlockState blockState = te.getCachedState();
BlockRenderManager dispatcher = MinecraftClient.getInstance().getBlockRenderManager();
BakedModel model = dispatcher.getModelForState(blockState);
BakedModel model = dispatcher.getModel(blockState);
VertexConsumer buffer = buffers.getBuffer(TexturedRenderLayers.getEntityTranslucentCull());
dispatcher.getModelRenderer().renderModelBrightnessColor(ms.peek(), buffer, null, model, 1, 1, 1,
combinedLightIn, combinedOverlayIn);
@@ -4,17 +4,16 @@ 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 com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.renderer.RenderState;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@@ -70,7 +69,7 @@ public class DriveLedTileEntityRenderer extends BlockEntityRenderer<DriveBlockEn
// Bottom Face
R, B, FR, L, B, FR, L, B, BA, R, B, BA, };
private static final RenderLayer STATE = RenderLayer.makeType("ae_drive_leds", DefaultVertexFormats.POSITION_COLOR, 7,
private static final RenderLayer STATE = RenderLayer.makeType("ae_drive_leds", VertexFormats.POSITION_COLOR, 7,
32565, false, true, RenderLayer.State.getBuilder().build(false));
public DriveLedTileEntityRenderer(BlockEntityRenderDispatcher rendererDispatcherIn) {
@@ -90,9 +89,9 @@ public class DriveLedTileEntityRenderer extends BlockEntityRenderer<DriveBlockEn
FacingToRotation.get(drive.getForward(), drive.getUp()).push(ms);
ms.translate(-0.5, -0.5, -0.5);
RenderType rt = RenderType.makeType("ae_drive_leds", DefaultVertexFormats.POSITION_COLOR, 7, 32565, false, true,
RenderType rt = RenderType.makeType("ae_drive_leds", VertexFormats.POSITION_COLOR, 7, 32565, false, true,
RenderType.State.getBuilder().transparency(TRANSLUCENT_TRANSPARENCY).build(false));
IVertexBuilder buffer = buffers.getBuffer(STATE);
VertexConsumer buffer = buffers.getBuffer(STATE);
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 2; col++) {
@@ -175,7 +175,7 @@ public final class InscriberTESR extends BlockEntityRenderer<InscriberBlockEntit
float z, double texU, double texV, int overlayUV, int lightmapUV, Direction front) {
vb.pos(ms.peek().getMatrix(), x, y, z);
vb.color(1.0f, 1.0f, 1.0f, 1.0f);
vb.tex(sprite.getInterpolatedU(texU), sprite.getInterpolatedV(texV));
vb.tex(sprite.getFrameU(texU), sprite.getFrameV(texV));
vb.overlay(overlayUV);
vb.lightmap(lightmapUV);
vb.normal(ms.peek().getNormal(), front.getOffsetX(), front.getOffsetY(), front.getOffsetZ());
@@ -66,7 +66,7 @@ public final class FacadeItemGroup extends ItemGroup {
for (final Block b : ForgeRegistries.BLOCKS) {
try {
final Item item = Item.getItemFromBlock(b);
final Item item = Item.fromBlock(b);
if (item == Items.AIR) {
continue;
}
@@ -107,7 +107,7 @@ public class BlockTransitionEffectPacket extends BasePacket {
EnergyParticleData data = new EnergyParticleData(false, direction);
for (int zz = 0; zz < 32; zz++) {
if (AppEng.proxy.shouldAddParticles(Platform.getRandom())) {
if (AppEng.instance().shouldAddParticles(Platform.getRandom())) {
// Distribute the spawn point across the entire block's area
double x = pos.getX() + Platform.getRandomFloat();
double y = pos.getY() + Platform.getRandomFloat();
@@ -140,7 +140,7 @@ public class BlockTransitionEffectPacket extends BasePacket {
volume = 1;
pitch = 1;
} else if (soundMode == SoundMode.BLOCK) {
BlockSoundGroup soundType = blockState.getSoundType();
BlockSoundGroup soundType = blockState.getSoundGroup();
soundEvent = soundType.getBreakSound();
volume = soundType.volume;
pitch = soundType.pitch;
@@ -82,7 +82,7 @@ public class ClickPacket extends BasePacket {
// API for when an item in hand was right-clicked, with no block context
public ClickPacket(Hand hand) {
this(BlockPos.ZERO, null, 0, 0, 0, hand);
this(BlockPos.ORIGIN, null, 0, 0, 0, hand);
}
private ClickPacket(final BlockPos pos, final Direction side, final float hitX, final float hitY, final float hitZ,
@@ -135,9 +135,9 @@ public class InventoryActionPacket extends BasePacket {
public void clientPacketData(final INetworkInfo network, final PlayerEntity player) {
if (this.action == InventoryAction.UPDATE_HAND) {
if (this.slotItem == null) {
AppEng.proxy.getPlayers().get(0).inventory.setItemStack(ItemStack.EMPTY);
AppEng.instance().getPlayers().get(0).inventory.setItemStack(ItemStack.EMPTY);
} else {
AppEng.proxy.getPlayers().get(0).inventory.setItemStack(this.slotItem.createItemStack());
AppEng.instance().getPlayers().get(0).inventory.setItemStack(this.slotItem.createItemStack());
}
}
}
@@ -74,7 +74,7 @@ public class ItemTransitionEffectPacket extends BasePacket {
public void clientPacketData(final INetworkInfo network, final PlayerEntity player) {
EnergyParticleData data = new EnergyParticleData(true, this.d);
for (int zz = 0; zz < 8; zz++) {
if (AppEng.proxy.shouldAddParticles(Platform.getRandom())) {
if (AppEng.instance().shouldAddParticles(Platform.getRandom())) {
// Distribute the spawn point around the item's position
double x = this.x + Platform.getRandomFloat() * 0.5 - 0.25;
double y = this.y + Platform.getRandomFloat() * 0.5 - 0.25;
@@ -1,78 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.core.sync.packets;
import io.netty.buffer.Unpooled;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import appeng.core.AppEng;
import appeng.core.sync.BasePacket;
import appeng.core.sync.network.INetworkInfo;
import appeng.parts.PartPlacement;
public class PartPlacementPacket extends BasePacket {
private int x;
private int y;
private int z;
private int face;
private float eyeHeight;
private Hand hand;
public PartPlacementPacket(final PacketByteBuf stream) {
this.x = stream.readInt();
this.y = stream.readInt();
this.z = stream.readInt();
this.face = stream.readByte();
this.eyeHeight = stream.readFloat();
this.hand = Hand.values()[stream.readByte()];
}
// api
public PartPlacementPacket(final BlockPos pos, final Direction face, final float eyeHeight, final Hand hand) {
final PacketByteBuf data = new PacketByteBuf(Unpooled.buffer());
data.writeInt(this.getPacketID());
data.writeInt(pos.getX());
data.writeInt(pos.getY());
data.writeInt(pos.getZ());
data.writeByte(face.ordinal());
data.writeFloat(eyeHeight);
data.writeByte(hand.ordinal());
this.configureWrite(data);
}
@Override
public void serverPacketData(final INetworkInfo manager, final PlayerEntity player) {
final ServerPlayerEntity sender = (ServerPlayerEntity) player;
AppEng.proxy.updateRenderMode(sender);
PartPlacement.setEyeHeight(this.eyeHeight);
PartPlacement.place(sender.getStackInHand(this.hand), new BlockPos(this.x, this.y, this.z),
Direction.values()[this.face], sender, this.hand, sender.world,
PartPlacement.PlaceType.INTERACT_FIRST_PASS, 0);
AppEng.proxy.updateRenderMode(null);
}
}
@@ -19,7 +19,7 @@
package appeng.debug;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.DirectionalPlaceContext;
import net.minecraft.item.AutomaticItemPlacementContext;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
@@ -50,7 +50,7 @@ public class CubeGeneratorBlockEntity extends AEBaseBlockEntity implements Ticka
this.countdown--;
if (this.countdown % 20 == 0) {
for (final PlayerEntity e : AppEng.proxy.getPlayers()) {
for (final PlayerEntity e : AppEng.instance().getPlayers()) {
e.sendSystemMessage(new LiteralText("Spawning in... " + (this.countdown / 20)), Util.NIL_UUID);
}
}
@@ -73,7 +73,7 @@ public class CubeGeneratorBlockEntity extends AEBaseBlockEntity implements Ticka
for (int x = -half; x < half; x++) {
for (int z = -half; z < half; z++) {
final BlockPos p = this.pos.add(x, y - 1, z);
ItemUsageContext useContext = new DirectionalPlaceContext(this.world, p, side, this.is,
ItemUsageContext useContext = new AutomaticItemPlacementContext(this.world, p, side, this.is,
side.getOpposite());
i.onItemUse(useContext);
}
@@ -71,7 +71,7 @@ public class DebugPartPlacerItem extends AEBaseItem {
.toArray(Direction[]::new);
BlockPos nextPos = pos;
for (Item item : ForgeRegistries.ITEMS) {
for (Item item : Registry.ITEM) {
if (!(item instanceof PartItem)) {
continue;
}
@@ -47,7 +47,7 @@ public class ItemGenBlockEntity extends AEBaseBlockEntity {
public ItemGenBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
if (POSSIBLE_ITEMS.isEmpty()) {
for (final Item mi : ForgeRegistries.ITEMS) {
for (final Item mi : Registry.ITEM) {
if (mi != null && mi != Items.AIR) {
if (mi.isDamageable()) {
ItemStack sampleStack = new ItemStack(mi);
@@ -1,178 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.facade;
import java.io.IOException;
import java.util.Optional;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.PacketByteBuf;
import appeng.api.AEApi;
import appeng.api.parts.IFacadeContainer;
import appeng.api.parts.IFacadePart;
import appeng.api.parts.IPartHost;
import appeng.api.util.AEPartLocation;
import appeng.items.parts.FacadeItem;
import appeng.parts.CableBusStorage;
public class FacadeContainer implements IFacadeContainer {
private final int facades = 6;
private final CableBusStorage storage;
public FacadeContainer(final CableBusStorage cbs) {
this.storage = cbs;
}
@Override
public boolean addFacade(final IFacadePart a) {
if (this.getFacade(a.getSide()) == null) {
this.storage.setFacade(a.getSide().ordinal(), a);
return true;
}
return false;
}
@Override
public void removeFacade(final IPartHost host, final AEPartLocation side) {
if (side != null && side != AEPartLocation.INTERNAL) {
if (this.storage.getFacade(side.ordinal()) != null) {
this.storage.setFacade(side.ordinal(), null);
if (host != null) {
host.markForUpdate();
}
}
}
}
@Override
public IFacadePart getFacade(final AEPartLocation s) {
return this.storage.getFacade(s.ordinal());
}
@Override
public void rotateLeft() {
final IFacadePart[] newFacades = new FacadePart[6];
newFacades[AEPartLocation.UP.ordinal()] = this.storage.getFacade(AEPartLocation.UP.ordinal());
newFacades[AEPartLocation.DOWN.ordinal()] = this.storage.getFacade(AEPartLocation.DOWN.ordinal());
newFacades[AEPartLocation.EAST.ordinal()] = this.storage.getFacade(AEPartLocation.NORTH.ordinal());
newFacades[AEPartLocation.SOUTH.ordinal()] = this.storage.getFacade(AEPartLocation.EAST.ordinal());
newFacades[AEPartLocation.WEST.ordinal()] = this.storage.getFacade(AEPartLocation.SOUTH.ordinal());
newFacades[AEPartLocation.NORTH.ordinal()] = this.storage.getFacade(AEPartLocation.WEST.ordinal());
for (int x = 0; x < this.facades; x++) {
this.storage.setFacade(x, newFacades[x]);
}
}
@Override
public void writeToNBT(final CompoundTag c) {
for (int x = 0; x < this.facades; x++) {
if (this.storage.getFacade(x) != null) {
final CompoundTag data = new CompoundTag();
this.storage.getFacade(x).getItemStack().toTag(data);
c.put("facade:" + x, data);
}
}
}
@Override
public boolean readFromStream(final PacketByteBuf out) throws IOException {
final int facadeSides = out.readByte();
boolean changed = false;
for (int x = 0; x < this.facades; x++) {
final AEPartLocation side = AEPartLocation.fromOrdinal(x);
final int ix = (1 << x);
if ((facadeSides & ix) == ix) {
final int id = Math.abs(out.readInt());
Optional<net.minecraft.item.Item> maybeFacadeItem = AEApi.instance().definitions().items().facade()
.maybeItem();
if (maybeFacadeItem.isPresent()) {
final FacadeItem ifa = (FacadeItem) maybeFacadeItem.get();
final ItemStack facade = ifa.createFromID(id);
if (facade != null) {
changed = changed || this.storage.getFacade(x) == null;
this.storage.setFacade(x, ifa.createPartFromItemStack(facade, side));
}
}
} else {
changed = changed || this.storage.getFacade(x) != null;
this.storage.setFacade(x, null);
}
}
return changed;
}
@Override
public void readFromNBT(final CompoundTag c) {
for (int x = 0; x < this.facades; x++) {
this.storage.setFacade(x, null);
final CompoundTag t = c.getCompound("facade:" + x);
if (t != null) {
final ItemStack is = ItemStack.fromTag(t);
if (!is.isEmpty()) {
final net.minecraft.item.Item i = is.getItem();
if (i instanceof IFacadeItem) {
this.storage.setFacade(x,
((IFacadeItem) i).createPartFromItemStack(is, AEPartLocation.fromOrdinal(x)));
}
}
}
}
}
@Override
public void writeToStream(final PacketByteBuf out) throws IOException {
int facadeSides = 0;
for (int x = 0; x < this.facades; x++) {
if (this.getFacade(AEPartLocation.fromOrdinal(x)) != null) {
facadeSides |= (1 << x);
}
}
out.writeByte((byte) facadeSides);
for (int x = 0; x < this.facades; x++) {
final IFacadePart part = this.getFacade(AEPartLocation.fromOrdinal(x));
if (part != null) {
final int itemID = net.minecraft.item.Item.getIdFromItem(part.getItem());
out.writeInt(itemID * (part.notAEFacade() ? -1 : 1));
}
}
}
@Override
public boolean isEmpty() {
for (int x = 0; x < this.facades; x++) {
if (this.storage.getFacade(x) != null) {
return false;
}
}
return true;
}
}
-108
View File
@@ -1,108 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.facade;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import appeng.api.parts.IFacadePart;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.util.AEPartLocation;
public class FacadePart implements IFacadePart {
private final ItemStack facade;
private final AEPartLocation side;
public FacadePart(final ItemStack facade, final AEPartLocation side) {
if (facade == null) {
throw new IllegalArgumentException("Facade Part constructed on null item.");
}
this.facade = facade.copy();
this.facade.setCount(1);
this.side = side;
}
@Override
public ItemStack getItemStack() {
return this.facade;
}
@Override
public void getBoxes(final IPartCollisionHelper ch, boolean livingEntity) {
if (livingEntity) {
// prevent weird snag behavior
ch.addBox(0.0, 0.0, 14, 16.0, 16.0, 16.0);
} else {
// the box is 15.9 for transition planes to pick up collision events.
ch.addBox(0.0, 0.0, 14, 16.0, 16.0, 15.9);
}
}
@Override
public AEPartLocation getSide() {
return this.side;
}
@Override
public Item getItem() {
final ItemStack is = this.getTextureItem();
if (is.isEmpty()) {
return Items.AIR;
}
return is.getItem();
}
@Override
public boolean notAEFacade() {
return !(this.facade.getItem() instanceof IFacadeItem);
}
@Override
public ItemStack getTextureItem() {
final Item maybeFacade = this.facade.getItem();
// AE Facade
if (maybeFacade instanceof IFacadeItem) {
final IFacadeItem facade = (IFacadeItem) maybeFacade;
return facade.getTextureItem(this.facade);
}
return ItemStack.EMPTY;
}
@Override
public BlockState getBlockState() {
final Item maybeFacade = this.facade.getItem();
// AE Facade
if (maybeFacade instanceof IFacadeItem) {
final IFacadeItem facade = (IFacadeItem) maybeFacade;
return facade.getTextureBlockState(this.facade);
}
return Blocks.GLASS.getDefaultState();
}
}
@@ -1,34 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.facade;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import appeng.api.util.AEPartLocation;
public interface IFacadeItem {
FacadePart createPartFromItemStack(ItemStack is, AEPartLocation side);
ItemStack getTextureItem(ItemStack is);
BlockState getTextureBlockState(ItemStack is);
}
@@ -237,7 +237,7 @@ public class FluidTerminalScreen extends AEBaseMEScreen<FluidTerminalContainer>
InputUtil.Key input = InputMappings.getInputByCode(keyCode, scanCode);
if (keyCode != GLFW.GLFW_KEY_ESCAPE && !this.checkHotbarKeys(input)) {
if (AppEng.proxy.isActionKey(ActionKey.TOGGLE_FOCUS, input)) {
if (AppEng.instance().isActionKey(ActionKey.TOGGLE_FOCUS, input)) {
this.searchField.setFocused2(!this.searchField.isFocused());
return true;
}
@@ -251,7 +251,7 @@ public class FluidAnnihilationPlanePart extends BasicStatePart implements IGridT
this.storeFluid(AEFluidStack.fromFluidStack(new FluidVolume(fluid, FluidAttributes.BUCKET_VOLUME)),
true);
AppEng.proxy.sendToAllNearExcept(null, pos.getX(), pos.getY(), pos.getZ(), 64, w,
AppEng.instance().sendToAllNearExcept(null, pos.getX(), pos.getY(), pos.getZ(), 64, w,
new BlockTransitionEffectPacket(pos, blockstate, this.getSide().getOpposite(),
BlockTransitionEffectPacket.SoundMode.FLUID));
@@ -1,27 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.helpers;
import appeng.api.implementations.tiles.IColorableTile;
import appeng.api.networking.IGridHost;
import appeng.api.parts.IPartHost;
public interface AEMultiTile extends IGridHost, IPartHost, IColorableTile {
}
@@ -29,6 +29,8 @@ import java.util.Optional;
import javax.annotation.Nullable;
import alexiil.mc.lib.attributes.item.FixedItemInv;
import appeng.block.networking.CableBusBlock;
import appeng.tile.networking.CableBusBlockEntity;
import com.google.common.collect.ImmutableSet;
import net.minecraft.block.Block;
@@ -982,12 +984,13 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
final BlockHitResult hit = null;// hostWorld.rayTraceBlocks( from, to ); //FIXME:
// https://github.com/MinecraftForge/MinecraftForge/pull/6708
if (hit != null && !BAD_BLOCKS.contains(directedBlock)) {
if (hit.getPos().equals(directedTile.getPos())) {
final ItemStack g = directedBlock.getPickBlock(directedBlockState, hit, hostWorld,
directedTile.getPos(), null);
if (!g.isEmpty()) {
what = g;
}
if (hit.getBlockPos().equals(directedTile.getPos())) {
// FIXME FABRIC: Either add "getName" to the interface adaptor, or special-case cable buses here
// FIXME FABRIC final ItemStack g = directedBlock.getPickBlock(directedBlockState, hit, hostWorld,
// FIXME FABRIC directedTile.getPos(), null);
// FIXME FABRIC if (!g.isEmpty()) {
// FIXME FABRIC what = g;
// FIXME FABRIC }
}
}
} catch (final Throwable t) {
@@ -998,7 +1001,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
return new TranslatableText(what.getTranslationKey());
}
final Item item = Item.getItemFromBlock(directedBlock);
final Item item = Item.fromBlock(directedBlock);
if (item == Items.AIR) {
return new TranslatableText(directedBlock.getTranslationKey());
}
@@ -21,7 +21,7 @@ package appeng.hooks;
import net.minecraft.block.DispenserBlock;
import net.minecraft.block.dispenser.ItemDispenserBehavior;
import net.minecraft.util.math.BlockPointer;
import net.minecraft.item.DirectionalPlaceContext;
import net.minecraft.item.AutomaticItemPlacementContext;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
@@ -40,7 +40,7 @@ public final class BlockToolDispenseItemBehavior extends ItemDispenserBehavior {
final World w = dispenser.getWorld();
if (w instanceof ServerWorld) {
ItemUsageContext context = new DirectionalPlaceContext(w, dispenser.getBlockPos().offset(direction),
ItemUsageContext context = new AutomaticItemPlacementContext(w, dispenser.getBlockPos().offset(direction),
direction, dispensedItem, direction.getOpposite());
tm.onItemUse(context);
}
@@ -1,53 +0,0 @@
/*
* 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.integration.abstraction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView;
import team.chisel.ctm.api.IFacade;
/**
* Neat abstraction class for All the IFacade interfaces.
*
* @author covers1624
*/
public interface IAEFacade extends IFacade {
BlockState getFacadeState(BlockView world, BlockPos pos, @Nullable Direction side);
@Nonnull
@Override
default BlockState getFacade(@Nonnull BlockView world, @Nonnull BlockPos pos, @Nullable Direction side) {
return getFacadeState(world, pos, side);
}
@Nonnull
@Override
default BlockState getFacade(@Nonnull BlockView world, @Nonnull BlockPos pos, @Nullable Direction side,
@Nonnull BlockPos connection) {
return getFacadeState(world, pos, side);
}
}
@@ -1,23 +0,0 @@
package appeng.items.parts;
import java.util.function.Function;
import net.minecraft.item.ItemStack;
import appeng.api.parts.IPart;
import appeng.api.util.AEColor;
public class ColoredPartItem<T extends IPart> extends PartItem<T> {
private final AEColor color;
public ColoredPartItem(Settings properties, Function<ItemStack, T> factory, AEColor color) {
super(properties, factory);
this.color = color;
}
public AEColor getColor() {
return color;
}
}
@@ -1,201 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.items.parts;
import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.renderer.RenderTypeLookup;
import net.minecraft.item.*;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.tag.BlockTags;
import net.minecraft.tag.Tag;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Identifier;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.text.Text;
import net.minecraft.world.EmptyBlockReader;
import net.minecraftforge.registries.ForgeRegistries;
import appeng.api.AEApi;
import appeng.api.exceptions.MissingDefinitionException;
import appeng.api.features.AEFeature;
import appeng.api.parts.IAlphaPassItem;
import appeng.api.util.AEPartLocation;
import appeng.core.AEConfig;
import appeng.core.AppEng;
import appeng.facade.FacadePart;
import appeng.facade.IFacadeItem;
import appeng.items.AEBaseItem;
public class FacadeItem extends AEBaseItem implements IFacadeItem, IAlphaPassItem {
/**
* Block tag used to explicitly whitelist blocks for use in facades.
*/
private static final Identifier TAG_WHITELISTED = new Identifier(AppEng.MOD_ID, "whitelisted/facades");
private static final String NBT_ITEM_ID = "item";
public FacadeItem(Settings properties) {
super(properties);
}
@Override
public ActionResult onItemUseFirst(ItemStack stack, ItemUsageContext context) {
return AEApi.instance().partHelper().placeBus(stack, context.getBlockPos(), context.getSide(), context.getPlayer(),
context.getHand(), context.getWorld());
}
@Override
public Text getName(ItemStack is) {
try {
final ItemStack in = this.getTextureItem(is);
if (!in.isEmpty()) {
return super.getName(is).deepCopy().append(" - ").append(in.getName());
}
} catch (final Throwable ignored) {
}
return super.getName(is);
}
@Override
public void appendStacks(ItemGroup group, DefaultedList<ItemStack> items) {
}
public ItemStack createFacadeForItem(final ItemStack itemStack, final boolean returnItem) {
if (itemStack.isEmpty() || itemStack.hasTag() || !(itemStack.getItem() instanceof BlockItem)) {
return ItemStack.EMPTY;
}
BlockItem blockItem = (BlockItem) itemStack.getItem();
Block block = blockItem.getBlock();
if (block == Blocks.AIR) {
return ItemStack.EMPTY;
}
// We only support the default state for facades. Sorry.
BlockState blockState = block.getDefaultState();
final boolean areTileEntitiesEnabled = AEConfig.instance().isFeatureEnabled(AEFeature.TILE_ENTITY_FACADES);
Tag<Block> whitelistTag = BlockTags.getCollection().getOrCreate(TAG_WHITELISTED);
final boolean isWhiteListed = block.isIn(whitelistTag);
final boolean isModel = blockState.getRenderType() == BlockRenderType.MODEL;
final BlockState defaultState = block.getDefaultState();
final boolean isTileEntity = block.hasTileEntity(defaultState);
final boolean isFullCube = defaultState.isNormalCube(EmptyBlockReader.INSTANCE, BlockPos.ZERO);
final boolean isTileEntityAllowed = !isTileEntity || (areTileEntitiesEnabled && isWhiteListed);
final boolean isBlockAllowed = isFullCube || isWhiteListed;
if (isModel && isTileEntityAllowed && isBlockAllowed) {
if (returnItem) {
return itemStack;
}
final ItemStack is = new ItemStack(this);
final CompoundTag data = new CompoundTag();
data.putString(NBT_ITEM_ID, itemStack.getItem().getRegistryName().toString());
is.setTag(data);
return is;
}
return ItemStack.EMPTY;
}
@Override
public FacadePart createPartFromItemStack(final ItemStack is, final AEPartLocation side) {
final ItemStack in = this.getTextureItem(is);
if (!in.isEmpty()) {
return new FacadePart(is, side);
}
return null;
}
@Override
public ItemStack getTextureItem(ItemStack is) {
CompoundTag nbt = is.getTag();
if (nbt == null) {
return ItemStack.EMPTY;
}
Identifier itemId = new Identifier(nbt.getString(NBT_ITEM_ID));
Item baseItem = ForgeRegistries.ITEMS.getValue(itemId);
if (baseItem == null) {
return ItemStack.EMPTY;
}
return new ItemStack(baseItem, 1);
}
@Override
public BlockState getTextureBlockState(ItemStack is) {
ItemStack baseItemStack = this.getTextureItem(is);
if (baseItemStack.isEmpty()) {
return Blocks.GLASS.getDefaultState();
}
Block block = Block.getBlockFromItem(baseItemStack.getItem());
if (block == Blocks.AIR) {
return Blocks.GLASS.getDefaultState();
}
return block.getDefaultState();
}
public ItemStack createFromID(final int id) {
ItemStack facadeStack = AEApi.instance().definitions().items().facade().maybeStack(1).orElseThrow(
() -> new MissingDefinitionException("Tried to create a facade, while facades are being deactivated."));
// Convert back to a registry name...
Item item = Registry.ITEM.getByValue(id);
if (item == Items.AIR) {
return ItemStack.EMPTY;
}
final CompoundTag facadeTag = new CompoundTag();
facadeTag.putString(NBT_ITEM_ID, item.getRegistryName().toString());
facadeStack.setTag(facadeTag);
return facadeStack;
}
@Override
public boolean useAlphaPass(final ItemStack is) {
BlockState blockState = this.getTextureBlockState(is);
if (blockState == null) {
return false;
}
return RenderTypeLookup.canRenderInLayer(blockState, RenderLayer.getTranslucent())
|| RenderTypeLookup.canRenderInLayer(blockState, RenderLayer.getTranslucentNoCrumbling());
}
}
@@ -1,59 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.items.parts;
import java.util.function.Function;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.util.ActionResult;
import appeng.api.AEApi;
import appeng.api.parts.IPart;
import appeng.api.parts.IPartItem;
import appeng.items.AEBaseItem;
public class PartItem<T extends IPart> extends AEBaseItem implements IPartItem<T> {
private final Function<ItemStack, T> factory;
public PartItem(Settings properties, Function<ItemStack, T> factory) {
super(properties);
this.factory = factory;
}
@Override
public ActionResult onItemUse(ItemUsageContext context) {
PlayerEntity player = context.getPlayer();
ItemStack held = player.getStackInHand(context.getHand());
if (held.getItem() != this) {
return ActionResult.PASS;
}
return AEApi.instance().partHelper().placeBus(held, context.getBlockPos(), context.getSide(), player,
context.getHand(), context.getWorld());
}
@Override
public T createPart(ItemStack is) {
return factory.apply(is);
}
}
@@ -1,46 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.items.parts;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.api.util.AEColor;
import appeng.bootstrap.IItemRendering;
import appeng.bootstrap.ItemRenderingCustomizer;
import appeng.client.render.StaticItemColor;
public class PartItemRendering extends ItemRenderingCustomizer {
private final AEColor color;
public PartItemRendering() {
this.color = AEColor.TRANSPARENT;
}
public PartItemRendering(AEColor color) {
this.color = color;
}
@Override
@Environment(EnvType.CLIENT)
public void customize(IItemRendering rendering) {
rendering.color(new StaticItemColor(color));
}
}
@@ -1,34 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.items.parts;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* This annotation is used to mark static fields or static methods that
* return/contain models used for a part. They are automatically registered as
* part of the part item registration.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD })
public @interface PartModels {
}
@@ -1,124 +0,0 @@
package appeng.items.parts;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.minecraft.util.Identifier;
import appeng.api.parts.IPartModel;
import appeng.core.AELog;
/**
* Helps with the reflection magic needed to gather all models for AE2 cable bus
* parts.
*/
public class PartModelsHelper {
public static List<Identifier> createModels(Class<?> clazz) {
List<Identifier> locations = new ArrayList<>();
// Check all static fields for used models
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.getAnnotation(PartModels.class) == null) {
continue;
}
if (!Modifier.isStatic(field.getModifiers())) {
AELog.error("The @PartModels annotation can only be used on static fields or methods. Was seen on: "
+ field);
continue;
}
Object value;
try {
field.setAccessible(true);
value = field.get(null);
} catch (IllegalAccessException e) {
AELog.error(e, "Cannot access field annotated with @PartModels: " + field);
continue;
}
convertAndAddLocation(field, value, locations);
}
// Check all static methods for the annotation
for (Method method : clazz.getDeclaredMethods()) {
if (method.getAnnotation(PartModels.class) == null) {
continue;
}
if (!Modifier.isStatic(method.getModifiers())) {
AELog.error("The @PartModels annotation can only be used on static fields or methods. Was seen on: "
+ method);
continue;
}
// Check for parameter count
if (method.getParameters().length != 0) {
AELog.error(
"The @PartModels annotation can only be used on static methods without parameters. Was seen on: "
+ method);
continue;
}
// Make sure we can handle the return type
Class<?> returnType = method.getReturnType();
if (!Identifier.class.isAssignableFrom(returnType)
&& !Collection.class.isAssignableFrom(returnType)) {
AELog.error(
"The @PartModels annotation can only be used on static methods that return a ResourceLocation or Collection of "
+ "ResourceLocations. Was seen on: " + method);
continue;
}
Object value;
try {
method.setAccessible(true);
value = method.invoke(null);
} catch (IllegalAccessException | InvocationTargetException e) {
AELog.error(e, "Failed to invoke the @PartModels annotated method " + method);
continue;
}
convertAndAddLocation(method, value, locations);
}
if (clazz.getSuperclass() != null) {
locations.addAll(createModels(clazz.getSuperclass()));
}
return locations;
}
private static void convertAndAddLocation(Object source, Object value, List<Identifier> locations) {
if (value == null) {
return;
}
if (value instanceof Identifier) {
locations.add((Identifier) value);
} else if (value instanceof IPartModel) {
locations.addAll(((IPartModel) value).getModels());
} else if (value instanceof Collection) {
// Check that each object is an IPartModel
Collection<?> values = (Collection<?>) value;
for (Object candidate : values) {
if (!(candidate instanceof IPartModel)) {
AELog.error("List of locations obtained from {} contains a non resource location: {}", source,
candidate);
continue;
}
locations.addAll(((IPartModel) candidate).getModels());
}
}
}
}
@@ -74,7 +74,7 @@ public class NetworkToolItem extends AEBaseItem implements IGuiItem, IAEWrench {
@Override
public TypedActionResult<ItemStack> use(final World w, final PlayerEntity p, final Hand hand) {
if (Platform.isClient()) {
final HitResult mop = AppEng.proxy.getRTR();
final HitResult mop = AppEng.instance().getRTR();
if (mop == null || mop.getType() == HitResult.Type.MISS) {
NetworkHandler.instance().sendToServer(new ClickPacket(hand));
@@ -47,7 +47,7 @@ public class ChargedStaffItem extends AEBasePoweredItem {
final float dx = (float) (Platform.getRandomFloat() * target.getWidth() + entityBoundingBox.minX);
final float dy = (float) (Platform.getRandomFloat() * target.getHeight() + entityBoundingBox.minY);
final float dz = (float) (Platform.getRandomFloat() * target.getWidth() + entityBoundingBox.minZ);
AppEng.proxy.sendToAllNearExcept(null, dx, dy, dz, 32.0, target.world,
AppEng.instance().sendToAllNearExcept(null, dx, dy, dz, 32.0, target.world,
new LightningPacket(dx, dy, dz));
}
}
@@ -205,16 +205,14 @@ public class EntropyManipulatorItem extends AEBasePoweredItem implements IBlockT
// considered for onItemUse
@Override
public TypedActionResult<ItemStack> use(final World w, final PlayerEntity p, final Hand hand) {
final HitResult target = rayTrace(w, p, RayTraceContext.FluidHandling.ANY);
final BlockHitResult target = rayTrace(w, p, RayTraceContext.FluidHandling.ANY);
if (target.getType() != HitResult.Type.BLOCK) {
return new TypedActionResult<>(ActionResult.FAIL, p.getStackInHand(hand));
} else {
BlockPos pos = ((BlockHitResult) target).getPos();
BlockPos pos = target.getBlockPos();
final BlockState state = w.getBlockState(pos);
if (state.getMaterial() == Material.LAVA || state.getMaterial() == Material.WATER) {
if (Platform.hasPermissions(new DimensionalCoord(w, pos), p)) {
ItemUsageContext context = new ItemUsageContext(p, hand, (BlockHitResult) target);
ItemUsageContext context = new ItemUsageContext(p, hand, target);
this.onItemUse(context);
}
}
@@ -327,7 +325,7 @@ public class EntropyManipulatorItem extends AEBasePoweredItem implements IBlockT
return ActionResult.FAIL;
}
if (w.isAirBlock(offsetPos)) {
if (w.isAir(offsetPos)) {
this.extractAEPower(item, 1600, Actionable.MODULATE);
w.playSound(p, offsetPos.getX() + 0.5D, offsetPos.getY() + 0.5D, offsetPos.getZ() + 0.5D,
SoundEvents.ITEM_FLINTANDSTEEL_USE, SoundCategory.PLAYERS, 1.0F,
@@ -226,7 +226,7 @@ public class MatterCannonItem extends AEBasePoweredItem implements IStorageCell<
}
try {
AppEng.proxy.sendToAllNearExcept(null, d0, d1, d2, 128, w,
AppEng.instance().sendToAllNearExcept(null, d0, d1, d2, 128, w,
new MatterCannonPacket(d0, d1, d2, (float) direction.x, (float) direction.y, (float) direction.z,
(byte) (pos.getType() == HitResult.Type.MISS ? 32
: pos.getPos().squaredDistanceTo(vec) + 1)));
@@ -265,7 +265,7 @@ public class MatterCannonItem extends AEBasePoweredItem implements IStorageCell<
}
final BlockState whatsThere = w.getBlockState(hitPos);
if (whatsThere.getMaterial().isReplaceable() && w.isAirBlock(hitPos)) {
if (whatsThere.getMaterial().isReplaceable() && w.isAir(hitPos)) {
AEApi.instance().definitions().blocks().paint().maybeBlock().ifPresent(paintBlock -> {
w.setBlockState(hitPos, paintBlock.getDefaultState(), 3);
});
@@ -335,7 +335,7 @@ public class MatterCannonItem extends AEBasePoweredItem implements IStorageCell<
}
try {
AppEng.proxy.sendToAllNearExcept(null, d0, d1, d2, 128, w,
AppEng.instance().sendToAllNearExcept(null, d0, d1, d2, 128, w,
new MatterCannonPacket(d0, d1, d2, (float) direction.x, (float) direction.y,
(float) direction.z, (byte) (pos.getType() == HitResult.Type.MISS ? 32
: pos.getPos().squaredDistanceTo(vec) + 1)));
@@ -1,377 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.me.helpers;
import java.util.Collections;
import java.util.EnumSet;
import com.mojang.authlib.GameProfile;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.math.Direction;
import appeng.api.AEApi;
import appeng.api.networking.GridFlags;
import appeng.api.networking.GridNotification;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridBlock;
import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.events.MENetworkPowerIdleChange;
import appeng.api.networking.pathing.IPathingGrid;
import appeng.api.networking.security.ISecurityGrid;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.networking.ticking.ITickManager;
import appeng.api.util.AEColor;
import appeng.api.util.DimensionalCoord;
import appeng.api.util.IOrientable;
import appeng.core.worlddata.WorldData;
import appeng.hooks.TickHandler;
import appeng.me.GridAccessException;
import appeng.me.cache.P2PCache;
import appeng.parts.networking.CablePart;
import appeng.tile.AEBaseBlockEntity;
import appeng.util.Platform;
public class AENetworkProxy implements IGridBlock {
private final IGridProxyable gp;
private final boolean worldNode;
private final String nbtName; // name
private AEColor myColor = AEColor.TRANSPARENT;
private CompoundTag data = null; // input
private ItemStack myRepInstance = ItemStack.EMPTY;
private boolean isReady = false;
private IGridNode node = null;
private EnumSet<Direction> validSides;
private EnumSet<GridFlags> flags = EnumSet.noneOf(GridFlags.class);
private double idleDraw = 1.0;
private PlayerEntity owner;
public AENetworkProxy(final IGridProxyable te, final String nbtName, final ItemStack visual,
final boolean inWorld) {
this.gp = te;
this.nbtName = nbtName;
this.worldNode = inWorld;
this.myRepInstance = visual;
this.validSides = EnumSet.allOf(Direction.class);
}
public void setVisualRepresentation(final ItemStack is) {
this.myRepInstance = is;
}
public void writeToNBT(final CompoundTag tag) {
if (this.node != null) {
this.node.saveToNBT(this.nbtName, tag);
}
}
public void setValidSides(final EnumSet<Direction> validSides) {
this.validSides = validSides;
if (this.node != null) {
this.node.updateState();
}
}
public void validate() {
if (this.gp instanceof AEBaseBlockEntity) {
TickHandler.INSTANCE.addInit((AEBaseBlockEntity) this.gp);
}
}
public void onChunkUnloaded() {
this.isReady = false;
this.remove();
}
public void remove() {
this.isReady = false;
if (this.node != null) {
this.node.destroy();
this.node = null;
}
}
public void onReady() {
this.isReady = true;
// send orientation based directionality to the node.
if (this.gp instanceof IOrientable) {
final IOrientable ori = (IOrientable) this.gp;
if (ori.canBeRotated()) {
ori.setOrientation(ori.getForward(), ori.getUp());
}
}
this.getNode();
}
public IGridNode getNode() {
if (this.node == null && Platform.isServer() && this.isReady) {
this.node = AEApi.instance().grid().createGridNode(this);
this.readFromNBT(this.data);
this.node.updateState();
}
return this.node;
}
public void readFromNBT(final CompoundTag tag) {
this.data = tag;
if (this.node != null && this.data != null) {
this.node.loadFromNBT(this.nbtName, this.data);
this.data = null;
} else if (this.node != null && this.owner != null) {
final GameProfile profile = this.owner.getGameProfile();
final int playerID = WorldData.instance().playerData().getMePlayerId(profile);
this.node.setPlayerID(playerID);
this.owner = null;
}
}
public IPathingGrid getPath() throws GridAccessException {
final IGrid grid = this.getGrid();
if (grid == null) {
throw new GridAccessException();
}
final IPathingGrid pg = grid.getCache(IPathingGrid.class);
if (pg == null) {
throw new GridAccessException();
}
return pg;
}
/**
* short cut!
*
* @return grid of node
*
* @throws GridAccessException of node or grid is null
*/
public IGrid getGrid() throws GridAccessException {
if (this.node == null) {
throw new GridAccessException();
}
final IGrid grid = this.node.getGrid();
if (grid == null) {
throw new GridAccessException();
}
return grid;
}
public ITickManager getTick() throws GridAccessException {
final IGrid grid = this.getGrid();
if (grid == null) {
throw new GridAccessException();
}
final ITickManager pg = grid.getCache(ITickManager.class);
if (pg == null) {
throw new GridAccessException();
}
return pg;
}
public IStorageGrid getStorage() throws GridAccessException {
final IGrid grid = this.getGrid();
if (grid == null) {
throw new GridAccessException();
}
final IStorageGrid pg = grid.getCache(IStorageGrid.class);
if (pg == null) {
throw new GridAccessException();
}
return pg;
}
public P2PCache getP2P() throws GridAccessException {
final IGrid grid = this.getGrid();
if (grid == null) {
throw new GridAccessException();
}
final P2PCache pg = grid.getCache(P2PCache.class);
if (pg == null) {
throw new GridAccessException();
}
return pg;
}
public ISecurityGrid getSecurity() throws GridAccessException {
final IGrid grid = this.getGrid();
if (grid == null) {
throw new GridAccessException();
}
final ISecurityGrid sg = grid.getCache(ISecurityGrid.class);
if (sg == null) {
throw new GridAccessException();
}
return sg;
}
public ICraftingGrid getCrafting() throws GridAccessException {
final IGrid grid = this.getGrid();
if (grid == null) {
throw new GridAccessException();
}
final ICraftingGrid sg = grid.getCache(ICraftingGrid.class);
if (sg == null) {
throw new GridAccessException();
}
return sg;
}
@Override
public double getIdlePowerUsage() {
return this.idleDraw;
}
@Override
public EnumSet<GridFlags> getFlags() {
return this.flags;
}
@Override
public boolean isWorldAccessible() {
return this.worldNode;
}
@Override
public DimensionalCoord getLocation() {
return this.gp.getLocation();
}
@Override
public AEColor getGridColor() {
return this.getColor();
}
@Override
public void onGridNotification(final GridNotification notification) {
if (this.gp instanceof CablePart) {
((CablePart) this.gp).markForUpdate();
}
}
@Override
public void setNetworkStatus(final IGrid grid, final int channelsInUse) {
}
@Override
public EnumSet<Direction> getConnectableSides() {
return this.validSides;
}
@Override
public IGridHost getMachine() {
return this.gp;
}
@Override
public void gridChanged() {
this.gp.gridChanged();
}
@Override
public ItemStack getMachineRepresentation() {
return this.myRepInstance;
}
public void setFlags(final GridFlags... requireChannel) {
final EnumSet<GridFlags> flags = EnumSet.noneOf(GridFlags.class);
Collections.addAll(flags, requireChannel);
this.flags = flags;
}
public void setIdlePowerUsage(final double idle) {
this.idleDraw = idle;
if (this.node != null) {
try {
final IGrid g = this.getGrid();
g.postEvent(new MENetworkPowerIdleChange(this.node));
} catch (final GridAccessException e) {
// not ready for this yet..
}
}
}
public boolean isReady() {
return this.isReady;
}
public boolean isActive() {
if (this.node == null) {
return false;
}
return this.node.isActive();
}
public boolean isPowered() {
try {
return this.getEnergy().isNetworkPowered();
} catch (final GridAccessException e) {
return false;
}
}
public IEnergyGrid getEnergy() throws GridAccessException {
final IGrid grid = this.getGrid();
if (grid == null) {
throw new GridAccessException();
}
final IEnergyGrid eg = grid.getCache(IEnergyGrid.class);
if (eg == null) {
throw new GridAccessException();
}
return eg;
}
public void setOwner(final PlayerEntity player) {
this.owner = player;
}
public AEColor getColor() {
return this.myColor;
}
public void setColor(final AEColor myColor) {
this.myColor = myColor;
}
}
-457
View File
@@ -1,457 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts;
import java.io.IOException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import com.google.common.base.Preconditions;
import net.fabricmc.api.EnvType;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.crash.CrashReportSection;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.text.Text;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.fabricmc.api.Environment;
import alexiil.mc.lib.attributes.item.FixedItemInv;
import appeng.api.AEApi;
import appeng.api.config.Upgrades;
import appeng.api.definitions.IDefinitions;
import appeng.api.implementations.IUpgradeableHost;
import appeng.api.implementations.items.IMemoryCard;
import appeng.api.implementations.items.MemoryCardMessages;
import appeng.api.networking.IGridNode;
import appeng.api.networking.security.IActionHost;
import appeng.api.parts.BusSupport;
import appeng.api.parts.IPart;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.parts.IPartHost;
import appeng.api.parts.PartItemStack;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import appeng.api.util.AEPartLocation;
import appeng.api.util.DimensionalCoord;
import appeng.api.util.IConfigManager;
import appeng.helpers.ICustomNameObject;
import appeng.helpers.IPriorityHost;
import appeng.me.helpers.AENetworkProxy;
import appeng.me.helpers.IGridProxyable;
import appeng.parts.networking.CablePart;
import appeng.tile.inventory.AppEngInternalAEInventory;
import appeng.util.Platform;
import appeng.util.SettingsFrom;
public abstract class AEBasePart implements IPart, IGridProxyable, IActionHost, IUpgradeableHost, ICustomNameObject {
private final AENetworkProxy proxy;
private final ItemStack is;
private BlockEntity tile = null;
private IPartHost host = null;
private AEPartLocation side = null;
public AEBasePart(final ItemStack is) {
Preconditions.checkNotNull(is);
this.is = is;
this.proxy = new AENetworkProxy(this, "part", is, this instanceof CablePart);
this.proxy.setValidSides(EnumSet.noneOf(Direction.class));
}
public IPartHost getHost() {
return this.host;
}
@Override
public IGridNode getGridNode(final AEPartLocation dir) {
return this.proxy.getNode();
}
@Override
public AECableType getCableConnectionType(final AEPartLocation dir) {
return AECableType.GLASS;
}
@Override
public void securityBreak() {
if (this.getItemStack().getCount() > 0 && this.getGridNode() != null) {
final List<ItemStack> items = new ArrayList<>();
items.add(this.is.copy());
this.host.removePart(this.side, false);
Platform.spawnDrops(this.tile.getWorld(), this.tile.getPos(), items);
this.is.setCount(0);
}
}
protected AEColor getColor() {
if (this.host == null) {
return AEColor.TRANSPARENT;
}
return this.host.getColor();
}
@Override
public void getBoxes(final IPartCollisionHelper bch) {
}
@Override
public int getInstalledUpgrades(final Upgrades u) {
return 0;
}
@Override
public BlockEntity getTile() {
return this.tile;
}
@Override
public AENetworkProxy getProxy() {
return this.proxy;
}
@Override
public DimensionalCoord getLocation() {
return new DimensionalCoord(this.tile);
}
@Override
public void gridChanged() {
}
@Override
public IGridNode getActionableNode() {
return this.proxy.getNode();
}
public void saveChanges() {
this.host.markForSave();
}
@Override
public Text getCustomInventoryName() {
return this.getItemStack().getName();
}
@Override
public boolean hasCustomInventoryName() {
return this.getItemStack().hasCustomName();
}
@Override
public void addEntityCrashInfo(final CrashReportSection section) {
section.add("Part Side", this.getSide());
}
@Override
public ItemStack getItemStack(final PartItemStack type) {
if (type == PartItemStack.NETWORK) {
final ItemStack copy = this.is.copy();
copy.setTag(null);
return copy;
}
return this.is;
}
@Override
public boolean isSolid() {
return false;
}
@Override
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
}
@Override
public boolean canConnectRedstone() {
return false;
}
@Override
public void readFromNBT(final CompoundTag data) {
this.proxy.readFromNBT(data);
}
@Override
public void writeToNBT(final CompoundTag data) {
this.proxy.writeToNBT(data);
}
@Override
public int isProvidingStrongPower() {
return 0;
}
@Override
public int isProvidingWeakPower() {
return 0;
}
@Override
public void writeToStream(final PacketByteBuf data) throws IOException {
}
@Override
public boolean readFromStream(final PacketByteBuf data) throws IOException {
return false;
}
@Override
public IGridNode getGridNode() {
return this.proxy.getNode();
}
@Override
public void onEntityCollision(final Entity entity) {
}
@Override
public void removeFromWorld() {
this.proxy.remove();
}
@Override
public void addToWorld() {
this.proxy.onReady();
}
@Override
public void setPartHostInfo(final AEPartLocation side, final IPartHost host, final BlockEntity tile) {
this.setSide(side);
this.tile = tile;
this.host = host;
}
@Override
public IGridNode getExternalFacingNode() {
return null;
}
@Override
@Environment(EnvType.CLIENT)
public void randomDisplayTick(final World world, final BlockPos pos, final Random r) {
}
@Override
public int getLightLevel() {
return 0;
}
@Override
public void getDrops(final List<ItemStack> drops, final boolean wrenched) {
}
@Override
public float getCableConnectionLength(AECableType cable) {
return 3;
}
@Override
public boolean isLadder(final LivingEntity entity) {
return false;
}
@Override
public IConfigManager getConfigManager() {
return null;
}
@Override
public FixedItemInv getInventoryByName(final String name) {
return null;
}
/**
* depending on the from, different settings will be accepted, don't call this
* with null
*
* @param from source of settings
* @param compound compound of source
*/
private void uploadSettings(final SettingsFrom from, final CompoundTag compound) {
if (compound != null) {
final IConfigManager cm = this.getConfigManager();
if (cm != null) {
cm.readFromNBT(compound);
}
}
if (this instanceof IPriorityHost) {
final IPriorityHost pHost = (IPriorityHost) this;
pHost.setPriority(compound.getInt("priority"));
}
final FixedItemInv inv = this.getInventoryByName("config");
if (inv instanceof AppEngInternalAEInventory) {
final AppEngInternalAEInventory target = (AppEngInternalAEInventory) inv;
final AppEngInternalAEInventory tmp = new AppEngInternalAEInventory(null, target.getSlotCount());
tmp.readFromNBT(compound, "config");
for (int x = 0; x < tmp.getSlotCount(); x++) {
target.setInvStack(x, tmp.getInvStack(x));
}
}
}
/**
* null means nothing to store...
*
* @param from source of settings
*
* @return compound of source
*/
private CompoundTag downloadSettings(final SettingsFrom from) {
final CompoundTag output = new CompoundTag();
final IConfigManager cm = this.getConfigManager();
if (cm != null) {
cm.writeToNBT(output);
}
if (this instanceof IPriorityHost) {
final IPriorityHost pHost = (IPriorityHost) this;
output.putInt("priority", pHost.getPriority());
}
final FixedItemInv inv = this.getInventoryByName("config");
if (inv instanceof AppEngInternalAEInventory) {
((AppEngInternalAEInventory) inv).writeToNBT(output, "config");
}
return output.isEmpty() ? null : output;
}
public boolean useStandardMemoryCard() {
return true;
}
private boolean useMemoryCard(final PlayerEntity player) {
final ItemStack memCardIS = player.inventory.getCurrentItem();
if (!memCardIS.isEmpty() && this.useStandardMemoryCard() && memCardIS.getItem() instanceof IMemoryCard) {
final IMemoryCard memoryCard = (IMemoryCard) memCardIS.getItem();
ItemStack is = this.getItemStack(PartItemStack.NETWORK);
// Blocks and parts share the same soul!
final IDefinitions definitions = AEApi.instance().definitions();
if (definitions.parts().iface().isSameAs(is)) {
Optional<ItemStack> iface = definitions.blocks().iface().maybeStack(1);
if (iface.isPresent()) {
is = iface.get();
}
}
final String name = is.getTranslationKey();
if (player.isInSneakingPose()) {
final CompoundTag data = this.downloadSettings(SettingsFrom.MEMORY_CARD);
if (data != null) {
memoryCard.setMemoryCardContents(memCardIS, name, data);
memoryCard.notifyUser(player, MemoryCardMessages.SETTINGS_SAVED);
}
} else {
final String storedName = memoryCard.getSettingsName(memCardIS);
final CompoundTag data = memoryCard.getData(memCardIS);
if (name.equals(storedName)) {
this.uploadSettings(SettingsFrom.MEMORY_CARD, data);
memoryCard.notifyUser(player, MemoryCardMessages.SETTINGS_LOADED);
} else {
memoryCard.notifyUser(player, MemoryCardMessages.INVALID_MACHINE);
}
}
return true;
}
return false;
}
@Override
public final boolean onActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
if (this.useMemoryCard(player)) {
return true;
}
return this.onPartActivate(player, hand, pos);
}
@Override
public final boolean onShiftActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
if (this.useMemoryCard(player)) {
return true;
}
return this.onPartShiftActivate(player, hand, pos);
}
public boolean onPartActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
return false;
}
public boolean onPartShiftActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
return false;
}
@Override
public void onPlacement(final PlayerEntity player, final Hand hand, final ItemStack held,
final AEPartLocation side) {
this.proxy.setOwner(player);
}
@Override
public boolean canBePlacedOn(final BusSupport what) {
return what == BusSupport.CABLE;
}
@Override
public boolean requireDynamicRender() {
return false;
}
public AEPartLocation getSide() {
return this.side;
}
private void setSide(final AEPartLocation side) {
this.side = side;
}
public ItemStack getItemStack() {
return this.is;
}
}
@@ -1,153 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts;
import java.util.List;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.util.AEPartLocation;
public class BusCollisionHelper implements IPartCollisionHelper {
private final List<Box> boxes;
private final Direction x;
private final Direction y;
private final Direction z;
private final boolean isVisual;
public BusCollisionHelper(final List<Box> boxes, final Direction x, final Direction y, final Direction z,
final boolean visual) {
this.boxes = boxes;
this.x = x;
this.y = y;
this.z = z;
this.isVisual = visual;
}
public BusCollisionHelper(final List<Box> boxes, final AEPartLocation s, final boolean visual) {
this.boxes = boxes;
this.isVisual = visual;
switch (s) {
case DOWN:
this.x = Direction.EAST;
this.y = Direction.NORTH;
this.z = Direction.DOWN;
break;
case UP:
this.x = Direction.EAST;
this.y = Direction.SOUTH;
this.z = Direction.UP;
break;
case EAST:
this.x = Direction.SOUTH;
this.y = Direction.UP;
this.z = Direction.EAST;
break;
case WEST:
this.x = Direction.NORTH;
this.y = Direction.UP;
this.z = Direction.WEST;
break;
case NORTH:
this.x = Direction.WEST;
this.y = Direction.UP;
this.z = Direction.NORTH;
break;
case SOUTH:
this.x = Direction.EAST;
this.y = Direction.UP;
this.z = Direction.SOUTH;
break;
case INTERNAL:
default:
this.x = Direction.EAST;
this.y = Direction.UP;
this.z = Direction.SOUTH;
break;
}
}
@Override
public void addBox(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
minX /= 16.0;
minY /= 16.0;
minZ /= 16.0;
maxX /= 16.0;
maxY /= 16.0;
maxZ /= 16.0;
double aX = minX * this.x.getOffsetX() + minY * this.y.getOffsetX() + minZ * this.z.getOffsetX();
double aY = minX * this.x.getOffsetY() + minY * this.y.getOffsetY() + minZ * this.z.getOffsetY();
double aZ = minX * this.x.getOffsetZ() + minY * this.y.getOffsetZ() + minZ * this.z.getOffsetZ();
double bX = maxX * this.x.getOffsetX() + maxY * this.y.getOffsetX() + maxZ * this.z.getOffsetX();
double bY = maxX * this.x.getOffsetY() + maxY * this.y.getOffsetY() + maxZ * this.z.getOffsetY();
double bZ = maxX * this.x.getOffsetZ() + maxY * this.y.getOffsetZ() + maxZ * this.z.getOffsetZ();
if (this.x.getOffsetX() + this.y.getOffsetX() + this.z.getOffsetX() < 0) {
aX += 1;
bX += 1;
}
if (this.x.getOffsetY() + this.y.getOffsetY() + this.z.getOffsetY() < 0) {
aY += 1;
bY += 1;
}
if (this.x.getOffsetZ() + this.y.getOffsetZ() + this.z.getOffsetZ() < 0) {
aZ += 1;
bZ += 1;
}
minX = Math.min(aX, bX);
minY = Math.min(aY, bY);
minZ = Math.min(aZ, bZ);
maxX = Math.max(aX, bX);
maxY = Math.max(aY, bY);
maxZ = Math.max(aZ, bZ);
this.boxes.add(new Box(minX, minY, minZ, maxX, maxY, maxZ));
}
@Override
public Direction getWorldX() {
return this.x;
}
@Override
public Direction getWorldY() {
return this.y;
}
@Override
public Direction getWorldZ() {
return this.z;
}
@Override
public boolean isBBCollision() {
return !this.isVisual;
}
}
File diff suppressed because it is too large Load Diff
@@ -1,121 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts;
import javax.annotation.Nullable;
import appeng.api.implementations.parts.ICablePart;
import appeng.api.parts.IFacadePart;
import appeng.api.parts.IPart;
import appeng.api.util.AEPartLocation;
/**
* Thin data storage to optimize memory usage for cables.
*/
public class CableBusStorage {
private ICablePart center;
private IPart[] sides;
private IFacadePart[] facades;
protected ICablePart getCenter() {
return this.center;
}
protected void setCenter(final ICablePart center) {
this.center = center;
}
protected IPart getSide(final AEPartLocation side) {
final int x = side.ordinal();
if (this.sides != null && this.sides.length > x) {
return this.sides[x];
}
return null;
}
protected void setSide(final AEPartLocation side, final IPart part) {
final int x = side.ordinal();
if (this.sides != null && this.sides.length > x && part == null) {
this.sides[x] = null;
this.sides = this.decrement(this.sides, true);
} else if (part != null) {
this.sides = this.expand(this.sides, x, true);
this.sides[x] = part;
}
}
private <T> T[] shrink(final T[] in, final boolean parts) {
int newSize = -1;
for (int x = 0; x < in.length; x++) {
if (in[x] != null) {
newSize = x;
}
}
if (newSize == -1) {
return null;
}
newSize++;
if (newSize == in.length) {
return in;
}
final T[] newArray = (T[]) (parts ? new IPart[newSize] : new IFacadePart[newSize]);
System.arraycopy(in, 0, newArray, 0, newSize);
return newArray;
}
private <T> T[] grow(final T[] in, final int newValue, final boolean parts) {
if (in != null && in.length > newValue) {
return in;
}
final int newSize = newValue + 1;
final T[] newArray = (T[]) (parts ? new IPart[newSize] : new IFacadePart[newSize]);
if (in != null) {
System.arraycopy(in, 0, newArray, 0, in.length);
}
return newArray;
}
public IFacadePart getFacade(final int x) {
if (this.facades != null && this.facades.length > x) {
return this.facades[x];
}
return null;
}
public void setFacade(final int x, @Nullable final IFacadePart facade) {
if (this.facades != null && this.facades.length > x && facade == null) {
this.facades[x] = null;
this.facades = this.decrement(this.facades, false);
} else {
this.facades = this.expand(this.facades, x, false);
this.facades[x] = facade;
}
}
}
@@ -1,71 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts;
import java.util.EnumSet;
import java.util.Random;
import net.fabricmc.api.EnvType;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.fabricmc.api.Environment;
import appeng.api.parts.SelectedPart;
import appeng.api.util.AEColor;
import appeng.client.render.cablebus.CableBusRenderState;
public interface ICableBusContainer {
int isProvidingStrongPower(Direction opposite);
int isProvidingWeakPower(Direction opposite);
boolean canConnectRedstone(EnumSet<Direction> of);
void onEntityCollision(Entity e);
boolean activate(PlayerEntity player, Hand hand, Vec3d vecFromPool);
boolean clicked(PlayerEntity player, Hand hand, Vec3d hitVec);
void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor);
boolean isEmpty();
SelectedPart selectPart(Vec3d v3);
boolean recolourBlock(Direction side, AEColor colour, PlayerEntity who);
boolean isLadder(LivingEntity entity);
@Environment(EnvType.CLIENT)
void randomDisplayTick(World world, BlockPos pos, Random r);
int getLightValue();
CableBusRenderState getRenderState();
}
@@ -1,110 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts;
import java.util.EnumSet;
import java.util.Random;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import appeng.api.parts.SelectedPart;
import appeng.api.util.AEColor;
import appeng.client.render.cablebus.CableBusRenderState;
public class NullCableBusContainer implements ICableBusContainer {
@Override
public int isProvidingStrongPower(final Direction opposite) {
return 0;
}
@Override
public int isProvidingWeakPower(final Direction opposite) {
return 0;
}
@Override
public boolean canConnectRedstone(final EnumSet<Direction> of) {
return false;
}
@Override
public void onEntityCollision(final Entity e) {
}
@Override
public boolean activate(final PlayerEntity player, final Hand hand, final Vec3d vecFromPool) {
return false;
}
@Override
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public SelectedPart selectPart(final Vec3d v3) {
return new SelectedPart();
}
@Override
public boolean recolourBlock(final Direction side, final AEColor colour, final PlayerEntity who) {
return false;
}
@Override
public boolean isLadder(final LivingEntity entity) {
return false;
}
@Override
public void randomDisplayTick(final World world, final BlockPos pos, final Random r) {
}
@Override
public int getLightValue() {
return 0;
}
@Override
public CableBusRenderState getRenderState() {
return new CableBusRenderState();
}
@Override
public boolean clicked(PlayerEntity player, Hand hand, Vec3d hitVec) {
return false;
}
}
-69
View File
@@ -1,69 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts;
import java.util.List;
import com.google.common.collect.ImmutableList;
import net.minecraft.util.Identifier;
import appeng.api.parts.IPartModel;
public class PartModel implements IPartModel {
private final boolean isSolid;
private final List<Identifier> resources;
public PartModel(Identifier resource) {
this(true, resource);
}
public PartModel(Identifier... resources) {
this(true, resources);
}
public PartModel(boolean isSolid, Identifier resource) {
this(isSolid, ImmutableList.of(resource));
}
public PartModel(boolean isSolid, Identifier... resources) {
this(isSolid, ImmutableList.copyOf(resources));
}
public PartModel(List<Identifier> resources) {
this(true, resources);
}
public PartModel(boolean isSolid, List<Identifier> resources) {
this.isSolid = isSolid;
this.resources = resources;
}
@Override
public boolean requireCableConnection() {
return this.isSolid;
}
@Override
public List<Identifier> getModels() {
return this.resources;
}
}
@@ -1,421 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.DirectionalPlaceContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.block.entity.BlockEntity;
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.sound.SoundCategory;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.RayTraceContext;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import appeng.api.AEApi;
import appeng.api.definitions.IBlockDefinition;
import appeng.api.definitions.IItems;
import appeng.api.parts.IFacadePart;
import appeng.api.parts.IPartHost;
import appeng.api.parts.IPartItem;
import appeng.api.parts.PartItemStack;
import appeng.api.parts.SelectedPart;
import appeng.api.util.AEPartLocation;
import appeng.api.util.DimensionalCoord;
import appeng.core.AppEng;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ClickPacket;
import appeng.core.sync.packets.PartPlacementPacket;
import appeng.facade.IFacadeItem;
import appeng.util.LookDirection;
import appeng.util.Platform;
public class PartPlacement {
private static float eyeHeight = 0.0f;
private final ThreadLocal<Object> placing = new ThreadLocal<>();
private boolean wasCanceled = false;
public static ActionResult place(final ItemStack held, final BlockPos pos, Direction side,
final PlayerEntity player, final Hand hand, final World world, PlaceType pass, final int depth) {
if (depth > 3) {
return ActionResult.FAIL;
}
// FIXME: This was changed alot.
final LookDirection dir = Platform.getPlayerRay(player);
RayTraceContext rtc = new RayTraceContext(dir.getA(), dir.getB(), RayTraceContext.ShapeType.OUTLINE,
RayTraceContext.FluidHandling.NONE, player);
final BlockHitResult mop = world.rayTrace(rtc);
ItemPlacementContext useContext = new ItemPlacementContext(new ItemUsageContext(player, hand, mop));
if (!held.isEmpty() && Platform.isWrench(player, held, pos) && player.isInSneakingPose()) {
if (!Platform.hasPermissions(new DimensionalCoord(world, pos), player)) {
return ActionResult.FAIL;
}
final BlockEntity tile = world.getBlockEntity(pos);
IPartHost host = null;
if (tile instanceof IPartHost) {
host = (IPartHost) tile;
}
if (host != null) {
if (!world.isClient) {
if (mop.getType() == HitResult.Type.BLOCK) {
final List<ItemStack> is = new ArrayList<>();
final SelectedPart sp = selectPart(player, host,
mop.getPos().add(-mop.getPos().getX(), -mop.getPos().getY(), -mop.getPos().getZ()));
if (sp.part != null) {
is.add(sp.part.getItemStack(PartItemStack.WRENCH));
sp.part.getDrops(is, true);
host.removePart(sp.side, false);
}
if (sp.facade != null) {
is.add(sp.facade.getItemStack());
host.getFacadeContainer().removeFacade(host, sp.side);
Platform.notifyBlocksOfNeighbors(world, pos);
}
if (host.isEmpty()) {
host.cleanup();
}
if (!is.isEmpty()) {
Platform.spawnDrops(world, pos, is);
}
}
} else {
player.swingHand(hand);
NetworkHandler.instance()
.sendToServer(new PartPlacementPacket(pos, side, getEyeOffset(player), hand));
}
return ActionResult.SUCCESS;
}
return ActionResult.FAIL;
}
BlockEntity tile = world.getBlockEntity(pos);
IPartHost host = null;
if (tile instanceof IPartHost) {
host = (IPartHost) tile;
}
if (!held.isEmpty()) {
final IFacadePart fp = isFacade(held, AEPartLocation.fromFacing(side));
if (fp != null) {
if (host != null) {
if (!world.isClient) {
if (host.getPart(AEPartLocation.INTERNAL) == null) {
return ActionResult.FAIL;
}
if (host.canAddPart(held, AEPartLocation.fromFacing(side))) {
if (host.getFacadeContainer().addFacade(fp)) {
host.markForSave();
host.markForUpdate();
if (!player.isCreative()) {
held.increment(-1);
;
if (held.getCount() == 0) {
player.inventory.mainInventory.set(player.inventory.currentItem,
ItemStack.EMPTY);
MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(player, held, hand));
}
}
return ActionResult.CONSUME;
}
}
} else {
player.swingHand(hand);
NetworkHandler.instance()
.sendToServer(new PartPlacementPacket(pos, side, getEyeOffset(player), hand));
return ActionResult.SUCCESS;
}
}
return ActionResult.FAIL;
}
}
if (held.isEmpty()) {
if (host != null && player.isInSneakingPose() && world.isAirBlock(pos)) {
if (mop.getType() == HitResult.Type.BLOCK) {
Vec3d hitVec = mop.getPos().add(-mop.getPos().getX(), -mop.getPos().getY(),
-mop.getPos().getZ());
final SelectedPart sPart = selectPart(player, host, hitVec);
if (sPart != null && sPart.part != null) {
if (sPart.part.onShiftActivate(player, hand, hitVec)) {
if (world.isClient) {
NetworkHandler.instance()
.sendToServer(new PartPlacementPacket(pos, side, getEyeOffset(player), hand));
}
return ActionResult.SUCCESS;
}
}
}
}
}
if (held.isEmpty() || !(held.getItem() instanceof IPartItem)) {
return ActionResult.PASS;
}
BlockPos te_pos = pos;
final IBlockDefinition multiPart = AEApi.instance().definitions().blocks().multiPart();
if (host == null && pass == PlaceType.PLACE_ITEM) {
Direction offset = null;
BlockState blockState = world.getBlockState(pos);
// FIXME isReplacable on the block state allows for more control, but requires
// an item use context
if (!blockState.isAir(world, pos) && !blockState.isReplaceable(useContext)) {
offset = side;
if (Platform.isServer()) {
side = side.getOpposite();
}
}
te_pos = offset == null ? pos : pos.offset(offset);
tile = world.getBlockEntity(te_pos);
if (tile instanceof IPartHost) {
host = (IPartHost) tile;
}
final Optional<ItemStack> maybeMultiPartStack = multiPart.maybeStack(1);
final Optional<Block> maybeMultiPartBlock = multiPart.maybeBlock();
final Optional<BlockItem> maybeMultiPartBlockItem = multiPart.maybeBlockItem();
final boolean hostIsNotPresent = host == null;
final boolean multiPartPresent = maybeMultiPartBlock.isPresent() && maybeMultiPartStack.isPresent()
&& maybeMultiPartBlockItem.isPresent();
BlockState multiPartBlockState = maybeMultiPartBlock.get().getDefaultState();
final boolean canMultiPartBePlaced = multiPartBlockState.canPlaceAt(world, te_pos);
// We cannot override the item stack of normal use context, so we use this hack
ItemPlacementContext mpUseCtx = new ItemPlacementContext(
new DirectionalPlaceContext(world, te_pos, side, maybeMultiPartStack.get(), side));
// FIXME: This is super-fishy and all needs to be re-checked. what does this
// even do???
if (hostIsNotPresent && multiPartPresent && canMultiPartBePlaced
&& maybeMultiPartBlockItem.get().place(mpUseCtx) == ActionResult.SUCCESS) {
if (!world.isClient) {
tile = world.getBlockEntity(te_pos);
if (tile instanceof IPartHost) {
host = (IPartHost) tile;
}
pass = PlaceType.INTERACT_SECOND_PASS;
} else {
player.swingHand(hand);
NetworkHandler.instance()
.sendToServer(new PartPlacementPacket(pos, side, getEyeOffset(player), hand));
return ActionResult.SUCCESS;
}
} else if (host != null && !host.canAddPart(held, AEPartLocation.fromFacing(side))) {
return ActionResult.FAIL;
}
}
if (host == null) {
return ActionResult.PASS;
}
if (!host.canAddPart(held, AEPartLocation.fromFacing(side))) {
if (pass == PlaceType.INTERACT_FIRST_PASS || pass == PlaceType.PLACE_ITEM) {
te_pos = pos.offset(side);
final BlockState blkState = world.getBlockState(te_pos);
// FIXME: this is always true (host was de-referenced above)
if (blkState.isAir(world, te_pos) || blkState.isReplaceable(useContext) || host != null) {
return place(held, te_pos, side.getOpposite(), player, hand, world,
pass == PlaceType.INTERACT_FIRST_PASS ? PlaceType.INTERACT_SECOND_PASS
: PlaceType.PLACE_ITEM,
depth + 1);
}
}
return ActionResult.PASS;
}
if (!world.isClient) {
if (mop.getType() != HitResult.Type.MISS) {
final SelectedPart sp = selectPart(player, host,
mop.getPos().add(-mop.getPos().getX(), -mop.getPos().getY(), -mop.getPos().getZ()));
if (sp.part != null) {
if (!player.isInSneakingPose() && sp.part.onActivate(player, hand, mop.getPos())) {
return ActionResult.FAIL;
}
}
}
final DimensionalCoord dc = host.getLocation();
if (!Platform.hasPermissions(dc, player)) {
return ActionResult.FAIL;
}
final AEPartLocation mySide = host.addPart(held, AEPartLocation.fromFacing(side), player, hand);
if (mySide != null) {
multiPart.maybeBlock().ifPresent(multiPartBlock -> {
BlockState blockState = world.getBlockState(pos);
final BlockSoundGroup ss = multiPartBlock.getSoundType(blockState, world, pos, player);
world.playSound(null, pos, ss.getPlaceSound(), SoundCategory.BLOCKS, (ss.getVolume() + 1.0F) / 2.0F,
ss.getPitch() * 0.8F);
});
if (!player.isCreative()) {
held.increment(-1);
if (held.getCount() == 0) {
player.setStackInHand(hand, ItemStack.EMPTY);
MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(player, held, hand));
}
}
}
} else {
player.swingHand(hand);
}
return ActionResult.SUCCESS;
}
private static float getEyeOffset(final PlayerEntity p) {
if (p.world.isClient) {
return Platform.getEyeOffset(p);
}
return getEyeHeight();
}
private static SelectedPart selectPart(final PlayerEntity player, final IPartHost host, final Vec3d pos) {
AppEng.proxy.updateRenderMode(player);
final SelectedPart sp = host.selectPart(pos);
AppEng.proxy.updateRenderMode(null);
return sp;
}
public static IFacadePart isFacade(final ItemStack held, final AEPartLocation side) {
if (held.getItem() instanceof IFacadeItem) {
return ((IFacadeItem) held.getItem()).createPartFromItemStack(held, side);
}
return null;
}
@SubscribeEvent
public void playerInteract(final TickEvent.ClientTickEvent event) {
this.wasCanceled = false;
}
@SubscribeEvent
public void playerInteract(final PlayerInteractEvent event) {
// Only handle the main hand event
if (event.getHand() != Hand.MAIN_HAND) {
return;
}
if (event instanceof PlayerInteractEvent.RightClickEmpty && event.getPlayer().world.isClient) {
// re-check to see if this event was already channeled, cause these two events
// are really stupid...
final HitResult mop = Platform.rayTrace(event.getPlayer(), true, false);
final MinecraftClient mc = MinecraftClient.getInstance();
final float f = 1.0F;
final double d0 = mc.playerController.getBlockReachDistance();
final Vec3d vec3 = mc.getRenderViewEntity().getEyePosition(f);
if (mop instanceof BlockHitResult && mop.getPos().distanceTo(vec3) < d0) {
BlockHitResult brtr = (BlockHitResult) mop;
final World w = event.getEntity().world;
final BlockEntity te = w.getBlockEntity(brtr.getPos());
if (te instanceof IPartHost && this.wasCanceled) {
event.setCanceled(true);
}
} else {
final ItemStack held = event.getPlayer().getStackInHand(event.getHand());
final IItems items = AEApi.instance().definitions().items();
boolean supportedItem = items.memoryCard().isSameAs(held);
supportedItem |= items.colorApplicator().isSameAs(held);
if (event.getPlayer().isInSneakingPose() && !held.isEmpty() && supportedItem) {
NetworkHandler.instance().sendToServer(new ClickPacket(event.getHand()));
}
}
} else if (event instanceof PlayerInteractEvent.RightClickBlock && !event.getPlayer().world.isClient) {
if (this.placing.get() != null) {
return;
}
this.placing.set(event);
final ItemStack held = event.getPlayer().getStackInHand(event.getHand());
if (place(held, event.getPos(), event.getFace(), event.getPlayer(), event.getHand(),
event.getPlayer().world, PlaceType.INTERACT_FIRST_PASS, 0) == ActionResult.SUCCESS) {
event.setCanceled(true);
this.wasCanceled = true;
}
this.placing.set(null);
}
}
private static float getEyeHeight() {
return eyeHeight;
}
public static void setEyeHeight(final float eyeHeight) {
PartPlacement.eyeHeight = eyeHeight;
}
public enum PlaceType {
PLACE_ITEM, INTERACT_FIRST_PASS, INTERACT_SECOND_PASS
}
}
@@ -284,7 +284,7 @@ public class AnnihilationPlanePart extends BasicStatePart implements IGridTickab
final boolean changed = this.storeEntityItem(itemEntity);
if (changed) {
AppEng.proxy.sendToAllNearExcept(null, pos.getX(), pos.getY(), pos.getZ(), 64,
AppEng.instance().sendToAllNearExcept(null, pos.getX(), pos.getY(), pos.getZ(), 64,
this.getTile().getWorld(), new ItemTransitionEffectPacket(entity.getX(),
entity.getY(), entity.getZ(), this.getSide().getOpposite()));
}
@@ -444,7 +444,7 @@ public class AnnihilationPlanePart extends BasicStatePart implements IGridTickab
energy.extractAEPower(requiredPower, Actionable.MODULATE, PowerMultiplier.CONFIG);
AppEng.proxy.sendToAllNearExcept(null, pos.getX(), pos.getY(), pos.getZ(), 64, w,
AppEng.instance().sendToAllNearExcept(null, pos.getX(), pos.getY(), pos.getZ(), 64, w,
new BlockTransitionEffectPacket(pos, blockState, this.getSide().getOpposite(),
BlockTransitionEffectPacket.SoundMode.NONE));
}
@@ -620,7 +620,7 @@ public class AnnihilationPlanePart extends BasicStatePart implements IGridTickab
}
public static boolean isBlockBlacklisted(Block b) {
Tag<Block> tag = BlockTags.getCollection().getOrCreate(TAG_BLACKLIST);
Tag<Block> tag = BlockTags.getContainer().getOrCreate(TAG_BLACKLIST);
return b.isIn(tag);
}
@@ -32,7 +32,7 @@ import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.item.BlockItem;
import net.minecraft.item.DirectionalPlaceContext;
import net.minecraft.item.AutomaticItemPlacementContext;
import net.minecraft.item.FireworkRocketItem;
import net.minecraft.item.FireworkStarItem;
import net.minecraft.item.Item;
@@ -243,31 +243,31 @@ public class FormationPlanePart extends AbstractFormationPlanePart<IAEItemStack>
// Up or Down, Attempt 1??
if (side.xOffset == 0 && side.zOffset == 0) {
Worked = i.onItemUse(new DirectionalPlaceContext(w, placePos.offset(side.getFacing()),
Worked = i.onItemUse(new AutomaticItemPlacementContext(w, placePos.offset(side.getFacing()),
lookDirection, is, side.getFacing())) == ActionResult.SUCCESS;
}
// Up or Down, Attempt 2??
if (!Worked && side.xOffset == 0 && side.zOffset == 0) {
Worked = i.onItemUse(new DirectionalPlaceContext(w,
Worked = i.onItemUse(new AutomaticItemPlacementContext(w,
placePos.offset(side.getFacing().getOpposite()), lookDirection, is,
side.getFacing().getOpposite())) == ActionResult.SUCCESS;
}
// Horizontal, attempt 1??
if (!Worked && side.yOffset == 0) {
Worked = i.onItemUse(new DirectionalPlaceContext(w, placePos.offset(Direction.DOWN),
Worked = i.onItemUse(new AutomaticItemPlacementContext(w, placePos.offset(Direction.DOWN),
lookDirection, is, Direction.DOWN)) == ActionResult.SUCCESS;
}
if (!Worked) {
i.onItemUse(new DirectionalPlaceContext(w, placePos, lookDirection, is,
i.onItemUse(new AutomaticItemPlacementContext(w, placePos, lookDirection, is,
lookDirection.getOpposite()));
}
maxStorage -= is.getCount();
} else {
i.onItemUse(new DirectionalPlaceContext(w, placePos, lookDirection, is,
i.onItemUse(new AutomaticItemPlacementContext(w, placePos, lookDirection, is,
lookDirection.getOpposite()));
maxStorage -= is.getCount();
}
@@ -1,220 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts.misc;
import java.io.IOException;
import java.util.List;
import java.util.Random;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import appeng.api.networking.IGridNode;
import appeng.api.parts.BusSupport;
import appeng.api.parts.IPart;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.parts.IPartHost;
import appeng.api.parts.IPartModel;
import appeng.api.parts.PartItemStack;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
import appeng.core.AppEng;
import appeng.items.parts.PartModels;
import appeng.parts.PartModel;
public class CableAnchorPart implements IPart {
@PartModels
public static final PartModel DEFAULT_MODELS = new PartModel(false,
new Identifier(AppEng.MOD_ID, "part/cable_anchor"));
@PartModels
public static final PartModel FACADE_MODELS = new PartModel(false,
new Identifier(AppEng.MOD_ID, "part/cable_anchor_short"));
private ItemStack is = ItemStack.EMPTY;
private IPartHost host = null;
private AEPartLocation mySide = AEPartLocation.UP;
public CableAnchorPart(final ItemStack is) {
this.is = is;
}
@Override
public void getBoxes(final IPartCollisionHelper bch) {
if (this.host != null && this.host.getFacadeContainer().getFacade(this.mySide) != null) {
bch.addBox(7, 7, 10, 9, 9, 14);
} else {
bch.addBox(7, 7, 10, 9, 9, 16);
}
}
@Override
public ItemStack getItemStack(final PartItemStack wrenched) {
return this.is;
}
@Override
public boolean requireDynamicRender() {
return false;
}
@Override
public boolean isSolid() {
return false;
}
@Override
public boolean canConnectRedstone() {
return false;
}
@Override
public void writeToNBT(final CompoundTag data) {
}
@Override
public void readFromNBT(final CompoundTag data) {
}
@Override
public int getLightLevel() {
return 0;
}
@Override
public boolean isLadder(final LivingEntity entity) {
return this.mySide.yOffset == 0 && (entity.horizontalCollision || !entity.isOnGround());
}
@Override
public void onneighborUpdate(BlockView w, BlockPos pos, BlockPos neighbor) {
}
@Override
public int isProvidingStrongPower() {
return 0;
}
@Override
public int isProvidingWeakPower() {
return 0;
}
@Override
public void writeToStream(final PacketByteBuf data) throws IOException {
}
@Override
public boolean readFromStream(final PacketByteBuf data) throws IOException {
return false;
}
@Override
public IGridNode getGridNode() {
return null;
}
@Override
public void onEntityCollision(final Entity entity) {
}
@Override
public void removeFromWorld() {
}
@Override
public void addToWorld() {
}
@Override
public IGridNode getExternalFacingNode() {
return null;
}
@Override
public void setPartHostInfo(final AEPartLocation side, final IPartHost host, final BlockEntity tile) {
this.host = host;
this.mySide = side;
}
@Override
public boolean onActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
return false;
}
@Override
public boolean onShiftActivate(final PlayerEntity player, final Hand hand, final Vec3d pos) {
return false;
}
@Override
public void getDrops(final List<ItemStack> drops, final boolean wrenched) {
}
@Override
public float getCableConnectionLength(AECableType cable) {
return 0;
}
@Override
public void randomDisplayTick(final World world, final BlockPos pos, final Random r) {
}
@Override
public void onPlacement(final PlayerEntity player, final Hand hand, final ItemStack held,
final AEPartLocation side) {
}
@Override
public boolean canBePlacedOn(final BusSupport what) {
return what == BusSupport.CABLE || what == BusSupport.DENSE_CABLE;
}
@Override
public IPartModel getStaticModels() {
if (this.host != null && this.host.getFacadeContainer().getFacade(this.mySide) != null) {
return FACADE_MODELS;
} else {
return DEFAULT_MODELS;
}
}
}
@@ -1,355 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts.networking;
import java.io.IOException;
import java.util.EnumSet;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.Direction;
import appeng.api.AEApi;
import appeng.api.config.SecurityPermissions;
import appeng.api.definitions.IParts;
import appeng.api.implementations.parts.ICablePart;
import appeng.api.networking.GridFlags;
import appeng.api.networking.IGridConnection;
import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.parts.BusSupport;
import appeng.api.parts.IPart;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.parts.IPartHost;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import appeng.api.util.AEPartLocation;
import appeng.api.util.IReadOnlyCollection;
import appeng.items.parts.ColoredPartItem;
import appeng.me.GridAccessException;
import appeng.parts.AEBasePart;
import appeng.util.Platform;
public class CablePart extends AEBasePart implements ICablePart {
private final int[] channelsOnSide = { 0, 0, 0, 0, 0, 0 };
private EnumSet<AEPartLocation> connections = EnumSet.noneOf(AEPartLocation.class);
private boolean powered = false;
public CablePart(final ItemStack is) {
super(is);
this.getProxy().setFlags(GridFlags.PREFERRED);
this.getProxy().setIdlePowerUsage(0.0);
if (is.getItem() instanceof ColoredPartItem) {
ColoredPartItem<?> coloredPartItem = (ColoredPartItem<?>) is.getItem();
this.getProxy().setColor(coloredPartItem.getColor());
}
}
@Override
public BusSupport supportsBuses() {
return BusSupport.CABLE;
}
@Override
public AEColor getCableColor() {
return this.getProxy().getColor();
}
@Override
public AECableType getCableConnectionType() {
return AECableType.GLASS;
}
@Override
public float getCableConnectionLength(AECableType cable) {
if (cable == this.getCableConnectionType()) {
return 4;
} else if (cable.ordinal() >= this.getCableConnectionType().ordinal()) {
return -1;
} else {
return 8;
}
}
@Override
public boolean changeColor(final AEColor newColor, final PlayerEntity who) {
if (this.getCableColor() != newColor) {
ItemStack newPart = null;
final IParts parts = AEApi.instance().definitions().parts();
if (this.getCableConnectionType() == AECableType.GLASS) {
newPart = parts.cableGlass().stack(newColor, 1);
} else if (this.getCableConnectionType() == AECableType.COVERED) {
newPart = parts.cableCovered().stack(newColor, 1);
} else if (this.getCableConnectionType() == AECableType.SMART) {
newPart = parts.cableSmart().stack(newColor, 1);
} else if (this.getCableConnectionType() == AECableType.DENSE_COVERED) {
newPart = parts.cableDenseCovered().stack(newColor, 1);
} else if (this.getCableConnectionType() == AECableType.DENSE_SMART) {
newPart = parts.cableDenseSmart().stack(newColor, 1);
}
boolean hasPermission = true;
try {
hasPermission = this.getProxy().getSecurity().hasPermission(who, SecurityPermissions.BUILD);
} catch (final GridAccessException e) {
// :P
}
if (newPart != null && hasPermission) {
if (Platform.isClient()) {
return true;
}
this.getHost().removePart(AEPartLocation.INTERNAL, true);
this.getHost().addPart(newPart, AEPartLocation.INTERNAL, who, null);
return true;
}
}
return false;
}
@Override
public void setValidSides(final EnumSet<Direction> sides) {
this.getProxy().setValidSides(sides);
}
@Override
public boolean isConnected(final Direction side) {
return this.getConnections().contains(AEPartLocation.fromFacing(side));
}
public void markForUpdate() {
this.getHost().markForUpdate();
}
@Override
public void getBoxes(final IPartCollisionHelper bch) {
bch.addBox(6.0, 6.0, 6.0, 10.0, 10.0, 10.0);
if (Platform.isServer()) {
final IGridNode n = this.getGridNode();
if (n != null) {
this.setConnections(n.getConnectedSides());
} else {
this.getConnections().clear();
}
}
final IPartHost ph = this.getHost();
if (ph != null) {
for (final AEPartLocation dir : AEPartLocation.SIDE_LOCATIONS) {
final IPart p = ph.getPart(dir);
if (p instanceof IGridHost) {
final double dist = p.getCableConnectionLength(this.getCableConnectionType());
if (dist > 8) {
continue;
}
switch (dir) {
case DOWN:
bch.addBox(6.0, dist, 6.0, 10.0, 6.0, 10.0);
break;
case EAST:
bch.addBox(10.0, 6.0, 6.0, 16.0 - dist, 10.0, 10.0);
break;
case NORTH:
bch.addBox(6.0, 6.0, dist, 10.0, 10.0, 6.0);
break;
case SOUTH:
bch.addBox(6.0, 6.0, 10.0, 10.0, 10.0, 16.0 - dist);
break;
case UP:
bch.addBox(6.0, 10.0, 6.0, 10.0, 16.0 - dist, 10.0);
break;
case WEST:
bch.addBox(dist, 6.0, 6.0, 6.0, 10.0, 10.0);
break;
default:
}
}
}
}
for (final AEPartLocation of : this.getConnections()) {
switch (of) {
case DOWN:
bch.addBox(6.0, 0.0, 6.0, 10.0, 6.0, 10.0);
break;
case EAST:
bch.addBox(10.0, 6.0, 6.0, 16.0, 10.0, 10.0);
break;
case NORTH:
bch.addBox(6.0, 6.0, 0.0, 10.0, 10.0, 6.0);
break;
case SOUTH:
bch.addBox(6.0, 6.0, 10.0, 10.0, 10.0, 16.0);
break;
case UP:
bch.addBox(6.0, 10.0, 6.0, 10.0, 16.0, 10.0);
break;
case WEST:
bch.addBox(0.0, 6.0, 6.0, 6.0, 10.0, 10.0);
break;
default:
}
}
}
@Override
public void writeToNBT(final CompoundTag data) {
super.writeToNBT(data);
if (Platform.isServer()) {
final IGridNode node = this.getGridNode();
if (node != null) {
int howMany = 0;
for (final IGridConnection gc : node.getConnections()) {
howMany = Math.max(gc.getUsedChannels(), howMany);
}
data.putByte("usedChannels", (byte) howMany);
}
}
}
@Override
public void writeToStream(final PacketByteBuf data) throws IOException {
int flags = 0;
boolean[] writeSide = new boolean[Direction.values().length];
int[] channelsPerSide = new int[Direction.values().length];
for (Direction thisSide : Direction.values()) {
final IPart part = this.getHost().getPart(thisSide);
if (part != null) {
writeSide[thisSide.ordinal()] = true;
int channels = 0;
if (part.getGridNode() != null) {
final IReadOnlyCollection<IGridConnection> set = part.getGridNode().getConnections();
for (final IGridConnection gc : set) {
channels = Math.max(channels, gc.getUsedChannels());
}
}
channelsPerSide[thisSide.ordinal()] = channels;
}
}
IGridNode n = this.getGridNode();
if (n != null) {
for (final IGridConnection gc : n.getConnections()) {
final AEPartLocation side = gc.getDirection(n);
if (side != AEPartLocation.INTERNAL) {
writeSide[side.ordinal()] = true;
channelsPerSide[side.ordinal()] = gc.getUsedChannels();
flags |= (1 << side.ordinal());
}
}
}
try {
if (this.getProxy().getEnergy().isNetworkPowered()) {
flags |= (1 << AEPartLocation.INTERNAL.ordinal());
}
} catch (final GridAccessException e) {
// aww...
}
data.writeByte((byte) flags);
// Only write the used channels for sides where we have a part or another cable
for (int i = 0; i < writeSide.length; i++) {
if (writeSide[i]) {
data.writeByte(channelsPerSide[i]);
}
}
}
@Override
public boolean readFromStream(final PacketByteBuf data) throws IOException {
int cs = data.readByte();
final EnumSet<AEPartLocation> myC = this.getConnections().clone();
final boolean wasPowered = this.powered;
this.powered = false;
boolean channelsChanged = false;
for (final AEPartLocation d : AEPartLocation.values()) {
if (d == AEPartLocation.INTERNAL) {
final int id = 1 << d.ordinal();
if (id == (cs & id)) {
this.powered = true;
}
} else {
boolean conOnSide = (cs & (1 << d.ordinal())) != 0;
if (conOnSide) {
this.getConnections().add(d);
} else {
this.getConnections().remove(d);
}
int ch = 0;
// Only read channels if there's a part on this side or a cable connection
// This works only because cables are always read *last* from the packet update
// for
// a cable bus
if (conOnSide || this.getHost().getPart(d) != null) {
ch = (data.readByte()) & 0xFF;
}
if (ch != this.getChannelsOnSide(d.ordinal())) {
channelsChanged = true;
this.setChannelsOnSide(d.ordinal(), ch);
}
}
}
return !myC.equals(this.getConnections()) || wasPowered != this.powered || channelsChanged;
}
int getChannelsOnSide(final int i) {
return this.channelsOnSide[i];
}
public int getChannelsOnSide(Direction side) {
if (!this.powered) {
return 0;
}
return this.channelsOnSide[side.ordinal()];
}
void setChannelsOnSide(final int i, final int channels) {
this.channelsOnSide[i] = channels;
}
EnumSet<AEPartLocation> getConnections() {
return this.connections;
}
void setConnections(final EnumSet<AEPartLocation> connections) {
this.connections = connections;
}
}
@@ -1,91 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts.networking;
import net.minecraft.item.ItemStack;
import appeng.api.networking.IGridNode;
import appeng.api.networking.events.MENetworkChannelsChanged;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
import appeng.helpers.Reflected;
import appeng.util.Platform;
public class CoveredCablePart extends CablePart {
@Reflected
public CoveredCablePart(final ItemStack is) {
super(is);
}
@MENetworkEventSubscribe
public void channelUpdated(final MENetworkChannelsChanged c) {
this.getHost().markForUpdate();
}
@MENetworkEventSubscribe
public void powerRender(final MENetworkPowerStatusChange c) {
this.getHost().markForUpdate();
}
@Override
public AECableType getCableConnectionType() {
return AECableType.COVERED;
}
@Override
public void getBoxes(final IPartCollisionHelper bch) {
bch.addBox(5.0, 5.0, 5.0, 11.0, 11.0, 11.0);
if (Platform.isServer()) {
final IGridNode n = this.getGridNode();
if (n != null) {
this.setConnections(n.getConnectedSides());
} else {
this.getConnections().clear();
}
}
for (final AEPartLocation of : this.getConnections()) {
switch (of) {
case DOWN:
bch.addBox(5.0, 0.0, 5.0, 11.0, 5.0, 11.0);
break;
case EAST:
bch.addBox(11.0, 5.0, 5.0, 16.0, 11.0, 11.0);
break;
case NORTH:
bch.addBox(5.0, 5.0, 0.0, 11.0, 11.0, 5.0);
break;
case SOUTH:
bch.addBox(5.0, 5.0, 11.0, 11.0, 11.0, 16.0);
break;
case UP:
bch.addBox(5.0, 11.0, 5.0, 11.0, 16.0, 11.0);
break;
case WEST:
bch.addBox(0.0, 5.0, 5.0, 5.0, 11.0, 11.0);
break;
default:
}
}
}
}
@@ -1,36 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts.networking;
import net.minecraft.item.ItemStack;
import appeng.api.util.AECableType;
public class CoveredDenseCablePart extends DenseCablePart {
public CoveredDenseCablePart(ItemStack is) {
super(is);
}
@Override
public AECableType getCableConnectionType() {
return AECableType.DENSE_COVERED;
}
}
@@ -1,136 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts.networking;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.item.ItemStack;
import appeng.api.networking.GridFlags;
import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.networking.events.MENetworkChannelsChanged;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange;
import appeng.api.parts.BusSupport;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
import appeng.helpers.Reflected;
import appeng.util.Platform;
public abstract class DenseCablePart extends CablePart {
@Reflected
public DenseCablePart(final ItemStack is) {
super(is);
this.getProxy().setFlags(GridFlags.DENSE_CAPACITY, GridFlags.PREFERRED);
}
@Override
public BusSupport supportsBuses() {
return BusSupport.DENSE_CABLE;
}
@Override
public void getBoxes(final IPartCollisionHelper bch) {
final boolean noLadder = !bch.isBBCollision();
final double min = noLadder ? 3.0 : 4.9;
final double max = noLadder ? 13.0 : 11.1;
bch.addBox(min, min, min, max, max, max);
if (Platform.isServer()) {
final IGridNode n = this.getGridNode();
if (n != null) {
this.setConnections(n.getConnectedSides());
} else {
this.getConnections().clear();
}
}
for (final AEPartLocation of : this.getConnections()) {
if (this.isDense(of)) {
switch (of) {
case DOWN:
bch.addBox(min, 0.0, min, max, min, max);
break;
case EAST:
bch.addBox(max, min, min, 16.0, max, max);
break;
case NORTH:
bch.addBox(min, min, 0.0, max, max, min);
break;
case SOUTH:
bch.addBox(min, min, max, max, max, 16.0);
break;
case UP:
bch.addBox(min, max, min, max, 16.0, max);
break;
case WEST:
bch.addBox(0.0, min, min, min, max, max);
break;
default:
}
} else {
switch (of) {
case DOWN:
bch.addBox(5.0, 0.0, 5.0, 11.0, 5.0, 11.0);
break;
case EAST:
bch.addBox(11.0, 5.0, 5.0, 16.0, 11.0, 11.0);
break;
case NORTH:
bch.addBox(5.0, 5.0, 0.0, 11.0, 11.0, 5.0);
break;
case SOUTH:
bch.addBox(5.0, 5.0, 11.0, 11.0, 11.0, 16.0);
break;
case UP:
bch.addBox(5.0, 11.0, 5.0, 11.0, 16.0, 11.0);
break;
case WEST:
bch.addBox(0.0, 5.0, 5.0, 5.0, 11.0, 11.0);
break;
default:
}
}
}
}
private boolean isDense(final AEPartLocation of) {
final BlockEntity te = this.getTile().getWorld().getBlockEntity(this.getTile().getPos().offset(of.getFacing()));
if (te instanceof IGridHost) {
final AECableType t = ((IGridHost) te).getCableConnectionType(of.getOpposite());
return t.isDense();
}
return false;
}
@MENetworkEventSubscribe
public void channelUpdated(final MENetworkChannelsChanged c) {
this.getHost().markForUpdate();
}
@MENetworkEventSubscribe
public void powerRender(final MENetworkPowerStatusChange c) {
this.getHost().markForUpdate();
}
}
@@ -1,30 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts.networking;
import net.minecraft.item.ItemStack;
import appeng.helpers.Reflected;
public class GlassCablePart extends CablePart {
@Reflected
public GlassCablePart(final ItemStack is) {
super(is);
}
}
@@ -1,174 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts.networking;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import appeng.api.config.Actionable;
import appeng.api.networking.GridFlags;
import appeng.api.networking.IGridNode;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.energy.IEnergyGridProvider;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.parts.IPartHost;
import appeng.api.parts.IPartModel;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
import appeng.core.AppEng;
import appeng.items.parts.PartModels;
import appeng.me.GridAccessException;
import appeng.me.helpers.AENetworkProxy;
import appeng.parts.AEBasePart;
import appeng.parts.PartModel;
public class QuartzFiberPart extends AEBasePart implements IEnergyGridProvider {
@PartModels
private static final IPartModel MODELS = new PartModel(new Identifier(AppEng.MOD_ID, "part/quartz_fiber"));
private final AENetworkProxy outerProxy = new AENetworkProxy(this, "outer",
this.getProxy().getMachineRepresentation(), true);
public QuartzFiberPart(final ItemStack is) {
super(is);
this.getProxy().setIdlePowerUsage(0);
this.getProxy().setFlags(GridFlags.CANNOT_CARRY);
this.outerProxy.setIdlePowerUsage(0);
this.outerProxy.setFlags(GridFlags.CANNOT_CARRY);
}
@Override
public AECableType getCableConnectionType(final AEPartLocation dir) {
return AECableType.GLASS;
}
@Override
public void getBoxes(final IPartCollisionHelper bch) {
bch.addBox(6, 6, 10, 10, 10, 16);
}
@Override
public void readFromNBT(final CompoundTag extra) {
super.readFromNBT(extra);
this.outerProxy.readFromNBT(extra);
}
@Override
public void writeToNBT(final CompoundTag extra) {
super.writeToNBT(extra);
this.outerProxy.writeToNBT(extra);
}
@Override
public void removeFromWorld() {
super.removeFromWorld();
this.outerProxy.remove();
}
@Override
public void addToWorld() {
super.addToWorld();
this.outerProxy.onReady();
}
@Override
public void setPartHostInfo(final AEPartLocation side, final IPartHost host, final BlockEntity tile) {
super.setPartHostInfo(side, host, tile);
this.outerProxy.setValidSides(EnumSet.of(side.getFacing()));
}
@Override
public IGridNode getExternalFacingNode() {
return this.outerProxy.getNode();
}
@Override
public float getCableConnectionLength(AECableType cable) {
return 16;
}
@Override
public void onPlacement(final PlayerEntity player, final Hand hand, final ItemStack held,
final AEPartLocation side) {
super.onPlacement(player, hand, held, side);
this.outerProxy.setOwner(player);
}
@Override
public Collection<IEnergyGridProvider> providers() {
Collection<IEnergyGridProvider> providers = new ArrayList<>();
try {
final IEnergyGrid eg = this.getProxy().getEnergy();
providers.add(eg);
} catch (final GridAccessException e) {
// :P
}
try {
final IEnergyGrid eg = this.outerProxy.getEnergy();
providers.add(eg);
} catch (final GridAccessException e) {
// :P
}
return providers;
}
@Override
public double extractProviderPower(final double amt, final Actionable mode) {
return 0;
}
@Override
public double injectProviderPower(final double amt, final Actionable mode) {
return amt;
}
@Override
public double getProviderEnergyDemand(final double amt) {
return 0;
}
@Override
public double getProviderStoredEnergy() {
return 0;
}
@Override
public double getProviderMaxEnergy() {
return 0;
}
@Override
public IPartModel getStaticModels() {
return MODELS;
}
}
@@ -1,91 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts.networking;
import net.minecraft.item.ItemStack;
import appeng.api.networking.IGridNode;
import appeng.api.networking.events.MENetworkChannelsChanged;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
import appeng.helpers.Reflected;
import appeng.util.Platform;
public class SmartCablePart extends CablePart {
@Reflected
public SmartCablePart(final ItemStack is) {
super(is);
}
@MENetworkEventSubscribe
public void channelUpdated(final MENetworkChannelsChanged c) {
this.getHost().markForUpdate();
}
@MENetworkEventSubscribe
public void powerRender(final MENetworkPowerStatusChange c) {
this.getHost().markForUpdate();
}
@Override
public AECableType getCableConnectionType() {
return AECableType.SMART;
}
@Override
public void getBoxes(final IPartCollisionHelper bch) {
bch.addBox(5.0, 5.0, 5.0, 11.0, 11.0, 11.0);
if (Platform.isServer()) {
final IGridNode n = this.getGridNode();
if (n != null) {
this.setConnections(n.getConnectedSides());
} else {
this.getConnections().clear();
}
}
for (final AEPartLocation of : this.getConnections()) {
switch (of) {
case DOWN:
bch.addBox(5.0, 0.0, 5.0, 11.0, 5.0, 11.0);
break;
case EAST:
bch.addBox(11.0, 5.0, 5.0, 16.0, 11.0, 11.0);
break;
case NORTH:
bch.addBox(5.0, 5.0, 0.0, 11.0, 11.0, 5.0);
break;
case SOUTH:
bch.addBox(5.0, 5.0, 11.0, 11.0, 11.0, 16.0);
break;
case UP:
bch.addBox(5.0, 11.0, 5.0, 11.0, 16.0, 11.0);
break;
case WEST:
bch.addBox(0.0, 5.0, 5.0, 5.0, 11.0, 11.0);
break;
default:
}
}
}
}
@@ -1,35 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.parts.networking;
import net.minecraft.item.ItemStack;
import appeng.api.util.AECableType;
public class SmartDenseCablePart extends DenseCablePart {
public SmartDenseCablePart(ItemStack is) {
super(is);
}
@Override
public AECableType getCableConnectionType() {
return AECableType.DENSE_SMART;
}
}
@@ -47,7 +47,6 @@ import appeng.util.Platform;
public class ServerHelper extends CommonHelper {
private PlayerEntity renderModeBased;
@Override
public World getWorld() {
@@ -114,33 +113,6 @@ public class ServerHelper extends CommonHelper {
@Override
public CableRenderMode getRenderMode() {
if (this.renderModeBased == null) {
return CableRenderMode.STANDARD;
}
return this.renderModeForPlayer(this.renderModeBased);
}
@Override
public void updateRenderMode(final PlayerEntity player) {
this.renderModeBased = player;
}
protected CableRenderMode renderModeForPlayer(final PlayerEntity player) {
if (player != null) {
for (int x = 0; x < PlayerInventory.getHotbarSize(); x++) {
final ItemStack is = player.inventory.getStack(x);
if (!is.isEmpty() && is.getItem() instanceof NetworkToolItem) {
final CompoundTag c = is.getTag();
if (c != null && c.getBoolean("hideFacades")) {
return CableRenderMode.CABLE_VIEW;
}
}
}
}
return CableRenderMode.STANDARD;
}
@Override
@@ -29,7 +29,7 @@ import net.minecraft.block.entity.BlockEntity;
import net.minecraft.network.play.server.SChunkDataPacket;
import net.minecraft.util.Tickable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.EmptyBlockReader;
import net.minecraft.world.EmptyBlockView;
import net.minecraft.world.ITickList;
import net.minecraft.world.NextTickListEntry;
import net.minecraft.world.World;
@@ -136,7 +136,7 @@ public class CachedPlane {
this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].fillData(tePOS.getY(), details);
// don't skip air, just let the code replace it...
if (details.state.isAir(EmptyBlockReader.INSTANCE, tePOS)) {
if (details.state.isAir(EmptyBlockView.INSTANCE, tePOS)) {
w.removeBlock(tePOS, false);
} else {
this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].setSkip(tePOS.getY());
@@ -122,7 +122,7 @@ public final class SpatialDimensionManager implements ISpatialDimension {
@Override
public BlockPos getCellDimensionSize(DimensionType cellDim) {
SpatialDimensionExtraData extraData = getExtraData(cellDim);
return extraData != null ? extraData.getSize() : BlockPos.ZERO;
return extraData != null ? extraData.getSize() : BlockPos.ORIGIN;
}
@Override
@@ -21,8 +21,8 @@ package appeng.thirdparty.codechicken.lib.model;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormatElement;
/**
* A simple VertexFormat cache. This caches the existence of attributes and
@@ -73,7 +73,7 @@ public class CachedFormat {
this.elementCount = format.getElements().size();
for (int i = 0; i < this.elementCount; i++) {
VertexFormatElement element = format.getElements().get(i);
switch (element.getUsage()) {
switch (element.getType()) {
case POSITION:
if (this.hasPosition) {
throw new IllegalStateException("Found 2 position elements..");
@@ -18,11 +18,11 @@
package appeng.thirdparty.codechicken.lib.model;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
@@ -275,7 +275,7 @@ public class Quad implements IVertexProducer, ISmartVertexConsumer {
* @return The BakedQuad.
*/
public BakedQuad bake() {
if (format.format != DefaultVertexFormats.BLOCK) {
if (format.format != VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL) {
throw new IllegalStateException("Unable to bake this quad to the specified format. " + format.format);
}
int[] packedData = new int[this.format.format.getSize()];
@@ -25,9 +25,8 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import appeng.thirdparty.codechicken.lib.model.CachedFormat;
import appeng.thirdparty.codechicken.lib.model.ISmartVertexConsumer;
@@ -21,7 +21,7 @@ package appeng.thirdparty.codechicken.lib.model.pipeline;
import javax.annotation.OverridingMethodsMustInvokeSuper;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
@@ -261,7 +261,7 @@ public class CraftingBlockEntity extends AENetworkBlockEntity implements IAEMult
for (final AEPartLocation d : AEPartLocation.SIDE_LOCATIONS) {
final WorldCoord wc = new WorldCoord(te);
wc.add(d, 1);
if (this.world.isAirBlock(wc.getPos())) {
if (this.world.isAir(wc.getPos())) {
places.add(wc);
}
}
@@ -25,6 +25,7 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
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.texture.SpriteAtlasTexture;
@@ -37,7 +38,6 @@ import net.minecraft.client.renderer.RenderState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
@@ -116,7 +116,7 @@ public class MolecularAssemblerRenderer extends BlockEntityRenderer<MolecularAss
if (status.getTicksUntilParticles() <= 0) {
status.setTicksUntilParticles(4);
if (AppEng.proxy.shouldAddParticles(particleRandom)) {
if (AppEng.instance().shouldAddParticles(particleRandom)) {
for (int x = 0; x < (int) Math.ceil(status.getSpeed() / 5.0); x++) {
minecraft.particleManager.addParticle(ParticleTypes.CRAFTING, centerX, centerY, centerZ, 0, 0, 0);
}
@@ -156,7 +156,7 @@ public class MolecularAssemblerRenderer extends BlockEntityRenderer<MolecularAss
.transparency(TRANSLUCENT_TRANSPARENCY).alpha(new RenderState.AlphaState(0.05F))
.lightmap(disableLightmap).build(true);
return RenderLayer.makeType("ae2_translucent_alphatest", DefaultVertexFormats.POSITION_COLOR_TEX_LIGHTMAP,
return RenderLayer.makeType("ae2_translucent_alphatest", VertexFormats.POSITION_COLOR_TEX_LIGHTMAP,
GL11.GL_QUADS, 256, glState);
}
@@ -79,14 +79,14 @@ public class AENetworkBlockEntity extends AEBaseBlockEntity implements IActionHo
}
@Override
public void remove() {
super.remove();
public void markRemoved() {
super.markRemoved();
this.getProxy().remove();
}
@Override
public void validate() {
super.validate();
public void cancelRemoval() {
super.cancelRemoval();
this.getProxy().validate();
}
@@ -78,14 +78,14 @@ public abstract class AENetworkInvBlockEntity extends AEBaseInvBlockEntity imple
}
@Override
public void remove() {
super.remove();
public void markRemoved() {
super.markRemoved();
this.getProxy().remove();
}
@Override
public void validate() {
super.validate();
public void cancelRemoval() {
super.cancelRemoval();
this.getProxy().validate();
}
@@ -78,14 +78,14 @@ public abstract class AENetworkPowerBlockEntity extends AEBasePoweredBlockEntity
}
@Override
public void validate() {
super.validate();
public void cancelRemoval() {
super.cancelRemoval();
this.getProxy().validate();
}
@Override
public void remove() {
super.remove();
public void markRemoved() {
super.markRemoved();
this.getProxy().remove();
}
@@ -1,335 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.tile.networking;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.client.model.data.ModelDataMap;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import appeng.api.networking.IGridNode;
import appeng.api.parts.IFacadeContainer;
import appeng.api.parts.IPart;
import appeng.api.parts.LayerFlags;
import appeng.api.parts.SelectedPart;
import appeng.api.util.AECableType;
import appeng.api.util.AEColor;
import appeng.api.util.AEPartLocation;
import appeng.api.util.DimensionalCoord;
import appeng.client.render.cablebus.CableBusRenderState;
import appeng.helpers.AEMultiTile;
import appeng.hooks.TickHandler;
import appeng.parts.CableBusContainer;
import appeng.tile.AEBaseBlockEntity;
import appeng.util.Platform;
public class CableBusBlockEntity extends AEBaseBlockEntity implements AEMultiTile {
private CableBusContainer cb = new CableBusContainer(this);
private int oldLV = -1; // on re-calculate light when it changes
public CableBusBlockEntity(BlockEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
}
@Override
public void fromTag(BlockState state, final CompoundTag data) {
super.fromTag(state, data);
this.getCableBus().readFromNBT(data);
}
@Override
public CompoundTag toTag(final CompoundTag data) {
super.toTag(data);
this.getCableBus().writeToNBT(data);
return data;
}
@Override
protected boolean readFromStream(final PacketByteBuf data) throws IOException {
final boolean c = super.readFromStream(data);
boolean ret = this.getCableBus().readFromStream(data);
final int newLV = this.getCableBus().getLightValue();
if (newLV != this.oldLV) {
this.oldLV = newLV;
this.world.getLightManager().checkBlock(this.pos);
ret = true;
}
this.updateTileSetting();
return ret || c;
}
@Override
protected void writeToStream(final PacketByteBuf data) throws IOException {
super.writeToStream(data);
this.getCableBus().writeToStream(data);
}
/**
* Changes this tile to the TESR version if any of the parts require dynamic
* rendering.
*/
protected void updateTileSetting() {
// FIXME: potentially invalidate voxel shape cache?
}
@Override
public double getMaxRenderDistanceSquared() {
return 900.0;
}
@Override
public void remove() {
super.remove();
this.getCableBus().removeFromWorld();
}
@Override
public void validate() {
super.validate();
TickHandler.INSTANCE.addInit(this);
}
@Override
public IGridNode getGridNode(final AEPartLocation dir) {
return this.getCableBus().getGridNode(dir);
}
@Override
public AECableType getCableConnectionType(final AEPartLocation side) {
return this.getCableBus().getCableConnectionType(side);
}
@Override
public float getCableConnectionLength(AECableType cable) {
return this.getCableBus().getCableConnectionLength(cable);
}
@Override
public void onChunkUnloaded() {
super.onChunkUnloaded();
this.getCableBus().removeFromWorld();
}
@Override
public void markForUpdate() {
if (this.world == null) {
return;
}
final int newLV = this.getCableBus().getLightValue();
if (newLV != this.oldLV) {
this.oldLV = newLV;
this.world.getLightManager().checkBlock(this.pos);
}
super.markForUpdate();
}
@Override
public boolean canBeRotated() {
return false;
}
@Override
public void getDrops(final World w, final BlockPos pos, final List drops) {
this.getCableBus().getDrops(drops);
}
@Override
public void getNoDrops(final World w, final BlockPos pos, final List<ItemStack> drops) {
this.getCableBus().getNoDrops(drops);
}
@Override
public void onReady() {
super.onReady();
if (this.getCableBus().isEmpty()) {
if (this.world.getBlockEntity(this.pos) == this) {
this.world.breakBlock(this.pos, true);
}
} else {
this.getCableBus().addToWorld();
}
}
@Override
public IFacadeContainer getFacadeContainer() {
return this.getCableBus().getFacadeContainer();
}
@Override
public boolean canAddPart(final ItemStack is, final AEPartLocation side) {
return this.getCableBus().canAddPart(is, side);
}
@Override
public AEPartLocation addPart(final ItemStack is, final AEPartLocation side, final PlayerEntity player,
final Hand hand) {
return this.getCableBus().addPart(is, side, player, hand);
}
@Override
public IPart getPart(final AEPartLocation side) {
return this.cb.getPart(side);
}
@Override
public IPart getPart(final Direction side) {
return this.getCableBus().getPart(side);
}
@Override
public void removePart(final AEPartLocation side, final boolean suppressUpdate) {
this.getCableBus().removePart(side, suppressUpdate);
}
@Override
public DimensionalCoord getLocation() {
return new DimensionalCoord(this);
}
@Override
public AEColor getColor() {
return this.getCableBus().getColor();
}
@Override
public void clearContainer() {
this.setCableBus(new CableBusContainer(this));
}
@Override
public boolean isBlocked(final Direction side) {
// TODO 1.10.2-R - Stuff.
return false;
}
@Override
public SelectedPart selectPart(final Vec3d pos) {
return this.getCableBus().selectPart(pos);
}
@Override
public void markForSave() {
this.saveChanges();
}
@Override
public void partChanged() {
this.notifyNeighbors();
}
@Override
public boolean hasRedstone(final AEPartLocation side) {
return this.getCableBus().hasRedstone(side);
}
@Override
public boolean isEmpty() {
return this.getCableBus().isEmpty();
}
@Override
public Set<LayerFlags> getLayerFlags() {
return this.getCableBus().getLayerFlags();
}
@Override
public void cleanup() {
this.getWorld().removeBlock(this.pos, false);
}
@Override
public void notifyNeighbors() {
if (this.world != null && this.world.isChunkLoaded(this.pos) && !CableBusContainer.isLoading()) {
Platform.notifyBlocksOfNeighbors(this.world, this.pos);
}
}
@Override
public boolean isInWorld() {
return this.getCableBus().isInWorld();
}
@Override
public boolean recolourBlock(final Direction side, final AEColor colour, final PlayerEntity who) {
return this.getCableBus().recolourBlock(side, colour, who);
}
public CableBusContainer getCableBus() {
return this.cb;
}
private void setCableBus(final CableBusContainer cb) {
this.cb = cb;
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> capabilityClass, @Nullable Direction fromSide) {
// Note that null will be translated to INTERNAL here
AEPartLocation partLocation = AEPartLocation.fromFacing(fromSide);
IPart part = this.getPart(partLocation);
LazyOptional<T> result = part == null ? LazyOptional.empty() : part.getCapability(capabilityClass);
if (result != null) {
return result;
}
return super.getCapability(capabilityClass, fromSide);
}
@Nonnull
@Override
public CableBusRenderState getRenderAttachmentData() {
World world = getWorld();
if (world == null) {
return EmptyModelData.INSTANCE;
}
CableBusRenderState renderState = this.cb.getRenderState();
renderState.setWorld(world);
renderState.setPos(pos);
return new ModelDataMap.Builder().withInitial(CableBusRenderState.PROPERTY, renderState).build();
}
}

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