More misc control panel stuff

Includes RS indicator lights
This commit is contained in:
malte0811 2017-04-01 17:33:58 +02:00
parent b1ff95cf85
commit 4ecab259dd
15 changed files with 471 additions and 189 deletions

View file

@ -32,6 +32,7 @@ import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
@ -99,9 +100,9 @@ public abstract class BlockIWBase extends Block {
state = super.getExtendedState(state, world, pos);
if (state instanceof IExtendedBlockState) {
TileEntity te = world.getTileEntity(pos);
if (te instanceof IImmersiveConnectable&&world instanceof World) {
Set<ImmersiveNetHandler.Connection> conns = ImmersiveNetHandler.INSTANCE.getConnections((World)world, pos);
state = ((IExtendedBlockState) state).withProperty(IEProperties.CONNECTIONS, MiscUtils.genConnBlockstate(conns, (World) world));
if (te instanceof IImmersiveConnectable) {
Set<ImmersiveNetHandler.Connection> conns = ImmersiveNetHandler.INSTANCE.getConnections(te.getWorld(), pos);
state = ((IExtendedBlockState) state).withProperty(IEProperties.CONNECTIONS, MiscUtils.genConnBlockstate(conns, te.getWorld()));
}
}
return state;
@ -117,6 +118,10 @@ public abstract class BlockIWBase extends Block {
if (te instanceof IHasDummyBlocksIW) {
((IHasDummyBlocksIW) te).breakDummies();
}
if(te instanceof IImmersiveConnectable) {
if(!worldIn.isRemote||!Minecraft.getMinecraft().isSingleplayer())//TODO fix this in IE!!!
ImmersiveNetHandler.INSTANCE.clearAllConnectionsFor(Utils.toCC(te), worldIn, !worldIn.isRemote&&worldIn.getGameRules().getBoolean("doTileDrops"));
}
super.breakBlock(worldIn, pos, state);
worldIn.removeTileEntity(pos);
}

View file

@ -31,6 +31,7 @@ import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
@ -44,6 +45,18 @@ public class BlockPanel extends BlockIWBase implements IPlacementCheck, IMetaEnu
public static final PropertyEnum<BlockTypes_Panel> type = PropertyEnum.create("type", BlockTypes_Panel.class);
public BlockPanel() {
super(Material.IRON, "control_panel");
lightOpacity = 0;
}
@Override
public boolean canRenderInLayer(IBlockState state, BlockRenderLayer layer) {
switch (state.getValue(type)) {
case TOP:
return layer==BlockRenderLayer.CUTOUT;
case RS_WIRE:
return layer==BlockRenderLayer.TRANSLUCENT||layer==BlockRenderLayer.SOLID;
}
return super.canRenderInLayer(state, layer);
}
@Override
@ -99,7 +112,7 @@ public class BlockPanel extends BlockIWBase implements IPlacementCheck, IMetaEnu
if (state instanceof IExtendedBlockState) {
TileEntity te = world.getTileEntity(pos);
if (te instanceof TileEntityPanel) {
state = ((IExtendedBlockState) state).withProperty(PropertyComponents.INSTANCE, ((TileEntityPanel) te).components);
state = ((IExtendedBlockState) state).withProperty(PropertyComponents.INSTANCE, ((TileEntityPanel) te).getComponents());
}
}
return state;
@ -122,8 +135,28 @@ public class BlockPanel extends BlockIWBase implements IPlacementCheck, IMetaEnu
@Override
public void getSubBlocks(Item itemIn, CreativeTabs tab, List<ItemStack> list) {
//TODO figure out a way to properly place control panels...
list.add(new ItemStack(itemIn, 1, 0));
list.add(new ItemStack(itemIn, 1, 1));
list.add(new ItemStack(itemIn, 1, 2));
}
@Override
public boolean isFullBlock(IBlockState state) {
return false;
}
@Override
public boolean isFullCube(IBlockState state) {
return false;
}
@Override
public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) {
return false;
}
@Override
public boolean isOpaqueCube(IBlockState state) {
return false;
}
@Override
public boolean isVisuallyOpaque() {
return false;
}
}

View file

@ -6,7 +6,8 @@ import java.util.Locale;
public enum BlockTypes_Panel implements IStringSerializable {
TOP,
RS_WIRE;
RS_WIRE,
DUMMY;
@Override
public String getName() {

View file

@ -0,0 +1,127 @@
package malte0811.industrialWires.blocks.controlpanel;
import blusunrize.immersiveengineering.common.util.IELogger;
import com.google.common.collect.ImmutableList;
import malte0811.industrialWires.client.RawQuad;
import malte0811.industrialWires.client.panelmodel.PanelUtils;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.client.model.ModelLoader;
import org.lwjgl.util.vector.Vector3f;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class IndicatorLight extends PanelComponent {
int rsInputId;
int rsInputChannel;
int colorA;
byte rsInput;
public IndicatorLight() {
super("indicator_light");
}
public IndicatorLight(int rsId, int rsChannel, int color) {
this();
colorA = color;
rsInputChannel = rsChannel;
rsInputId = rsId;
}
@Override
protected void writeCustomNBT(NBTTagCompound nbt) {
nbt.setInteger("rsId", rsInputId);
nbt.setInteger("rsChannel", rsInputChannel);
nbt.setInteger("color", colorA);
nbt.setInteger("rsInput", rsInput);
}
@Override
protected void readCustomNBT(NBTTagCompound nbt) {
rsInputId = nbt.getInteger("rsId");
rsInputChannel = nbt.getInteger("rsChannel");
colorA = nbt.getInteger("color");
rsInput = nbt.getByte("rsInput");
}
private static final float size = .0625F;
private static final float antiZOffset = .001F;
@Override
public List<RawQuad> getQuads() {
float[] color = new float[4];
color[3] = 1;
for (int i = 0;i<3;i++) {
color[i] = ((this.colorA>>(8*(2-i)))&255)/255F*(rsInput+15F)/30F;
}
List<RawQuad> ret = new ArrayList<>(1);
PanelUtils.addColoredQuad(ret, new Vector3f(), new Vector3f(0, antiZOffset, size), new Vector3f(size, antiZOffset, size), new Vector3f(size, antiZOffset, 0), EnumFacing.UP, color);
return ret;
}
@Nonnull
@Override
public PanelComponent copyOf() {
IndicatorLight ret = new IndicatorLight(rsInputId, rsInputChannel, colorA);
ret.rsInput = rsInput;
ret.setX(x);
ret.setY(y);
ret.panelHeight = panelHeight;
return ret;
}
@Override
public AxisAlignedBB getBlockRelativeAABB() {
return null;
}
@Override
public boolean interactWith(Vec3d hitRelative, TileEntityPanel tile) {
return false;
}
@Override
public void update(TileEntityPanel tile) {
}
@Nullable
@Override
public Consumer<byte[]> getRSInputHandler(int id, TileEntityPanel panel) {
if (id==rsInputId) {
return (input)->{
if (input[rsInputChannel]!=rsInput) {
rsInput = input[rsInputChannel];
panel.markDirty();
panel.triggerRenderUpdate();
}
};
}
return null;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
IndicatorLight that = (IndicatorLight) o;
if (colorA != that.colorA) return false;
return rsInput == that.rsInput;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + colorA;
result = 31 * result + (int) rsInput;
return result;
}
}
//TODO optimize RS net in IE, updates multiple times per tick. 0-length pulses?

View file

@ -15,10 +15,13 @@ import java.util.List;
public class Label extends PanelComponent {
private static final ResourceLocation font = new ResourceLocation("minecraft", "textures/font/ascii.png");
String text;
RawModelFontRenderer renderer;
int color;
public Label(String text) {
public Label(String text, int color) {
this();
this.text = text;
this.color = color;
}
public Label() {
super("label");
@ -27,26 +30,29 @@ public class Label extends PanelComponent {
@Override
protected void writeCustomNBT(NBTTagCompound nbt) {
nbt.setString("text", text);
nbt.setInteger("color", color);
}
@Override
protected void readCustomNBT(NBTTagCompound nbt) {
text = nbt.getString("text");
color = nbt.getInteger("color");
}
@Override
public List<RawQuad> getQuads() {
RawModelFontRenderer render = fontRenderer();
render.drawString(text, 0, 0, 0xff0000);
render.drawString(text, 0, 0, 0xff000000|color);
return render.build();
}
@Nonnull
@Override
public Label copyOf() {
Label ret = new Label(text);
Label ret = new Label(text, color);
ret.setX(x);
ret.setY(y);
ret.panelHeight = panelHeight;
return ret;
}
@ -66,8 +72,11 @@ public class Label extends PanelComponent {
}
private RawModelFontRenderer fontRenderer() {
return new RawModelFontRenderer(Minecraft.getMinecraft().gameSettings, font, Minecraft.getMinecraft().getTextureManager(),
false, .01F);
if (renderer==null) {
renderer = new RawModelFontRenderer(Minecraft.getMinecraft().gameSettings, font, Minecraft.getMinecraft().getTextureManager(),
false, 1);
}
return renderer;
}
}

View file

@ -28,6 +28,7 @@ import org.lwjgl.util.vector.Vector3f;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
public class LightedButton extends PanelComponent {
public int color;
@ -37,6 +38,7 @@ public class LightedButton extends PanelComponent {
public int rsOutputChannel;
private AxisAlignedBB aabb;
private int ticksTillOff;
private BiConsumer<Integer, Byte> rsOut;
public LightedButton() {
super("lightedButton");
}
@ -88,6 +90,7 @@ public class LightedButton extends PanelComponent {
LightedButton ret = new LightedButton(color, active, latching, rsOutputId, rsOutputChannel);
ret.setX(x);
ret.setY(y);
ret.panelHeight = panelHeight;
return ret;
}
@ -124,15 +127,20 @@ public class LightedButton extends PanelComponent {
}
}
@Override
public void registerRSOutput(int id, @Nonnull BiConsumer<Integer, Byte> out) {
if (id==rsOutputId) {
rsOut = out;
rsOut.accept(rsOutputChannel, (byte) (active?15:0));
}
}
private void setOut(boolean on, TileEntityPanel tile) {
active = on;
tile.markDirty();
tile.triggerRenderUpdate();
TileEntityRSPanelConn rs = tile.getRSConn(rsOutputId);
if (rs!=null) {
byte[] oldRS = rs.getCachedOutput();
oldRS[rsOutputChannel] = (byte) (on ? 15 : 0);
rs.updateInternalRSValues(oldRS);
if (rsOut!=null) {
rsOut.accept(rsOutputChannel, (byte)(active?15:0));
}
}

View file

@ -29,9 +29,12 @@ import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3d;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
public abstract class PanelComponent {
@ -45,6 +48,7 @@ public abstract class PanelComponent {
static {
baseCreaters.put("lightedButton", LightedButton::new);
baseCreaters.put("label", Label::new);
baseCreaters.put("indicator_light", IndicatorLight::new);
}
protected abstract void writeCustomNBT(NBTTagCompound nbt);
protected abstract void readCustomNBT(NBTTagCompound nbt);
@ -60,6 +64,15 @@ public abstract class PanelComponent {
public abstract void update(TileEntityPanel tile);
@Nullable
public Consumer<byte[]> getRSInputHandler(int id, TileEntityPanel panel) {
return null;
}
public void registerRSOutput(int id, @Nonnull BiConsumer<Integer, Byte> out) {}
public void unregisterRSOutput(int id, @Nonnull BiConsumer<Integer, Byte> out) {}
public float getX() {
return x;
}
@ -110,7 +123,7 @@ public abstract class PanelComponent {
double px = te.getPos().getX()-TileEntityRendererDispatcher.staticPlayerX;
double py = te.getPos().getY()-TileEntityRendererDispatcher.staticPlayerY;
double pz = te.getPos().getZ()-TileEntityRendererDispatcher.staticPlayerZ;
RenderGlobal.func_189697_a(te.apply(te.components.getPanelTopTransform(), getBlockRelativeAABB()).expandXyz(0.002).offset(px, py, pz), 0.0F, 0.0F, 0.0F, 0.4F);
RenderGlobal.func_189697_a(te.apply(te.getComponents().getPanelTopTransform(), getBlockRelativeAABB()).expandXyz(0.002).offset(px, py, pz), 0.0F, 0.0F, 0.0F, 0.4F);
GlStateManager.depthMask(true);
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();

View file

@ -49,6 +49,7 @@ public class PropertyComponents implements IUnlistedProperty<PropertyComponents.
public static class PanelRenderProperties extends ArrayList<PanelComponent> {
public EnumFacing facing = EnumFacing.NORTH;
public float height = .5F;
public EnumFacing top = EnumFacing.UP;
public TileEntityPanel panel;//Don't compare this+erase it on copying
public PanelRenderProperties() {
super();
@ -68,18 +69,36 @@ public class PropertyComponents implements IUnlistedProperty<PropertyComponents.
return ret+"]";
}
public Matrix4 getPanelTopTransform() {
return getPanelBaseTransform().translate(0, height, 0);
}
public Matrix4 getPanelBaseTransform() {
Matrix4 ret = new Matrix4();
ret.translate(.5, height, .5);
ret.rotate(-facing.getHorizontalAngle()*Math.PI/180+Math.PI, 0, 1, 0);
ret.translate(-.5, 0, -.5);
ret.translate(.5, .5, .5);
switch (top) {
case DOWN:
ret.rotate(Math.PI, 0, 0, 1);
case UP:
ret.rotate(-facing.getHorizontalAngle() * Math.PI / 180 + Math.PI, 0, 1, 0);
break;
case NORTH:
case SOUTH:
case WEST:
case EAST:
ret.rotate(Math.PI/2, 1, 0, 0);
ret.rotate(top.getHorizontalAngle() * Math.PI / 180, 0, 0, 1);
break;
}
ret.translate(-.5, -.5, -.5);
return ret;
}
public PanelRenderProperties copyOf() {
PanelRenderProperties ret = new PanelRenderProperties(size());
for (PanelComponent pc:this) {
ret.add(pc.copyOf());
}
ret.facing = facing;
ret.top = top;
return ret;
}
@ -91,13 +110,17 @@ public class PropertyComponents implements IUnlistedProperty<PropertyComponents.
PanelRenderProperties that = (PanelRenderProperties) o;
return facing == that.facing;
if (Float.compare(that.height, height) != 0) return false;
if (facing != that.facing) return false;
return top == that.top;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + facing.hashCode();
result = 31 * result + (height != +0.0f ? Float.floatToIntBits(height) : 0);
result = 31 * result + top.hashCode();
return result;
}
}

View file

@ -24,10 +24,12 @@ import blusunrize.immersiveengineering.common.util.IELogger;
import blusunrize.immersiveengineering.common.util.chickenbones.Matrix4;
import malte0811.industrialWires.blocks.IBlockBoundsIW;
import malte0811.industrialWires.blocks.TileEntityIWBase;
import malte0811.industrialWires.util.MiscUtils;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
@ -44,40 +46,34 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class TileEntityPanel extends TileEntityIWBase implements IDirectionalTile, IBlockBoundsIW, IPlayerInteraction, ITickable {
PropertyComponents.PanelRenderProperties components = new PropertyComponents.PanelRenderProperties();
private PropertyComponents.PanelRenderProperties components = new PropertyComponents.PanelRenderProperties();
boolean firstTick = true;
// non-rendered properties
//relative positions!
private List<BlockPos> rsWireConns = new ArrayList<>();
//TODO does the lambda stuff cause GC issues?
{
Random r = new Random();
PanelComponent b = new LightedButton(0xff<<(8*r.nextInt(3)), false, false, 0, 0);
b.setX(3/16F);
b.setY(.75F);
b.setPanelHeight(components.height);
components.add(b);
b = new LightedButton(0xff<<(8*r.nextInt(3)), false, true, 0, 1);
b.setX(8/16F);
b.setY(.75F);
b.setPanelHeight(components.height);
components.add(b);
b = new LightedButton(0xff<<(8*r.nextInt(3)), false, true, 0, 2);
b.setX(13/16F);
b.setY(.75F);
b.setPanelHeight(components.height);
components.add(b);
b = new Label("TESTtextIII");
b.setX(3/16F);
b.setY(.25F);
b.setPanelHeight(components.height);
components.add(b);
rsWireConns.add(new BlockPos(0, -1, 0));//one RS output 1 block below the panel
for (int i = 0;i<16;i++) {
int color = EnumDyeColor.byMetadata(i).getMapColor().colorValue;
IndicatorLight ind = new IndicatorLight(0, i, color);
LightedButton btn = new LightedButton(color, false, true, 1, i);
Label lbl = new Label("->", color);
ind.setX(0);
ind.setY(i/16F);
ind.setPanelHeight(.5F);
lbl.setX(2/16F);
lbl.setY(i/16F);
lbl.setPanelHeight(.5F);
btn.setX(5/16F);
btn.setY(i/16F);
btn.setPanelHeight(.5F);
components.add(ind);
components.add(lbl);
components.add(btn);
}
}
@Override
@ -86,10 +82,16 @@ public class TileEntityPanel extends TileEntityIWBase implements IDirectionalTil
pc.update(this);
}
if (!worldObj.isRemote) {
for (int i = 0; i < rsWireConns.size(); i++) {
TileEntityRSPanelConn rs = getRSConn(i);
if (rs != null)
rs.flushRS();
if (firstTick) {
List<BlockPos> parts = MiscUtils.discoverPanelParts(worldObj, pos);
for (BlockPos bp:parts) {
TileEntity te = worldObj.getTileEntity(bp);
if (te instanceof TileEntityRSPanelConn) {
//TODO deal with people adding 2 RS ports with the same ID!
((TileEntityRSPanelConn) te).requestRSConn(this);
}
}
firstTick = false;
}
}
}
@ -105,11 +107,7 @@ public class TileEntityPanel extends TileEntityIWBase implements IDirectionalTil
out.setTag("components", comps);
out.setInteger("facing", components.facing.getHorizontalIndex());
out.setFloat("height", components.height);
NBTTagList rsConns = new NBTTagList();
for (BlockPos pos:rsWireConns) {
rsConns.appendTag(new NBTTagLong(pos.toLong()));
}
out.setTag("rsConns", rsConns);
out.setInteger("top", components.top.getIndex());
}
@Override
@ -122,13 +120,10 @@ public class TileEntityPanel extends TileEntityIWBase implements IDirectionalTil
components.add(pc);
}
}
l = in.getTagList("rsConns", 4);
rsWireConns.clear();
for (int i = 0;i<l.tagCount();i++) {
rsWireConns.add(BlockPos.fromLong(((NBTTagLong)l.get(i)).getLong()));
}
components.facing = EnumFacing.getHorizontal(in.getInteger("facing"));
components.height = in.getFloat("height");
components.top = EnumFacing.getFront(in.getInteger("top"));
defAABB = null;
}
@Override
@ -146,6 +141,25 @@ public class TileEntityPanel extends TileEntityIWBase implements IDirectionalTil
return 2;
}
@Override
public EnumFacing getFacingForPlacement(EntityLivingBase placer, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ) {
switch (side) {
case UP:
components.top = EnumFacing.UP;
return IDirectionalTile.super.getFacingForPlacement(placer, pos, side, hitX, hitY, hitZ);
case DOWN:
components.top = EnumFacing.DOWN;
return IDirectionalTile.super.getFacingForPlacement(placer, pos, side, hitX, hitY, hitZ);
case NORTH:
case SOUTH:
case WEST:
case EAST:
components.top = side;
return EnumFacing.SOUTH;//Should not matter
}
return components.facing;
}
@Override
public boolean mirrorFacingOnPlacement(EntityLivingBase placer) {
return false;
@ -165,7 +179,7 @@ public class TileEntityPanel extends TileEntityIWBase implements IDirectionalTil
@Override
public AxisAlignedBB getBoundingBox() {
if (defAABB==null) {
defAABB = new AxisAlignedBB(0, 0, 0, 1, components.height, 1);
defAABB = apply(components.getPanelBaseTransform(), new AxisAlignedBB(0, 0, 0, 1, components.height, 1));
}
return defAABB;
}
@ -209,15 +223,4 @@ public class TileEntityPanel extends TileEntityIWBase implements IDirectionalTil
worldObj.notifyBlockUpdate(pos,state,state,3);
worldObj.addBlockEvent(pos, state.getBlock(), 255, 0);
}
public TileEntityRSPanelConn getRSConn(int id) {
if (id < 0 || id >= rsWireConns.size()) {
return null;
}
TileEntity te = worldObj.getTileEntity(pos.add(rsWireConns.get(id)));
if (te instanceof TileEntityRSPanelConn) {
return (TileEntityRSPanelConn) te;
}
return null;
}
}

View file

@ -3,66 +3,94 @@ package malte0811.industrialWires.blocks.controlpanel;
import blusunrize.immersiveengineering.api.TargetingInfo;
import blusunrize.immersiveengineering.api.energy.wires.IImmersiveConnectable;
import blusunrize.immersiveengineering.api.energy.wires.ImmersiveNetHandler;
import blusunrize.immersiveengineering.api.energy.wires.TileEntityImmersiveConnectable;
import blusunrize.immersiveengineering.api.energy.wires.WireType;
import blusunrize.immersiveengineering.api.energy.wires.redstone.IRedstoneConnector;
import blusunrize.immersiveengineering.api.energy.wires.redstone.RedstoneWireNetwork;
import malte0811.industrialWires.blocks.TileEntityIWBase;
import malte0811.industrialWires.util.MiscUtils;
import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ITickable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
//TODO implement IRedstoneConnector once there is a Maven build with it
public class TileEntityRSPanelConn extends TileEntityIWBase implements IRedstoneConnector, ITickable {
public class TileEntityRSPanelConn extends TileEntityImmersiveConnectable implements IRedstoneConnector, ITickable {
private byte[] out = new byte[16];
private boolean dirty = true;
private byte[] oldInput = new byte[16];
private Set<Consumer<byte[]>> changeListeners = new HashSet<>();
@Nonnull
private RedstoneWireNetwork network = new RedstoneWireNetwork().add(this);
private boolean hasConn = false;//TODO write to NBT
private boolean hasConn = false;
private int id;
{
for (int i = 0;i<16;i++) {
out[i] = -1;
oldInput[i] = -1;
}
}
private boolean loaded = false;
@Override
public void update() {
if(hasWorldObj() && !worldObj.isRemote && !loaded) {
loaded = true;
// completely reload the network
network.removeFromNetwork(null);
if(hasWorldObj() && !worldObj.isRemote) {
if (!loaded) {
loaded = true;
// completely reload the network
network.removeFromNetwork(null);
List<BlockPos> parts = MiscUtils.discoverPanelParts(worldObj, pos);
for (BlockPos bp:parts) {
TileEntity te = worldObj.getTileEntity(bp);
if (te instanceof TileEntityPanel) {
requestRSConn(((TileEntityPanel) te));
}
}
}
if (dirty) {
network.updateValues();
dirty = false;
}
}
}
@Override
public void writeNBT(NBTTagCompound out, boolean updatePacket) {
public void writeCustomNBT(NBTTagCompound out, boolean updatePacket) {
super.writeCustomNBT(out, updatePacket);
out.setByteArray("out", this.out);
out.setBoolean("hasConn", hasConn);
out.setInteger("rsId", id);
}
@Override
public void readNBT(NBTTagCompound in, boolean updatePacket) {
public void readCustomNBT(NBTTagCompound in, boolean updatePacket) {
super.readCustomNBT(in, updatePacket);
out = in.getByteArray("out");
hasConn = in.getBoolean("hasConn");
id = in.getInteger("rsId");
}
// <0 means don't care
public void updateInternalRSValues(byte[] output) {
out = output;
dirty = true;
}
public void flushRS() {
if (dirty) {
network.updateValues();
public void requestRSConn(TileEntityPanel panel) {
PropertyComponents.PanelRenderProperties p = panel.getComponents();
for (PanelComponent pc:p) {
Consumer<byte[]> listener = pc.getRSInputHandler(id, panel);
if (listener!=null) {
changeListeners.add(listener);
}
pc.registerRSOutput(id, (channel, value)->{
if (value!=out[channel]) {
dirty = true;
out[channel] = value;
}
});
}
}
public byte[] getInput() {
return network.channelValues;
}
public byte[] getCachedOutput() {
return out;
}
@Override
public void setNetwork(@Nonnull RedstoneWireNetwork net) {
@ -77,7 +105,12 @@ public class TileEntityRSPanelConn extends TileEntityIWBase implements IRedstone
@Override
public void onChange() {
if (!Arrays.equals(oldInput, network.channelValues)) {
oldInput = Arrays.copyOf(network.channelValues, 16);
for (Consumer<byte[]> c:changeListeners) {
c.accept(oldInput);
}
}
}
@Override
@ -87,21 +120,6 @@ public class TileEntityRSPanelConn extends TileEntityIWBase implements IRedstone
}
}
@Override
public boolean canConnect() {
return !hasConn;
}
@Override
public boolean isEnergyOutput() {
return false;
}
@Override
public int outputEnergy(int i, boolean b, int i1) {
return 0;
}
@Override
public BlockPos getConnectionMaster(@Nullable WireType wire, TargetingInfo target) {
return pos;
@ -122,7 +140,7 @@ public class TileEntityRSPanelConn extends TileEntityIWBase implements IRedstone
@Override
public WireType getCableLimiter(TargetingInfo targetingInfo) {
return hasConn?WireType.REDSTONE:null;
return WireType.REDSTONE;
}
@Override
@ -130,13 +148,15 @@ public class TileEntityRSPanelConn extends TileEntityIWBase implements IRedstone
return false;
}
@Override
public void onEnergyPassthrough(int i) {}
@Override
public void removeCable(ImmersiveNetHandler.Connection connection) {
hasConn = false;
network.removeFromNetwork(this);
this.markDirty();
if(worldObj != null) {
IBlockState state = worldObj.getBlockState(pos);
worldObj.notifyBlockUpdate(pos, state,state, 3);
}
}
@Override

View file

@ -18,18 +18,21 @@
package malte0811.industrialWires.client.panelmodel;
import blusunrize.immersiveengineering.common.util.IELogger;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ImmutableList;
import malte0811.industrialWires.blocks.controlpanel.PropertyComponents;
import malte0811.industrialWires.blocks.controlpanel.PropertyComponents.PanelRenderProperties;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.common.property.IExtendedBlockState;
import javax.annotation.Nullable;
@ -41,13 +44,7 @@ public class PanelModel implements IBakedModel {
public final static Cache<PanelRenderProperties, AssembledBakedModel> modelCache = CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterAccess(60, TimeUnit.SECONDS)
.build();//TODO make all components implement equals+hashCode
private IBakedModel base;
public PanelModel(IBakedModel base) {
this.base = base;
}
.build();
@Override
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand) {
@ -58,17 +55,17 @@ public class PanelModel implements IBakedModel {
PanelRenderProperties cl = ((IExtendedBlockState) state).getValue(PropertyComponents.INSTANCE);
if (cl == null) {
return base.getQuads(state, side, rand);
return ImmutableList.of();
}
modelCache.invalidateAll();//TODO remove
IELogger.info(modelCache.size());
AssembledBakedModel m = modelCache.getIfPresent(cl);
if (m == null) {
m = new AssembledBakedModel(cl, base, rand);
m = new AssembledBakedModel(cl);
modelCache.put(cl.copyOf(), m);
}
return m.getQuads(state, side, rand);
}
return base.getQuads(state, side, rand);
return ImmutableList.of();
}
@Override
@ -88,7 +85,7 @@ public class PanelModel implements IBakedModel {
@Override
public TextureAtlasSprite getParticleTexture() {
return base.getParticleTexture();
return PanelUtils.IRON_BLOCK_TEX;
}
@Override
@ -102,24 +99,21 @@ public class PanelModel implements IBakedModel {
}
public class AssembledBakedModel implements IBakedModel {
IBakedModel basic;
PanelRenderProperties components;
List<BakedQuad> quads;
List<BakedQuad> quadsDefault;
public AssembledBakedModel(PanelRenderProperties comp, IBakedModel b, long posRand) {
basic = b;
public AssembledBakedModel(PanelRenderProperties comp) {
components = comp;
}
@Override
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand) {
if (quads == null) {
quads = PanelUtils.generateQuads(components);
quads.addAll(basic.getQuads(state, side, rand));
quads = Collections.synchronizedList(quads);
if (quadsDefault == null) {
quadsDefault = PanelUtils.generateQuads(components);
quadsDefault = Collections.synchronizedList(quadsDefault);
}
return quads;
return quadsDefault;
}
@Override
@ -139,7 +133,7 @@ public class PanelModel implements IBakedModel {
@Override
public TextureAtlasSprite getParticleTexture() {
return basic.getParticleTexture();
return PanelUtils.IRON_BLOCK_TEX;
}
@Override

View file

@ -40,15 +40,12 @@ import java.util.*;
public class PanelModelLoader implements ICustomModelLoader {
public static final String RESOURCE_BASE = "models/block/";
public static final String RESOURCE_LOCATION = "smartmodel/panel_";
public static final Map<String, ResourceLocation> baseModels = new HashMap<>();
static {
baseModels.put("normal", new ResourceLocation(IndustrialWires.MODID, "block/panel_normal"));
}
public static final String RESOURCE_LOCATION = "smartmodel/panel";
@Override
public void onResourceManagerReload(IResourceManager resourceManager) {
PanelModel.modelCache.invalidateAll();
PanelUtils.IRON_BLOCK_TEX = null;
}
@Override
@ -61,37 +58,24 @@ public class PanelModelLoader implements ICustomModelLoader {
String resourcePath = modelLocation.getResourcePath();
int pos = resourcePath.indexOf(RESOURCE_LOCATION);
if (pos >= 0) {
pos += RESOURCE_LOCATION.length();
String name = resourcePath.substring(pos);
ResourceLocation r = baseModels.get(name);
if (r != null) {
return new PanelModelBase(r);
}
return new PanelModelBase();
}
return ModelLoaderRegistry.getMissingModel();
}
private class PanelModelBase implements IModel {
ResourceLocation base;
public PanelModelBase(ResourceLocation b) {
base = b;
}
@Override
public Collection<ResourceLocation> getDependencies() {
return ImmutableList.of(base);
return ImmutableList.of();
}
@Override
public Collection<ResourceLocation> getTextures() {
try {
List<ResourceLocation> ret = new ArrayList<>(ModelLoaderRegistry.getModel(base).getTextures());
List<ResourceLocation> ret = new ArrayList<>();
ret.add(new ResourceLocation("minecraft", "font/ascii"));
//ret.add(ModelLoader.White.LOCATION);
for (ResourceLocation res:ret) {
IELogger.info(res);
}
ret.add(new ResourceLocation("minecraft", "blocks/iron_block"));
return ret;
} catch (Exception e) {
throw new RuntimeException(e);
@ -101,12 +85,7 @@ public class PanelModelLoader implements ICustomModelLoader {
@Override
public IBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) {
try {
IModel model = ModelLoaderRegistry.getModel(base);
if (model instanceof OBJModel) {
OBJModel obj = (OBJModel) model;
model = obj.process(ImmutableMap.of("flip-v", "true"));
}
return new PanelModel(model.bake(state, format, bakedTextureGetter));
return new PanelModel();
} catch (Exception e) {
throw new RuntimeException(e);
}

View file

@ -25,6 +25,7 @@ import malte0811.industrialWires.client.RawQuad;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.EnumFacing;
@ -38,13 +39,16 @@ import java.util.ArrayList;
import java.util.List;
public final class PanelUtils {
public static TextureAtlasSprite IRON_BLOCK_TEX;
private PanelUtils() {}
public static List<BakedQuad> generateQuads(PropertyComponents.PanelRenderProperties components) {
//TODO different sizes of panels?
if (IRON_BLOCK_TEX==null) {
IRON_BLOCK_TEX = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/iron_block");
}
List<BakedQuad> ret = new ArrayList<>();
Matrix4 m4 = components.getPanelTopTransform().copy();
Matrix4 m4RotOnly = components.getPanelTopTransform();
Matrix4 m4 = components.getPanelTopTransform();
Matrix4 m4RotOnly = m4.copy();
m4RotOnly.invert();
m4RotOnly.transpose();
for (PanelComponent pc:components) {
@ -54,6 +58,17 @@ public final class PanelUtils {
ret.add(bakeQuad(bq, m4Here, m4RotOnly));
}
}
Matrix4 baseTrans = components.getPanelBaseTransform();
Matrix4 baseNorm = baseTrans.copy();
baseNorm.invert();
baseNorm.transpose();
List<RawQuad> rawOut = new ArrayList<>();
addTexturedBox(new Vector3f(0, 0, 0), new Vector3f(1, components.height, 1), rawOut, UV_FULL, IRON_BLOCK_TEX);
for (RawQuad bq:rawOut) {
ret.add(bakeQuad(bq, baseTrans, baseNorm));
}
return ret;
}
@ -103,32 +118,43 @@ public final class PanelUtils {
builder.put(e);
}
}
private static final float[] UV_FULL = {0, 0, 16, 16};
private static final float[] WHITE = {1, 1, 1, 1};
public static void addTexturedBox(Vector3f min, Vector3f size, List<RawQuad> out, float[] uvs, TextureAtlasSprite tex) {
addBox(WHITE, WHITE, WHITE, min, size, out, true, uvs, tex);
}
public static void addColoredBox(float[] colorTop, float[] colorSides, float[] colorBottom, Vector3f min, Vector3f size, List<RawQuad> out, boolean doBottom) {
addBox(colorTop, colorSides, colorBottom, min, size, out, doBottom, UV_FULL, ModelLoader.White.INSTANCE);
}
public static void addBox(float[] colorTop, float[] colorSides, float[] colorBottom, Vector3f min, Vector3f size, List<RawQuad> out, boolean doBottom, float[] uvs, TextureAtlasSprite tex) {
addQuad(out, new Vector3f(min.x, min.y+size.y, min.z), new Vector3f(min.x, min.y+size.y, min.z+size.z),
new Vector3f(min.x+size.x, min.y+size.y, min.z+size.z), new Vector3f(min.x+size.x, min.y+size.y, min.z),
EnumFacing.UP, colorTop);
EnumFacing.UP, colorTop, tex, uvs);
if (doBottom) {
addQuad(out, new Vector3f(min.x, min.y, min.z), new Vector3f(min.x+size.x, min.y, min.z),
new Vector3f(min.x+size.x, min.y, min.z+size.z), new Vector3f(min.x, min.y, min.z+size.z),
EnumFacing.UP, colorBottom);
EnumFacing.UP, colorBottom, tex, uvs);
}
addQuad(out, new Vector3f(min.x, min.y, min.z), new Vector3f(min.x, min.y, min.z+size.z),
new Vector3f(min.x, min.y+size.y, min.z+size.z), new Vector3f(min.x, min.y+size.y, min.z),
EnumFacing.WEST, colorSides);
EnumFacing.WEST, colorSides, tex, uvs);
addQuad(out, new Vector3f(min.x+size.x, min.y, min.z), new Vector3f(min.x+size.x, min.y+size.y, min.z),
new Vector3f(min.x+size.x, min.y+size.y, min.z+size.z), new Vector3f(min.x+size.x, min.y, min.z+size.z),
EnumFacing.EAST, colorSides);
EnumFacing.EAST, colorSides, tex, uvs);
addQuad(out, new Vector3f(min.x, min.y, min.z), new Vector3f(min.x, min.y+size.y, min.z),
new Vector3f(min.x+size.x, min.y+size.y, min.z), new Vector3f(min.x+size.x, min.y, min.z),
EnumFacing.NORTH, colorSides);
EnumFacing.NORTH, colorSides, tex, uvs);
addQuad(out, new Vector3f(min.x, min.y, min.z+size.z), new Vector3f(min.x+size.x, min.y, min.z+size.z),
new Vector3f(min.x+size.x, min.y+size.y, min.z+size.z), new Vector3f(min.x, min.y+size.y, min.z+size.z),
EnumFacing.SOUTH, colorSides);
EnumFacing.SOUTH, colorSides, tex, uvs);
}
private static final float[] UV_FULL = {0, 0, 1, 1};
public static void addQuad(List<RawQuad> out, Vector3f v0, Vector3f v1, Vector3f v2, Vector3f v3, EnumFacing dir, float[] color) {
public static void addColoredQuad(List<RawQuad> out, Vector3f v0, Vector3f v1, Vector3f v2, Vector3f v3, EnumFacing dir, float[] color) {
addQuad(out, v0, v1, v2, v3, dir, color, Minecraft.getMinecraft().getTextureMapBlocks().getTextureExtry(ModelLoader.White.LOCATION.toString()), UV_FULL);
}
public static void addQuad(List<RawQuad> out, Vector3f v0, Vector3f v1, Vector3f v2, Vector3f v3, EnumFacing dir, float[] color, TextureAtlasSprite tex, float[] uvs) {
Vec3i dirV = dir.getDirectionVec();
out.add(new RawQuad(v0, v1, v2, v3, dir, Minecraft.getMinecraft().getTextureMapBlocks().getTextureExtry(ModelLoader.White.LOCATION.toString()),
color, new Vector3f(dirV.getX(), dirV.getY(), dirV.getZ()), UV_FULL));
out.add(new RawQuad(v0, v1, v2, v3, dir, tex,
color, new Vector3f(dirV.getX(), dirV.getY(), dirV.getZ()), uvs));
}
}

View file

@ -25,7 +25,7 @@ public class RawModelFontRenderer extends FontRenderer {
public RawModelFontRenderer(GameSettings settings, ResourceLocation font, TextureManager manager, boolean isUnicode, float scale) {
super(settings, font, manager, isUnicode);
manager.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
this.scale = scale;
this.scale = scale/(9*16);
onResourceManagerReload(null);
}
@ -71,7 +71,7 @@ public class RawModelFontRenderer extends FontRenderer {
colorA[0] = r;
colorA[1] = g;
colorA[2] = b;
colorA[3] = a;
colorA[3] = 1;
}
@Override

View file

@ -4,10 +4,17 @@ import blusunrize.immersiveengineering.api.ApiUtils;
import blusunrize.immersiveengineering.api.energy.wires.IImmersiveConnectable;
import blusunrize.immersiveengineering.api.energy.wires.ImmersiveNetHandler;
import com.google.common.collect.ImmutableSet;
import malte0811.industrialWires.IndustrialWires;
import malte0811.industrialWires.blocks.controlpanel.BlockPanel;
import malte0811.industrialWires.blocks.controlpanel.BlockTypes_Panel;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.HashSet;
import java.util.Set;
import java.util.*;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
public final class MiscUtils {
private MiscUtils() {}
@ -45,4 +52,38 @@ public final class MiscUtils {
return ret;
}
public static List<BlockPos> discoverPanelParts(World w, BlockPos here) {
BiPredicate<BlockPos, Integer> isValid = (pos, count)->{
if (here.distanceSq(pos)>25||count>100||!w.isBlockLoaded(pos)) {
return false;
}
IBlockState state = w.getBlockState(pos);
return state.getBlock()== IndustrialWires.panel;
};
List<BlockPos> all = discoverLocal(w, here, isValid);
List<BlockPos> ret = new ArrayList<>();
for (BlockPos pos:all) {
if (w.getBlockState(pos).getValue(BlockPanel.type)!= BlockTypes_Panel.DUMMY) {
ret.add(pos);
}
}
return ret;
}
public static List<BlockPos> discoverLocal(World w, BlockPos here, BiPredicate<BlockPos, Integer> isValid) {
List<BlockPos> ret = new ArrayList<>();
List<BlockPos> open = new ArrayList<>();
open.add(here);
while (!open.isEmpty()) {
BlockPos curr = open.get(0);
ret.add(curr);
open.remove(0);
for (EnumFacing f:EnumFacing.VALUES) {
BlockPos next = curr.offset(f);
if (!open.contains(next)&&!ret.contains(next)&&isValid.test(next, ret.size())) {
open.add(next);
}
}
}
return ret;
}
}