IndustrialWires/src/main/java/malte0811/industrialWires/controlpanel/PanelComponent.java

252 lines
7.7 KiB
Java

/*
* This file is part of Industrial Wires.
* Copyright (C) 2016-2018 malte0811
* Industrial Wires is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* Industrial Wires 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with Industrial Wires. If not, see <http://www.gnu.org/licenses/>.
*/
package malte0811.industrialWires.controlpanel;
import malte0811.industrialWires.IndustrialWires;
import malte0811.industrialWires.blocks.controlpanel.TileEntityPanel;
import malte0811.industrialWires.client.RawQuad;
import malte0811.industrialWires.client.gui.GuiPanelCreator;
import malte0811.industrialWires.controlpanel.ControlPanelNetwork.IOwner;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public abstract class PanelComponent implements IOwner {
public static final float Y_DELTA = .001F;
protected static final float[] GRAY = {.8F, .8F, .8F};
protected static final int GRAY_INT = 0xFFD0D0D0;
protected static final float[] BLACK = {0, 0, 0, 1};
protected float panelHeight;
protected AxisAlignedBB aabb = null;
protected float x, y;
private final String type;
protected TileEntityPanel panel;
protected ControlPanelNetwork network;
protected PanelComponent(String type) {
this.type = type;
}
public static final Map<String, Supplier<PanelComponent>> baseCreaters = new HashMap<>();
public static void init() {
baseCreaters.put("lighted_button", LightedButton::new);
baseCreaters.put("label", Label::new);
baseCreaters.put("indicator_light", IndicatorLight::new);
baseCreaters.put("slider", Slider::new);
baseCreaters.put("variac", Variac::new);
baseCreaters.put("toggle_switch", ToggleSwitch::new);
baseCreaters.put("toggle_switch_covered", CoveredToggleSwitch::new);
baseCreaters.put("lock", Lock::new);
baseCreaters.put("panel_meter", PanelMeter::new);
baseCreaters.put(SevenSegDisplay.NAME, SevenSegDisplay::new);
//Check that all components implement equals+hashCode if in a dev env
boolean isDevEnv = "NBTTagCompound".equals(NBTTagCompound.class.getSimpleName());
if (isDevEnv) {
for (Supplier<PanelComponent> sup:baseCreaters.values()) {
PanelComponent comp = sup.get();
try {
comp.getClass().getDeclaredMethod("equals", Object.class);
comp.getClass().getDeclaredMethod("hashCode");
} catch (NoSuchMethodException e) {
throw new RuntimeException(comp.getClass()+" lacks equals or hasCode! This will break the cache!", e);
}
}
}
}
protected abstract void writeCustomNBT(NBTTagCompound nbt, boolean toItem);
protected abstract void readCustomNBT(NBTTagCompound nbt);
// DON'T OFFSET BY x, y IN THIS METHOD!
@SideOnly(Side.CLIENT)
public abstract List<RawQuad> getQuads();
@Nonnull
public abstract PanelComponent copyOf();
//well, only relative in the x/z directions
@Nonnull
public abstract AxisAlignedBB getBlockRelativeAABB();
public abstract void interactWith(Vec3d hitRelative, EntityPlayerMP player);
public abstract void update();
public abstract int getColor();
public abstract float getHeight();
public void setNetwork(ControlPanelNetwork net) {
this.network = net;
}
public void dropItems() {
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public void setX(float x) {
this.x = x;
aabb = null;
}
public void setY(float y) {
this.y = y;
aabb = null;
}
public void setPanelHeight(float panelHeight) {
this.panelHeight = panelHeight;
}
@Override
public BlockPos getBlockPos() {
return panel.getPos();
}
public void writeToNBT(NBTTagCompound nbt, boolean toItem) {
writeCustomNBT(nbt, toItem);
nbt.setFloat("x", getX());
nbt.setFloat("y", getY());
nbt.setFloat("panelHeight", panelHeight);
nbt.setString("type", type);
}
public static PanelComponent read(NBTTagCompound nbt) {
String type = nbt.getString("type");
if (baseCreaters.containsKey(type)) {
PanelComponent ret = baseCreaters.get(type).get();
ret.readFromNBT(nbt);
return ret;
} else {
IndustrialWires.logger.warn("Unknown panel component: " + type);
return null;
}
}
public final void readFromNBT(NBTTagCompound nbt) {
readCustomNBT(nbt);
setX(nbt.getFloat("x"));
setY(nbt.getFloat("y"));
setPanelHeight(nbt.getFloat("panelHeight"));
}
public boolean isValidPos(List<PanelComponent> components, float height, float angle) {
float h = PanelUtils.getHeightWithComponent(this, angle, height);
if (h < 0 || h > 1) {
return false;
}
AxisAlignedBB aabb = getBlockRelativeAABB();
if (aabb.minX < 0 || aabb.maxX > 1) {
return false;
}
if (aabb.minZ < 0 || aabb.maxZ > 1) {
return false;
}
for (PanelComponent pc : components) {
if (pc == this) {
continue;
}
AxisAlignedBB otherBB = pc.getBlockRelativeAABB();
if (PanelUtils.intersectXZ(aabb, otherBB)) {
return false;
}
}
return true;
}
@SideOnly(Side.CLIENT)
public void renderBox() {
GlStateManager.pushMatrix();
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);
GlStateManager.glLineWidth(2.0F);
GlStateManager.disableTexture2D();
GlStateManager.depthMask(false);
panel.getComponents().transformGLForTop(panel.getBlockPos());
RenderGlobal.drawSelectionBoundingBox(getBlockRelativeAABB().grow(0.002),
0.0F, 0.0F, 0.0F, 0.4F);
GlStateManager.depthMask(true);
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
GlStateManager.popMatrix();
}
@SideOnly(Side.CLIENT)
public abstract void renderInGUI(GuiPanelCreator gui);
@SideOnly(Side.CLIENT)
public void renderInGUIDefault(GuiPanelCreator gui, int color) {
color |= 0xff000000;
AxisAlignedBB aabb = getBlockRelativeAABB();
int left = (int) (gui.getX0() + aabb.minX * gui.panelSize);
int top = (int) (gui.getY0() + aabb.minZ * gui.panelSize);
int right = (int) (gui.getX0() + aabb.maxX * gui.panelSize);
int bottom = (int) (gui.getY0() + aabb.maxZ * gui.panelSize);
Gui.drawRect(left, top, right, bottom, color);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PanelComponent that = (PanelComponent) o;
if (Float.compare(that.panelHeight, panelHeight) != 0) return false;
if (Float.compare(that.x, x) != 0) return false;
if (Float.compare(that.y, y) != 0) return false;
return type.equals(that.type);
}
@Override
public int hashCode() {
int result = (panelHeight != +0.0f ? Float.floatToIntBits(panelHeight) : 0);
result = 31 * result + (x != +0.0f ? Float.floatToIntBits(x) : 0);
result = 31 * result + (y != +0.0f ? Float.floatToIntBits(y) : 0);
result = 31 * result + type.hashCode();
return result;
}
public void setPanel(TileEntityPanel tile) {
panel = tile;
}
}