/* * 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 . */ package malte0811.industrialWires.mech_mb; import blusunrize.immersiveengineering.common.IEContent; import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IPlayerInteraction; import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IRedstoneOutput; import blusunrize.immersiveengineering.common.items.ItemIETool; import blusunrize.immersiveengineering.common.util.ChatUtils; import blusunrize.immersiveengineering.common.util.Utils; import malte0811.industrialWires.IndustrialWires; import malte0811.industrialWires.blocks.converter.MechanicalMBBlockType; import malte0811.industrialWires.util.LocalSidedWorld; import malte0811.industrialWires.util.NBTKeys; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraftforge.oredict.OreDictionary; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.text.DecimalFormat; import static blusunrize.immersiveengineering.common.IEContent.blockMetalDecoration0; import static blusunrize.immersiveengineering.common.blocks.metal.BlockTypes_MetalDecoration0.RS_ENGINEERING; import static malte0811.industrialWires.blocks.converter.MechanicalMBBlockType.SPEEDOMETER; import static net.minecraft.util.EnumFacing.Axis.X; import static net.minecraft.util.EnumFacing.AxisDirection.POSITIVE; import static net.minecraft.util.math.BlockPos.ORIGIN; public class MechPartSpeedometer extends MechMBPart implements IPlayerInteraction, IRedstoneOutput { private double speedFor15RS = 2 * Waveform.EXTERNAL_SPEED; private int currentOutputLin = -1; private int currentOutputLog = -1; private double logFactor = 15 / Math.log(speedFor15RS + 1); { original.put(ORIGIN, blockMetalDecoration0 .getStateFromMeta(RS_ENGINEERING.getMeta())); } @Nullable private MechEnergy energy = null; @Override public void createMEnergy(MechEnergy e) { } @Override public double requestMEnergy(MechEnergy e) { energy = e; return 0; } @Override public void insertMEnergy(double added) { update(false); } private void update(boolean changedMax) { if (changedMax) { logFactor = 15 / Math.log(speedFor15RS + 1); } if (energy != null) { int newLin = roundHysteresis(currentOutputLin, 15 * energy.getSpeed() / speedFor15RS); int newLog = roundHysteresis(currentOutputLog, Math.log(energy.getSpeed() + 1) * logFactor); if (newLin != currentOutputLin || newLog != currentOutputLog) { currentOutputLin = newLin; currentOutputLog = newLog; world.markForUpdate(ORIGIN); } } } private int roundHysteresis(int old, double newExact) { double mod = newExact%1; final double THRESHOLD = .1; int floor = (int) Math.floor(newExact); if (floor == old) { return old; } if (oldTHRESHOLD) { return floor; } else if (old>newExact && mod<1-THRESHOLD) { return floor; } return old; } @Override public double getInertia() { return 60; } @Override public double getMaxSpeed() { return 2 * speedFor15RS; } @Override public void writeToNBT(NBTTagCompound out) { out.setDouble(NBTKeys.MAX_SPEED, speedFor15RS); } @Override public void readFromNBT(NBTTagCompound in) { speedFor15RS = in.getDouble(NBTKeys.MAX_SPEED); update(true); } @Override public ResourceLocation getRotatingBaseModel() { return new ResourceLocation(IndustrialWires.MODID, "block/mech_mb/shaft.obj"); } @Override public boolean canForm(LocalSidedWorld w) { IBlockState state = w.getBlockState(ORIGIN); return state.getBlock() == blockMetalDecoration0 && state.getValue(blockMetalDecoration0.property) == RS_ENGINEERING; } @Override public short getFormPattern(int offset) { return 0b000_010_000; } @Override public void breakOnFailure(MechEnergy energy) { world.setBlockState(ORIGIN, Blocks.AIR.getDefaultState()); } @Override public MechanicalMBBlockType getType() { return SPEEDOMETER; } private static ItemStack voltMeter = ItemStack.EMPTY; private static DecimalFormat format = new DecimalFormat("###.000"); @Override public boolean interact(@Nonnull EnumFacing side, @Nonnull EntityPlayer player, @Nonnull EnumHand hand, @Nonnull ItemStack heldItem, float hitX, float hitY, float hitZ) { if (voltMeter.isEmpty()) { voltMeter = new ItemStack(IEContent.itemTool, 1, ItemIETool.VOLTMETER_META); } if (Utils.isHammer(heldItem)) { if (!world.isRemote) { if (player.isSneaking()) { if (speedFor15RS > 1) { speedFor15RS--; } } else { speedFor15RS++; } ChatUtils.sendServerNoSpamMessages(player, new TextComponentTranslation(IndustrialWires.MODID + ".chat.maxSpeed", speedFor15RS)); update(true); } return true; } else if (OreDictionary.itemMatches(heldItem, voltMeter, false)) { if (!world.isRemote) { double speed = energy != null ? energy.getSpeed() : 0; ChatUtils.sendServerNoSpamMessages(player, new TextComponentTranslation(IndustrialWires.MODID + ".chat.currSpeed", format.format(speed), format.format(speed * 60D / (2 * Math.PI)))); } return true; } return false; } @Override public int getStrongRSOutput(@Nonnull IBlockState state, @Nonnull EnumFacing side) { if (side.getAxis() == X) { if (side.getAxisDirection() == POSITIVE) { return currentOutputLog; } else { return currentOutputLin; } } return 0; } @Override public boolean canConnectRedstone(@Nonnull IBlockState state, @Nonnull EnumFacing side) { return side.getAxis() == X; } @Override public AxisAlignedBB getBoundingBox(BlockPos offsetPart) { return new AxisAlignedBB(0, .1875, 0, 1, .8125, 1); } }