From 2d2a8a12c4a65609a869bb7da057d0d39dc6f2af Mon Sep 17 00:00:00 2001 From: LemADEC Date: Wed, 27 Aug 2014 17:52:47 +0200 Subject: [PATCH] Revert "Removing experimental/unstable/untested/debug stuff" This reverts commit b76ec1d361f76213e415908caf4665bec8a27971. --- src/assets/warpdrive/lua/power/startup | 1449 +++++++++++++++++ src/cr0s/WarpDrive/README.md | 9 +- src/cr0s/WarpDrive/WarpDrive.java | 109 ++ src/cr0s/WarpDrive/WarpDriveConfig.java | 14 + src/cr0s/WarpDrive/block/BlockDecorative.java | 98 ++ .../WarpDrive/block/BlockTransportBeacon.java | 57 + .../WarpDrive/block/ItemBlockDecorative.java | 40 + src/cr0s/WarpDrive/command/DebugCommand.java | 151 ++ src/cr0s/WarpDrive/item/ItemWarpUpgrade.java | 137 ++ .../WarpDrive/machines/BlockChunkLoader.java | 37 + .../WarpDrive/machines/BlockPowerLaser.java | 63 + .../WarpDrive/machines/BlockPowerReactor.java | 70 + .../WarpDrive/machines/BlockPowerStore.java | 54 + .../WarpDrive/machines/BlockTransporter.java | 47 + .../machines/TileEntityChunkLoader.java | 257 +++ .../machines/TileEntityPowerLaser.java | 218 +++ .../machines/TileEntityPowerReactor.java | 543 ++++++ .../machines/TileEntityPowerStore.java | 73 + .../machines/TileEntityTransporter.java | 497 ++++++ .../machines/WarpBlockContainer.java | 39 + 20 files changed, 3956 insertions(+), 6 deletions(-) create mode 100644 src/assets/warpdrive/lua/power/startup create mode 100644 src/cr0s/WarpDrive/block/BlockDecorative.java create mode 100644 src/cr0s/WarpDrive/block/BlockTransportBeacon.java create mode 100644 src/cr0s/WarpDrive/block/ItemBlockDecorative.java create mode 100644 src/cr0s/WarpDrive/command/DebugCommand.java create mode 100644 src/cr0s/WarpDrive/item/ItemWarpUpgrade.java create mode 100644 src/cr0s/WarpDrive/machines/BlockChunkLoader.java create mode 100644 src/cr0s/WarpDrive/machines/BlockPowerLaser.java create mode 100644 src/cr0s/WarpDrive/machines/BlockPowerReactor.java create mode 100644 src/cr0s/WarpDrive/machines/BlockPowerStore.java create mode 100644 src/cr0s/WarpDrive/machines/BlockTransporter.java create mode 100644 src/cr0s/WarpDrive/machines/TileEntityChunkLoader.java create mode 100644 src/cr0s/WarpDrive/machines/TileEntityPowerLaser.java create mode 100644 src/cr0s/WarpDrive/machines/TileEntityPowerReactor.java create mode 100644 src/cr0s/WarpDrive/machines/TileEntityPowerStore.java create mode 100644 src/cr0s/WarpDrive/machines/TileEntityTransporter.java diff --git a/src/assets/warpdrive/lua/power/startup b/src/assets/warpdrive/lua/power/startup new file mode 100644 index 00000000..7810ad48 --- /dev/null +++ b/src/assets/warpdrive/lua/power/startup @@ -0,0 +1,1449 @@ +monitor_textScale = 0.5 + +-- set alarm side if you need this +alarm_side = "top" + +Style = { + CDefault = colors.white, + BGDefault = colors.blue, + + CTitle = colors.black, + BGTitle = colors.cyan, + + CWarning = colors.white, + BGWarning = colors.red, + + CSuccess = colors.white, + BGSuccess = colors.lime, + + CDisabled = colors.gray, + BGDisabled = colors.blue +} + +if not term.isColor() then + print("Advanced computer required") + exit() +end + +----------- Monitor support + +function SetMonitorColorFrontBack(frontColor, backgroundColor) + term.setBackgroundColor(backgroundColor) + term.setTextColor(frontColor) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + monitor.setTextColor(frontColor) + monitor.setBackgroundColor(backgroundColor) + end + end +end + +function Write(text) + term.write(text) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + monitor.write(text) + end + end +end + +function SetCursorPos(x, y) + term.setCursorPos(x, y) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + monitor.setCursorPos(x, y) + end + end +end + +function SetColorDefault() + SetMonitorColorFrontBack(Style.CDefault, Style.BGDefault) +end + +function SetColorTitle() + SetMonitorColorFrontBack(Style.CTitle, Style.BGTitle) +end + +function SetColorWarning() + SetMonitorColorFrontBack(Style.CWarning, Style.BGWarning) +end + +function SetColorSuccess() + SetMonitorColorFrontBack(Style.CSuccess, Style.BGSuccess) +end + +function SetColorDisabled() + SetMonitorColorFrontBack(Style.CDisabled, Style.BGDisabled) +end + +function Clear() + clearWarningTick = -1 + SetColorDefault() + term.clear() + if monitors ~= nil then + for key,monitor in pairs(monitors) do + monitor.clear() + end + end + SetCursorPos(1,1) +end + +function ClearLine() + SetColorDefault() + term.clearLine() + if monitors ~= nil then + for key,monitor in pairs(monitors) do + monitor.clearLine() + end + end + SetCursorPos(1,1) +end + +function WriteLn(Text) + Write(Text) + local xt, yt = term.getCursorPos() + SetCursorPos(1, yt + 1) +end + +function WriteCentered(y, text) + SetCursorPos((51 - text:len()) / 2, y) + term.write(text) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + local sizeX, sizeY = monitor.getSize() + monitor.setCursorPos((sizeX - text:len()) / 2, y) + monitor.write(text) + end + end + local xt, yt = term.getCursorPos() + SetCursorPos(1, yt + 1) +end + +function ShowTitle(text) + Clear() + SetColorTitle() + WriteCentered(1, text) + SetColorDefault() +end + +function ShowMenu(Text) + Write(Text) + local xt, yt = term.getCursorPos() + for i = xt, 51 do + Write(" ") + end + SetCursorPos(1, yt+1) +end + +local clearWarningTick = -1 +function ShowWarning(Text) + SetColorWarning() + SetCursorPos((51 - Text:len() - 2) / 2, 19) + Write(" "..Text.." ") + SetColorDefault() + clearWarningTick = 5 +end +function ClearWarning(Text) + if clearWarningTick > 0 then + clearWarningTick = clearWarningTick - 1 + elseif clearWarningTick == 0 then + SetColorDefault() + SetCursorPos(1, 19) + ClearLine() + end +end + +----------- Formatting & popups + +function FormatFloat(value, nbchar) + return string.sub(string.format(" %f", value), -nbchar) +end +function FormatInteger(value, nbchar) + return string.sub(string.format(" %d", value), -nbchar) +end + +function Confirm() + ShowWarning("Are you sure? (y/n)") + local event, keycode = os.pullEvent("key") + if keycode == 21 then + return true + else + return false + end +end + +function boolToYesNo(bool) + if bool then + return "YES" + else + return "no" + end +end + +function readInputNumber(currentValue) + local inputAbort = false + local input = string.format(currentValue) + local x, y = term.getCursorPos() + repeat + ClearWarning() + SetColorDefault() + SetCursorPos(x, y) + Write(input .. " ") + local input = string.sub(input, -9) + + local params = { os.pullEventRaw() } + local eventName = params[1] + local side = params[2] + if side == nil then side = "none" end + if eventName == "key" then + local keycode = params[2] + if keycode >= 2 and keycode <= 10 then -- 1 to 9 + input = input .. string.format(keycode - 1) + elseif keycode == 11 or keycode == 82 then -- 0 & keypad 0 + input = input .. "0" + elseif keycode >= 79 and keycode <= 81 then -- keypad 1 to 3 + input = input .. string.format(keycode - 78) + elseif keycode >= 75 and keycode <= 87 then -- keypad 4 to 6 + input = input .. string.format(keycode - 71) + elseif keycode >= 71 and keycode <= 73 then -- keypad 7 to 9 + input = input .. string.format(keycode - 64) + elseif keycode == 14 then -- Backspace + input = string.sub(input, 1, string.len(input) - 1) + elseif keycode == 211 then -- Delete + input = "" + elseif keycode == 28 then -- Enter + inputAbort = true + else + ShowWarning("Key " .. keycode .. " is invalid") + end + elseif eventName == "char" then + -- drop it + elseif eventName == "reactorPulse" then + reactor_pulse(params[2]) + -- elseif eventName == "reactorDeactivation" then + -- ShowWarning("Reactor deactivated") + -- os.sleep(0.2) + -- elseif eventName == "reactorActivation" then + -- ShowWarning("Reactor activated") + -- os.sleep(0.2) + elseif eventName == "terminate" then + inputAbort = true + else + ShowWarning("Event '" .. eventName .. "', " .. side .. " is unsupported") + end + until inputAbort + if input == "" then + return currentValue + else + return tonumber(input) + end +end + +function readInputText(currentValue) + local inputAbort = false + local input = string.format(currentValue) + local x, y = term.getCursorPos() + repeat + ClearWarning() + SetColorDefault() + SetCursorPos(x, y) + Write(input .. " ") + input = string.sub(input, -30) + + local params = { os.pullEventRaw() } + local eventName = params[1] + local side = params[2] + if side == nil then side = "none" end + if eventName == "key" then + local keycode = params[2] + if keycode == 14 then -- Backspace + input = string.sub(input, 1, string.len(input) - 1) + elseif keycode == 211 then -- Delete + input = "" + elseif keycode == 28 then -- Enter + inputAbort = true + else + -- ShowWarning("Key " .. keycode .. " is invalid") + end + elseif eventName == "char" then + local char = params[2] + if char >= ' ' and char <= '~' then -- 1 to 9 + input = input .. char + else + ShowWarning("Char #" .. string.byte(char) .. " is invalid") + end + elseif eventName == "reactorPulse" then + reactor_pulse(params[2]) + -- elseif eventName == "reactorDeactivation" then + -- ShowWarning("Reactor deactivated") + -- os.sleep(0.2) + -- elseif eventName == "reactorActivation" then + -- ShowWarning("Reactor activated") + -- os.sleep(0.2) + elseif eventName == "terminate" then + inputAbort = true + else + ShowWarning("Event '" .. eventName .. "', " .. side .. " is unsupported") + end + until inputAbort + if input == "" then + return currentValue + else + return input + end +end + +----------- Redstone support + +local tblRedstoneState = {-- Remember redstone state on each side + ["top"] = rs.getInput("top"), + ["front"] = rs.getInput("front"), + ["left"] = rs.getInput("left"), + ["right"] = rs.getInput("right"), + ["back"] = rs.getInput("back"), + ["bottom"] = rs.getInput("bottom"), +} +local tblSides = {-- list all sides and offset coordinates + ["top" ] = { 3, 1}, + ["front" ] = { 1, 3}, + ["left" ] = { 3, 3}, + ["right" ] = { 5, 3}, + ["back" ] = { 5, 5}, + ["bottom"] = { 3, 5}, +} + +function redstone_event() + -- Event only returns nil so we need to check sides manually + local message = "" + for side, state in pairs(tblRedstoneState) do + if rs.getInput(side) ~= state then + -- print(side .. " is now " .. tostring(rs.getInput(side))) + message = message .. side .. " " + tblRedstoneState[side] = rs.getInput(side) + end + end + if message ~= "" then + message = "Redstone changed on " .. message + showWarning(message) + end +end + +----------- Cloaking support + +cloaking_highTier = false +cloaking_currentKey = 1 +function cloaking_key(keycode) + if keycode == 31 then -- S + cloaking_start() + return true + elseif keycode == 25 then -- P + cloaking_stop() + return true + elseif keycode == 20 then -- T + cloaking_highTier = not cloaking_highTier + return true + end + return false +end + +function cloaking_page() + ShowTitle(label .. " - Cloaking status") + + local cloakingcore = nil + if cloakingcores ~= nil then + if cloaking_currentKey > #cloakingcores then + cloaking_currentKey = 1 + end + cloakingcore = cloakingcores[cloaking_currentKey] + end + + SetCursorPos(1, 2) + if #cloakingcores == 0 then + SetColorDisabled() + Write("No cloaking core detected...") + elseif cloakingcore == nil then + SetColorWarning() + Write("Cloaking core " .. cloaking_currentKey .. " of " .. #cloakingcores .. " is invalid") + else + SetColorDefault() + Write("Cloaking core " .. cloaking_currentKey .. " of " .. #cloakingcores) + local isAssemblyValid = cloakingcore.isAssemblyValid() + local energy = cloakingcore.getEnergyLevel() + local isEnabled = true -- cloakingcore.isEnabled() + + if not isAssemblyValid then + SetColorWarning() + SetCursorPos(1, 3) + Write("Invalid assembly!") + SetColorDefault() + SetCursorPos(1, 4) + print("In each direction, you need to place exactly 2 Cloaking device coils, for a total of 12 coils.") + print("The 6 inner coils shall be exactly one block away from the core.") + print("The cloaking field will extend 5 blocks past the outer 6 coils.") + print("Power consumption scales with the amount of cloaked blocks.") + else + SetCursorPos(1, 4) + Write("Assembly is valid") + + if energy < 50000 then + SetColorWarning() + else + SetColorDefault() + end + SetCursorPos(1, 6) + Write("Energy level is " .. energy .. " EU") + + SetCursorPos(1, 8) + if isEnabled then + if energy <= 100 then + SetColorWarning() + else + SetColorSuccess() + end + Write("Cloak is enabled") + else + SetColorNormal() + Write("Cloak is disabled") + end + end + end + sleep(0.1) + cloaking_currentKey = cloaking_currentKey + 1 + + SetColorDefault() + SetCursorPos(1, 12) + Write(" -----------------------------------------------") + SetCursorPos(1, 13) + if cloaking_highTier then + Write("Cloak tier: HIGH") + else + Write("Cloak tier: low") + end + + SetColorTitle() + SetCursorPos(1, 16) + ShowMenu("S - Start cloaking, P - stoP cloaking") + SetCursorPos(1, 17) + ShowMenu("T - change low/high Tier") +end + +function cloaking_start() + for key,cloakingcore in pairs(cloakingcores) do + cloakingcore.disableCloakingField() + if cloaking_highTier then + cloakingcore.setFieldTier(2) + else + cloakingcore.setFieldTier(1) + end + cloakingcore.enableCloakingField() + end +end + +function cloaking_stop() + for key,cloakingcore in pairs(cloakingcores) do + cloakingcore.disableCloakingField() + end +end + +----------- Mining lasers support + +mining_currentKey = 1 +mining_layerOffset = 1 +mining_mineAll = true +mining_useDeuterium = false +function mining_key(keycode) + if keycode == 31 then -- S + mining_start() + return true + elseif keycode == 25 then -- P + mining_stop() + return true + elseif keycode == 30 then -- A + mining_mineAll = not mining_mineAll + return true + elseif keycode == 32 then -- D + mining_useDeuterium = not mining_useDeuterium + return true + elseif keycode == 74 then -- - + mining_layerOffset = mining_layerOffset - 1 + if mining_layerOffset < 1 then + mining_layerOffset = 1 + end + return true + elseif keycode == 78 then -- + + mining_layerOffset = mining_layerOffset + 1 + return true + end + return false +end + +function mining_page() + ShowTitle(label .. " - Mining status") + + local mininglaser = nil + if mininglasers ~= nil then + if mining_currentKey > #mininglasers then + mining_currentKey = 1 + end + mininglaser = mininglasers[mining_currentKey] + end + + SetCursorPos(1, 2) + if #mininglasers == 0 then + SetColorDisabled() + Write("No mining laser detected...") + elseif mininglaser == nil then + SetColorWarning() + Write("Mining laser " .. mining_currentKey .. " of " .. #mininglasers .. " is invalid") + else + SetColorDefault() + Write("Mining laser " .. mining_currentKey .. " of " .. #mininglasers) + local status, energy, currentLayer, mined, total = mininglaser.state() + SetCursorPos(1, 3) + Write("Status: " .. status .. " ") + SetCursorPos(1, 5) + Write("Energy level is " .. energy .. " EU") + SetCursorPos(1, 7) + Write("Mined " .. mined .. " out of " .. total .. " blocks at layer " .. currentLayer .. " ") + end + sleep(0.1) + mining_currentKey = mining_currentKey + 1 + + SetColorDefault() + SetCursorPos(1, 11) + Write(" -----------------------------------------------") + SetCursorPos(1, 12) + Write("Layer offset: " .. mining_layerOffset) + SetCursorPos(1, 13) + Write("Mine all: " .. boolToYesNo(mining_mineAll)) + SetCursorPos(1, 14) + Write("Use Deuterium: " .. boolToYesNo(mining_useDeuterium)) + + SetColorTitle() + SetCursorPos(1, 16) + ShowMenu("S - Start mining, P - stoP mining, A - mine All") + SetCursorPos(1, 17) + ShowMenu("D - use Deuterium, +/- - adjust offset") +end + +function mining_start() + for key,mininglaser in pairs(mininglasers) do + if not mininglaser.isMining() then + mininglaser.offset(mining_layerOffset) + if mining_mineAll then + if mining_useDeuterium then + mininglaser.quarry(mining_useDeuterium) + else + mininglaser.quarry() + end + else + if mining_useDeuterium then + mininglaser.mine(mining_useDeuterium) + else + mininglaser.mine() + end + end + end + end +end + +function mining_stop() + if #mininglasers == 0 then + SetColorWarning() + Write("No mining laser detected") + else + for key,mininglaser in pairs(mininglasers) do + SetCursorPos(1, 2 + key) + if not mininglaser.isMining() then + SetColorDisabled() + Write("Mining laser " .. key .. " of " .. #mininglasers .. " is already stopped") + else + mininglaser.stop() + SetColorSuccess() + Write("Mining laser " .. key .. " of " .. #mininglasers .. " has been stopped") + end + end + end +end + +----------- Configuration + +function data_save() + local file = fs.open("shipdata.txt", "w") + file.writeLine(textutils.serialize(data)) + file.close() +end + +function data_read() + if fs.exists("shipdata.txt") then + local file = fs.open("shipdata.txt", "r") + data = textutils.unserialize(file.readAll()) + file.close() + else + data = { } + end + if data.core_summon == nil then data.core_summon = false; end + if data.core_distance == nil then data.core_distance = 1; end + if data.core_direction == nil then data.core_direction = 0; end + if data.reactor_mode == nil then data.reactor_mode = 0; end + if data.reactor_rate == nil then data.reactor_rate = 100; end + if data.reactor_targetStability == nil then data.reactor_targetStability = 50; end + if data.reactor_laserAmount == nil then data.reactor_laserAmount = 10000; end +end + +function data_explode(separator, data) + local result, iCurrent, iNext + result = {} + iCurrent = 0 + if(#data == 1) then return {data} end + while true do + iNext = string.find(data, separator, iCurrent, true) + if iNext ~= nil then + table.insert(result, string.sub(data, iCurrent, iNext - 1)) + iCurrent = iNext + 1 + else + table.insert(result, string.sub(data, iCurrent)) + break + end + end + return result +end + +function data_setName() + if warpcore ~= nil then + ShowTitle("<==== Set ship name ====>") + else + ShowTitle("<==== Set name ====>") + end + + SetCursorPos(1, 2) + Write("Enter ship name: ") + label = readInputText(label) + os.setComputerLabel(label) + if warpcore ~= nil then + warpcore.set_core_frequency(label) + end + os.reboot() +end + +----------- Warpcore support + +core_front = 0 +core_right = 0 +core_up = 0 +core_back = 0 +core_left = 0 +core_down = 0 +core_isInHyper = false +core_minimumDistance = 1 +core_realDistance = 0 +core_jumpCost = 0 +core_shipSize = 0 + +function core_boot() + if data.core_summon then + warpcore.summon_all() + end + + core_front, core_right, core_up = warpcore.dim_getp() + core_back, core_left, core_down = warpcore.dim_getn() + core_isInHyper = warpcore.is_in_hyperspace() + repeat + X = warpcore.get_x() + sleep(0.3) + until X ~= nil + Y = warpcore.get_y() + Z = warpcore.get_z() + repeat + isAttached = warpcore.isAttached() + sleep(0.3) + until isAttached ~= false + + repeat + core_shipSize = warpcore.get_ship_size() + sleep(0.3) + until core_shipSize ~= nil + + core_computeRealDistance() + + warpcore.set_mode(1) +end + +function core_writeDirection() + if data.core_direction == 1 then + Write(" Direction = Up") + elseif data.core_direction == 2 then + Write(" Direction = Down") + elseif data.core_direction == 0 then + Write(" Direction = Front") + elseif data.core_direction == 180 then + Write(" Direction = Back") + elseif data.core_direction == 90 then + Write(" Direction = Left") + elseif data.core_direction == 255 then + Write(" Direction = Right") + end +end + +function core_computeRealDistance() + if core_isInHyper then + core_realDistance = data.core_distance * 100 + core_minimumDistance = 1 + core_jumpCost = (1000 * core_shipSize) + (1000 * data.core_distance) + else + if data.core_direction == 1 or data.core_direction == 2 then + core_minimumDistance = core_up + core_down + core_realDistance = data.core_distance + core_minimumDistance + elseif data.core_direction == 0 or data.core_direction == 180 then + core_minimumDistance = core_front + core_back + core_realDistance = data.core_distance + core_minimumDistance + elseif data.core_direction == 90 or data.core_direction == 255 then + core_minimumDistance = core_left + core_right + core_realDistance = data.core_distance + core_minimumDistance + end + core_minimumDistance = core_minimumDistance + 1 + core_jumpCost = (10 * core_shipSize) + (100 * data.core_distance) + end +end + +function core_computeNewCoordinates(cx, cy, cz) + local res = { x = cx, y = cy, z = cz } + if data.core_direction == 1 then + res.y = res.y + core_realDistance + elseif data.core_direction == 2 then + res.y = res.y - core_realDistance + end + local dx = warpcore.get_dx() + local dz = warpcore.get_dz() + if dx ~= 0 then + if data.core_direction == 0 then + res.x = res.x + (core_realDistance * dx) + elseif data.core_direction == 180 then + res.x = res.x - (core_realDistance * dx) + elseif data.core_direction == 90 then + res.z = res.z + (core_realDistance * dx) + elseif data.core_direction == 255 then + res.z = res.z - (core_realDistance * dx) + end + else + if data.core_direction == 0 then + res.z = res.z + (core_realDistance * dz) + elseif data.core_direction == 180 then + res.z = res.z - (core_realDistance * dz) + elseif data.core_direction == 90 then + res.x = res.x + (core_realDistance * dz) + elseif data.core_direction == 255 then + res.x = res.x - (core_realDistance * dz) + end + end + return res +end + +function core_warp() + rs.setOutput(alarm_side, true) + if Confirm() then + rs.setOutput(alarm_side, false) + warpcore.set_direction(data.core_direction) + if core_isInHyper then + warpcore.set_mode(2) + else + warpcore.set_mode(1) + end + warpcore.do_jump() + end + rs.setOutput(alarm_side, false) +end + +function core_page_setDistance() + ShowTitle("<==== Set distance ====>") + SetCursorPos(1, 2) + + data.core_distance = 0 + core_computeRealDistance() + local maximumDistance = core_minimumDistance + 127 + if core_isInHyper then + Write("Distance * 100 (min " .. core_minimumDistance .. ", max " .. maximumDistance .. "): ") + else + Write("Distance (min " .. core_minimumDistance .. ", max " .. maximumDistance .. "): ") + end + + data.core_distance = readInputNumber(data.core_distance) + if data.core_distance == nil then data.core_distance = 1 end + if data.core_distance < core_minimumDistance or data.core_distance > maximumDistance then + data.core_distance = 1 + ShowWarning("Wrong distance. Try again.") + os.pullEvent("key") + core_computeRealDistance() + else + if not core_isInHyper then + data.core_distance = data.core_distance - core_realDistance + end + warpcore.set_distance(data.core_distance) + core_computeRealDistance() + end +end + +function core_page_setDirection() + local drun = true + while(drun) do + ShowTitle("<==== Set direction ====>") + core_writeDirection() + term.setCursorPos(1, 16) + SetColorTitle() + ShowMenu("Use directional keys") + ShowMenu("W/S keys for Up/Down") + ShowMenu("Enter - confirm") + SetColorDeflt() + local event, keycode = os.pullEvent("key") + if keycode == 200 then + data.core_direction = 0 + elseif keycode == 17 then + data.core_direction = 1 + elseif keycode == 203 then + data.core_direction = 90 + elseif keycode == 205 then + data.core_direction = 255 + elseif keycode == 208 then + data.core_direction = 180 + elseif keycode == 31 then + data.core_direction = 2 + elseif keycode == 28 then + drun = false + end + end +end + +function core_page_setDimensions() + ShowTitle("<==== Set dimensions ====>") + Write(" Front (".. core_front ..") : ") + core_front = readInputNumber(core_front) + Write(" Right (".. core_right ..") : ") + core_right = readInputNumber(core_right) + Write(" Up (".. core_up ..") : ") + core_up = readInputNumber(core_up) + Write(" Back (".. core_back ..") : ") + core_back = readInputNumber(core_back) + Write(" Left (".. core_left ..") : ") + core_left = readInputNumber(core_left) + Write(" Down (".. core_down ..") : ") + core_down = readInputNumber(core_down) + Write("Setting dimensions...") + warpcore.dim_setp(core_front, core_right, core_up) + warpcore.dim_setn(core_back, core_left, core_down) + core_shipSize = warpcore.get_ship_size() +end + +function core_page_summon() + ShowTitle("<==== Summon players ====>") + local players = Explode(",", warpcore.get_attached_players()) + for i = 1, #players do + Show(i..". "..players[i]) + end + SetColorTitle() + ShowMenu("Enter player number") + ShowMenu("or press enter to summon everyone") + SetColorDeflt() + + Write(":") + local input = readInputNumber("") + if input == "" then + warpcore.summon_all() + else + input = tonumber(input) + warpcore.summon(input - 1) + end +end + +function core_page_jumpToBeacon() + ShowTitle("<==== Jump to beacon ====>") + + Write("Enter beacon frequency: ") + local freq = readInputText("") + rs.setOutput(alarm_side, true) + if Confirm() then + rs.setOutput(alarm_side, false) + warpcore.set_mode(4) + warpcore.set_beacon_frequency(freq) + warpcore.do_jump() + end + rs.setOutput(alarm_side, false) +end + +function core_page_jumpToGate() + ShowTitle("<==== Jump to Jumpgate ====>") + + Write("Enter jumpgate name: ") + local name = readInputText("") + rs.setOutput(alarm_side, true) + if Confirm() then + rs.setOutput(alarm_side, false) + warpcore.set_mode(6) + warpcore.set_target_jumpgate(name) + warpcore.do_jump() + end + rs.setOutput(alarm_side, false) +end + +function core_page() + ShowTitle(label .. " - Warpcore status") + if warpcore ~= nil then + WriteLn("Core:") + WriteLn(" x, y, z = " .. X .. ", " .. Y .. ", " .. Z) + local energy = warpcore.get_energy_level() + WriteLn(" Energy = " .. math.floor(energy / 1000000).." % ("..energy.."EU)") + WriteLn(" Attached players = " .. warpcore.get_attached_players()) + WriteLn("Dimensions:") + WriteLn(" Front, Right, Up = " .. core_front .. ", " .. core_right .. ", " .. core_up) + WriteLn(" Back, Left, Down = " .. core_back .. ", " .. core_left .. ", " .. core_down) + WriteLn(" Size = " .. core_weight .. " blocks") + WriteLn("core_warp data:") + core_writeDirection() + local dest = core_computeNewCoordinates(X, Y, Z) + WriteLn(" Distance = " .. core_realDistance .. " (" .. core_jumpCost .. "EU, " .. math.floor(energy / core_jumpCost) .. " jumps)") + WriteLn(" Dest.coordinates = " .. dest.x .. ", " .. dest.y .. ", " .. dest.z) + if data.core_summon then + WriteLn(" Summon after = Yes") + else + WriteLn(" Summon after = No") + end + else + ShowWarning("No warpcore controller detected") + end + + SetCursorPos(1, 15) + SetColorTitle() + ShowMenu("D - Dimensions, M - Toggle summon, N - Ship name") + ShowMenu("S - Set core_warp Data, J - Jump, G - Jump to JumpGate") + ShowMenu("B - Jump to Beacon, H - Jump to Hyperspace") + ShowMenu("C - core_page_summon crew") +end + +function core_key(keycode) + if keycode == 31 then + core_page_setDirection() + core_page_setDistance() + data_save() + elseif keycode == 50 then + if data.core_summon then + data.core_summon = false + else + data.core_summon = true + end + data_save() + elseif keycode == 32 then + core_page_setDimensions() + data_save() + elseif keycode == 36 then + core_warp() + elseif keycode == 46 then + core_page_summon() + elseif keycode == 48 then + core_page_jumpToBeacon() + elseif keycode == 34 then + core_page_jumpToGate() + elseif keycode == 35 then + rs.setOutput(alarm_side, true) + if Confirm() then + rs.setOutput(alarm_side, false) + warpcore.set_mode(5) + warpcore.do_jump() + end + rs.setOutput(alarm_side, false) + elseif keycode == 49 then + data_setName() + end +end + +----------- Reactor support + +reactor_output = 0 +function reactor_key(keycode) + if keycode == 31 then -- S + reactor_start() + return true + elseif keycode == 25 then -- P + reactor_stop() + return true + elseif keycode == 38 then -- L + reactor_laser() + return true + elseif keycode == 24 then -- O + data.reactor_mode = (data.reactor_mode + 1) % 4 + reactor_setMode() + data_save() + return true + elseif keycode == 34 then -- G + data.reactor_rate = data.reactor_rate / 10 + reactor_setMode() + data_save() + return true + elseif keycode == 20 then -- T + data.reactor_rate = data.reactor_rate * 10 + reactor_setMode() + data_save() + return true + elseif keycode == 36 then -- J + data.reactor_laserAmount = data.reactor_laserAmount / 10 + reactor_setLaser() + data_save() + return true + elseif keycode == 22 then -- U + data.reactor_laserAmount = data.reactor_laserAmount * 10 + reactor_setLaser() + data_save() + return true + elseif keycode == 74 then -- - + data.reactor_targetStability = data.reactor_targetStability - 1 + reactor_setTargetStability() + data_save() + return true + elseif keycode == 78 then -- + + data.reactor_targetStability = data.reactor_targetStability + 1 + reactor_setTargetStability() + data_save() + return true + elseif keycode == 46 then -- C + reactor_config() + data_save() + return true + end + return false +end + +function reactor_page() + ShowTitle(label .. " - Reactor status") + + SetCursorPos(1, 2) + if reactor == nil then + SetColorDisabled() + Write("Reactor not detected") + else + SetColorDefault() + Write("Reactor stability") + instabilities = { reactor.instability() } + average = 0 + for key,instability in pairs(instabilities) do + SetCursorPos(12, 2 + key) + stability = math.floor((100.0 - instability) * 10) / 10 + if stability >= data.reactor_targetStability then + SetColorSuccess() + else + SetColorWarning() + end + Write(FormatFloat(stability, 5) .. " %") + average = average + instability + end + average = average / #instabilities + + SetColorDefault() + energy = { reactor.energy() } + SetCursorPos(1, 7) + Write("Energy : ") + if energy[1] ~= nil then + Write(FormatInteger(energy[1], 10) .. " / " .. energy[2] .. " RF +" .. FormatInteger(reactor_output, 5) .. " RF/t") + else + Write("???") + end + SetCursorPos(1, 8) + Write("Outputing: ") + if energy[1] ~= nil then + Write(energy[3] .. " RF/t") + end + + SetColorDefault() + SetCursorPos(1, 9) + Write("Activated: ") + isActive = reactor.getActive() + if isActive then SetColorSuccess() else SetColorDefault() end + Write(boolToYesNo(isActive)) + end + + if #reactorlasers == 0 then + SetColorDisabled() + SetCursorPos(30, 2) + Write("Lasers not detected") + else + SetColorDefault() + SetCursorPos(30, 2) + Write("Lasers") + + for key,reactorlaser in pairs(reactorlasers) do + side = reactorlaser.side() + if side ~= nil then + side = side % 4 + SetColorDefault() + SetCursorPos(4, 3 + side) + Write("Side " .. side .. ":") + SetCursorPos(30, 3 + side) + energy = reactorlaser.energy() + if not reactorlaser.hasReactor() then + SetColorDisabled() + elseif energy > 3 * data.reactor_laserAmount then + SetColorSuccess() + else + SetColorWarning() + end + Write(FormatInteger(reactorlaser.energy(), 6)) + end + end + end + + SetColorDefault() + SetCursorPos(1, 10) + Write(" -----------------------------------------------") + SetCursorPos(1, 11) + Write("Output mode : ") + if data.reactor_mode == 0 then + SetColorDisabled() + Write("hold") + elseif data.reactor_mode == 1 then + Write("manual/unlimited") + elseif data.reactor_mode == 2 then + Write("surplus above " .. data.reactor_rate .. " RF") + else + Write("rated at " .. data.reactor_rate .. " RF") + end + SetColorDefault() + SetCursorPos( 1, 12) + Write("Target stability: " .. data.reactor_targetStability .. "%") + SetCursorPos(30, 12) + Write("Laser amount: " .. data.reactor_laserAmount) + + SetColorTitle() + SetCursorPos(1, 14) + ShowMenu("S - Start reactor, P - Stop reactor, L - Use lasers") + SetCursorPos(1, 15) + ShowMenu("O - Output mode, C - Configuration") + SetCursorPos(1, 16) + ShowMenu("+/- - Target stability, U/J - Laser amount") + SetCursorPos(1, 17) + ShowMenu("G/T - Output rate/threshold") +end + +function reactor_setMode() + if data.reactor_rate < 1 then + data.reactor_rate = 1 + elseif data.reactor_rate > 100000 then + data.reactor_rate = 100000 + end + if reactor ~= nil then + if data.reactor_mode == 0 then + reactor.release(false) + elseif data.reactor_mode == 1 then + reactor.release(true) + elseif data.reactor_mode == 2 then + reactor.releaseAbove(data.reactor_rate) + else + reactor.releaseRate(data.reactor_rate) + end + end +end + +function reactor_setLaser() + if data.reactor_laserAmount < 1 then + data.reactor_laserAmount = 1 + elseif data.reactor_laserAmount > 100000 then + data.reactor_laserAmount = 100000 + end +end + +function reactor_setTargetStability() + if data.reactor_targetStability < 1 then + data.reactor_targetStability = 1 + elseif data.reactor_targetStability > 100 then + data.reactor_targetStability = 100 + end +end + +function reactor_start() + if reactor ~= nil then + reactor_setMode() + reactor.setActive(true) + end +end + +function reactor_stop() + if reactor ~= nil then + reactor.setActive(false) + end +end + +function reactor_laser(side) + for key,reactorlaser in pairs(reactorlasers) do + if (side == nil) or (reactorlaser.side() == side) then + reactorlaser.sendLaser(data.reactor_laserAmount) + end + end +end + +function reactor_pulse(output) + reactor_output = output + local instabilities = { reactor.instability() } + for key,instability in pairs(instabilities) do + local stability = math.floor((100.0 - instability) * 10) / 10 + if stability < data.reactor_targetStability then + reactor_laser(key - 1) + end + end +end + +function reactor_config() + ShowTitle(label .. " - Reactor configuration") + + SetCursorPos(1, 2) + if reactor == nil then + SetColorDisabled() + Write("Reactor not detected") + else + SetColorDefault() + SetCursorPos(1, 4) + Write("Reactor output rate (" .. data.reactor_rate .. " RF): ") + data.reactor_rate = readInputNumber(data.reactor_rate) + reactor_setMode() + SetCursorPos(1, 5) + Write("Reactor output rate set") + + SetCursorPos(1, 7) + Write("Laser energy level (" .. data.reactor_laserAmount .. "): ") + data.reactor_laserAmount = readInputNumber(data.reactor_laserAmount) + reactor_setLaser() + SetCursorPos(1, 8) + Write("Laser energy level set") + + SetCursorPos(1, 10) + Write("Reactor target stability (" .. data.reactor_targetStability .. "%): ") + data.reactor_targetStability = readInputNumber(data.reactor_targetStability) + reactor_setTargetStability() + SetCursorPos(1, 11) + Write("Reactor target stability set") + end +end + +function reactor_init() + if reactor ~= nil then + local isActive, strMode, releaseRate = reactor.getActive() + if strMode == "OFF" then + data.reactor_mode = 0 + elseif strMode == "MANUAL" then + data.reactor_mode = 1 + elseif strMode == "ABOVE" then + data.reactor_mode = 2 + elseif strMode == "RATE" then + data.reactor_mode = 3 + else + data.reactor_mode = 0 + end + end +end + +----------- Boot sequence +label = os.getComputerLabel() +if not label then + label = "" .. os.getComputerID() +end + +-- initial scanning +monitors = {} +ShowTitle(label .. " - Connecting...") +WriteLn("") + +sides = peripheral.getNames() +reactor = nil +mininglasers = {} +reactorlasers = {} +cloakingcores = {} +warpcore = nil +for key,side in pairs(sides) do + sleep(0) + if peripheral.getType(side) == "monitor" then + WriteLn("Wrapping " .. side) + lmonitor = peripheral.wrap(side) + table.insert(monitors, lmonitor) + lmonitor.setTextScale(monitor_textScale) + end + if peripheral.getType(side) == "warpcore" then + WriteLn("Wrapping " .. side) + warpcore = peripheral.wrap(side) + end + if peripheral.getType(side) == "warpdriveReactor" then + WriteLn("Wrapping " .. side) + reactor = peripheral.wrap(side) + end + if peripheral.getType(side) == "warpdriveReactorLaser" then + WriteLn("Wrapping " .. side) + table.insert(reactorlasers, peripheral.wrap(side)) + end + if peripheral.getType(side) == "mininglaser" then + WriteLn("Wrapping " .. side) + table.insert(mininglasers, peripheral.wrap(side)) + end + if peripheral.getType(side) == "cloakingdevicecore" then + WriteLn("Wrapping " .. side) + table.insert(cloakingcores, peripheral.wrap(side)) + end +end +-- sleep(1) + +-- read configuration +data_read() + +if not os.getComputerLabel() and (warpcore ~= nil or reactor ~= nil) then + data_setName() +end + +-- peripherals status +function connections_page() + ShowTitle(label .. " - Connections") + + WriteLn("") + if #monitors == 0 then + SetColorDisabled() + WriteLn("No Monitor detected") + elseif #monitors == 1 then + SetColorSuccess() + WriteLn("1 monitor detected") + else + SetColorSuccess() + WriteLn(#monitors .. " Monitors detected") + end + + if warpcore == nil then + SetColorDisabled() + WriteLn("No warpcore controller detected") + else + SetColorSuccess() + WriteLn("Warpcore controller detected") + end + + if reactor == nil then + SetColorDisabled() + WriteLn("No reactor detected") + else + SetColorSuccess() + WriteLn("Warpcore reactor detected") + end + + if #reactorlasers == 0 then + SetColorDisabled() + WriteLn("No reactor stabilisation laser detected") + elseif #reactorlasers == 1 then + SetColorSuccess() + WriteLn("1 reactor stabilisation laser detected") + else + SetColorSuccess() + WriteLn(#reactorlasers .. " reactor stabilisation lasers detected") + end + + if #mininglasers == 0 then + SetColorDisabled() + WriteLn("No mining laser detected") + elseif #mininglasers == 1 then + SetColorSuccess() + WriteLn("1 mining laser detected") + else + SetColorSuccess() + WriteLn(#mininglasers .. " mining lasers detected") + end + + if #cloakingcores == 0 then + SetColorDisabled() + WriteLn("No cloaking core detected") + elseif #cloakingcores == 1 then + SetColorSuccess() + WriteLn("1 cloaking core detected") + else + SetColorSuccess() + WriteLn(#cloakingcores .. " cloaking cores detected") + end +end + +-- waiting for warp core to boot up +if warpcore ~= nil then + core_boot() +end + +function menu_common() + SetCursorPos(1, 18) + SetColorTitle() + ShowMenu("1 Reactor, 2 Cloak, 3 Mining, 4 Core, 5 Laser, eXit") +end + +reactor_init() +abort = false +refresh = true +page = connections_page +keyHandler = nil +repeat + ClearWarning() + if refresh then + Clear() + page() + menu_common() + refresh = false + end + params = { os.pullEventRaw() } + eventName = params[1] + side = params[2] + if side == nil then side = "none" end + if eventName == "key" then + keycode = params[2] + if keycode == 45 then -- x for eXit + os.pullEventRaw() + abort = true + elseif keycode == 2 then -- 1 + page = reactor_page + keyHandler = reactor_key + refresh = true + elseif keycode == 3 then -- 2 + page = cloaking_page + keyHandler = cloaking_key + refresh = true + elseif keycode == 4 then -- 3 + page = mining_page + keyHandler = mining_key + refresh = true + elseif keycode == 5 then -- 4 + page = core_page + keyHandler = core_key + refresh = true + elseif keycode == 6 then -- 6 + page = laser_page + keyHandler = laser_key + refresh = true + elseif keyHandler ~= nil and keyHandler(keycode) then + refresh = true + os.sleep(0) + else + ShowWarning("Key " .. keycode .. " is invalid") + os.sleep(0.2) + end + -- func(unpack(params)) + -- abort, refresh = false, false + elseif eventName == "char" then + -- drop it + elseif eventName == "reactorPulse" then + reactor_pulse(params[2]) + refresh = (page == reactor_page) +-- elseif eventName == "reactorDeactivation" then +-- ShowWarning("Reactor deactivated") +-- os.sleep(0.2) +-- elseif eventName == "reactorActivation" then +-- ShowWarning("Reactor activated") +-- os.sleep(0.2) + elseif eventName == "terminate" then + abort = true + else + ShowWarning("Event '" .. eventName .. "', " .. side .. " is unsupported") + refresh = true + os.sleep(0.2) + end +until abort + +-- deactivate summon all on exit +if data.core_summon then + data.core_summon = false + data_save() +end + +SetMonitorColorFrontBack(colors.white, colors.black) +print() diff --git a/src/cr0s/WarpDrive/README.md b/src/cr0s/WarpDrive/README.md index d879d4f2..1140ec77 100644 --- a/src/cr0s/WarpDrive/README.md +++ b/src/cr0s/WarpDrive/README.md @@ -3,14 +3,11 @@ WarpDrive A warp drive mod for minecraft -See mcmod.info for credits - Minecraft forum: http://www.minecraftforum.net/topic/1938578-164-warpdrive-mod-ships-space-lasers Mod Showcase: https://www.youtube.com/watch?v=9pUSZPEMc1g - http://www.twitch.tv/pyrostasis/c/4571421 Wiki: http://wiki.kubach.tk/ @@ -19,9 +16,9 @@ Installation ============ 1. Download fresh build: http://kubach.tk/1.6.4/WarpDrive.zip 2. Download fresh Core build: http://kubach.tk/1.6.4/WarpDriveCore.jar -3. Install last version of IC2, Applied Energistics, CoFHCore and Computer Craft +3. Install last version of IC2 and Computer Craft Contact Us -========== +============= * Visit our IRC channel on EsperNet: irc://chaos.esper.net/WarpDrive -* Or PM me: http://www.minecraftforum.net/user/1133830-anon1644/ \ No newline at end of file +* Or PM me: http://www.minecraftforum.net/user/1133830-anon1644/ diff --git a/src/cr0s/WarpDrive/WarpDrive.java b/src/cr0s/WarpDrive/WarpDrive.java index c44b6035..97965db0 100644 --- a/src/cr0s/WarpDrive/WarpDrive.java +++ b/src/cr0s/WarpDrive/WarpDrive.java @@ -82,14 +82,21 @@ public class WarpDrive implements LoadingCallback { public static Block cloakCoilBlock; public static Block transporterBlock; public static Block reactorMonitorBlock; + public static Block powerReactorBlock; + public static Block powerLaserBlock; + public static Block powerStoreBlock; public static Block airBlock; public static Block gasBlock; public static Block iridiumBlock; + public static Block transportBeaconBlock; + public static Block chunkLoaderBlock; + public static BlockDecorative decorativeBlock; public static Item reactorLaserFocusItem; public static ItemWarpComponent componentItem; + public static ItemWarpUpgrade upgradeItem; public static EnumArmorMaterial armorMaterial = EnumHelper.addArmorMaterial("WARP", 5, new int[]{1, 3, 2, 1}, 15); public static ItemWarpArmor helmetItem; @@ -146,6 +153,7 @@ public class WarpDrive implements LoadingCallback { @SideOnly(Side.CLIENT) @EventHandler public void init(FMLInitializationEvent event) { +// FIXME FMLInterModComms.sendMessage("Waila", "register", "cr0s.WarpDrive.client.WailaHandler.callbackRegister"); } public static void print(String out) { @@ -272,12 +280,45 @@ public class WarpDrive implements LoadingCallback { GameRegistry.registerBlock(cloakCoilBlock, "cloakCoilBlock"); + // TRANSPORTER + transporterBlock = new BlockTransporter(WarpDriveConfig.transporterID,Material.rock); + + GameRegistry.registerBlock(transporterBlock, "transporter"); + GameRegistry.registerTileEntity(TileEntityTransporter.class,"transporter"); + // REACTOR MONITOR reactorMonitorBlock = new BlockLaserReactorMonitor(WarpDriveConfig.reactorMonitorID, Material.rock); GameRegistry.registerBlock(reactorMonitorBlock, "reactorMonitor"); GameRegistry.registerTileEntity(TileEntityLaserReactorMonitor.class,"reactorMonitor"); + // TRANSPORT BEACON + transportBeaconBlock = new BlockTransportBeacon(WarpDriveConfig.transportBeaconID); + + GameRegistry.registerBlock(transportBeaconBlock, "transportBeacon"); + + // POWER REACTOR, LASER, STORE + powerReactorBlock = new BlockPowerReactor(WarpDriveConfig.powerReactorID); + GameRegistry.registerBlock(powerReactorBlock,"powerReactor"); + GameRegistry.registerTileEntity(TileEntityPowerReactor.class, "powerReactor"); + + powerLaserBlock = new BlockPowerLaser(WarpDriveConfig.powerLaserID); + GameRegistry.registerBlock(powerLaserBlock, "powerLaser"); + GameRegistry.registerTileEntity(TileEntityPowerLaser.class, "powerLaser"); + + powerStoreBlock = new BlockPowerStore(WarpDriveConfig.powerStoreID); + GameRegistry.registerBlock(powerStoreBlock,"powerStore"); + GameRegistry.registerTileEntity(TileEntityPowerStore.class, "powerStore"); + + // CHUNK LOADER + chunkLoaderBlock = new BlockChunkLoader(WarpDriveConfig.chunkLoaderID); + GameRegistry.registerBlock(chunkLoaderBlock, "chunkLoader"); + GameRegistry.registerTileEntity(TileEntityChunkLoader.class, "chunkLoader"); + + // DECORATIVE + decorativeBlock = new BlockDecorative(WarpDriveConfig.decorativeID); + GameRegistry.registerBlock(decorativeBlock, ItemBlockDecorative.class, "decorative"); + // REACTOR LASER FOCUS reactorLaserFocusItem = new ItemReactorLaserFocus(WarpDriveConfig.reactorLaserFocusID); GameRegistry.registerItem(reactorLaserFocusItem, "reactorLaserFocus"); @@ -292,6 +333,9 @@ public class WarpDrive implements LoadingCallback { airCanisterItem = new ItemWarpAirCanister(WarpDriveConfig.airCanisterID); GameRegistry.registerItem(airCanisterItem, "airCanisterFull"); + upgradeItem = new ItemWarpUpgrade(WarpDriveConfig.upgradeID); + GameRegistry.registerItem(upgradeItem, "upgrade"); + proxy.registerEntities(); ForgeChunkManager.setForcedChunkLoadingCallback(instance, instance); @@ -337,6 +381,8 @@ public class WarpDrive implements LoadingCallback { private static void initVanillaRecipes() { componentItem.registerRecipes(); + decorativeBlock.initRecipes(); + upgradeItem.initRecipes(); //WarpCore GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(warpCore), false, "ipi", "ici", "idi", @@ -449,6 +495,42 @@ public class WarpDrive implements LoadingCallback { 'r', Item.redstone, 'n', Item.goldNugget)); + //Power Laser + GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(powerLaserBlock), false, "iii", "ilg", "ici", + 'i', Item.ingotIron, + 'g', Block.glass, + 'c', componentItem.getIS(5), + 'l', componentItem.getIS(3))); + + //Power Reactor + GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(powerReactorBlock), false, "ipi", "gog", "ici", + 'i', Item.ingotIron, + 'g', Block.glass, + 'o', componentItem.getIS(4), + 'c', componentItem.getIS(5), + 'p', componentItem.getIS(6))); + + //Power Store + GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(powerStoreBlock), false, "ipi", "isi", "ici", + 'i', Item.ingotIron, + 's', componentItem.getIS(7), + 'c', componentItem.getIS(5), + 'p', componentItem.getIS(6))); + + //Transport Beacon + GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(transportBeaconBlock), false, " e ", "ldl", " s ", + 'e', Item.enderPearl, + 'l', "dyeBlue", + 'd', Item.diamond, + 's', Item.stick)); + + //Chunk Loader + GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(chunkLoaderBlock), false, "ipi", "ici", "ifi", + 'i', Item.ingotIron, + 'p', componentItem.getIS(6), + 'c', componentItem.getIS(0), + 'f', componentItem.getIS(5))); + //Helmet GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(helmetItem), false, "iii", "iwi", "gcg", 'i', Item.ingotIron, @@ -459,13 +541,16 @@ public class WarpDrive implements LoadingCallback { private static void initAETERecipes() { ItemStack redstoneEnergycell = GameRegistry.findItemStack("ThermalExpansion", "cellReinforced", 1); + ItemStack resonantEnergycell = GameRegistry.findItemStack("ThermalExpansion", "cellResonant", 1); ItemStack bucketEnder = GameRegistry.findItemStack("ThermalExpansion", "bucketEnder", 1); ItemStack fluixCrystal = WarpDriveConfig.getAEMaterial("matFluxCrystal"); + ItemStack quantumEntangledSingularity = WarpDriveConfig.getAEMaterial("matQuantumEntangledSingularity"); ItemStack vibrantQuartzGlass = WarpDriveConfig.getAEBlock("blkQuartzLamp"); vibrantQuartzGlass.setItemDamage(4); ItemStack antimatter = GameRegistry.findItemStack("ResonantInduction|Atomic", "antimatter", 1); antimatter.setItemDamage(0); ItemStack floppy = GameRegistry.findItemStack("ComputerCraft", "disk", 1); + ItemStack ultimateLappack = new ItemStack(WarpDriveConfig.GS_ultimateLappack, 1, 1); // top = advancedCircuit, redstoneEnergycell, advancedCircuit // middle = fluix crystal, advancedMachine, fluix crystal @@ -485,6 +570,29 @@ public class WarpDrive implements LoadingCallback { 'c', WarpDriveConfig.getIC2Item("advancedCircuit"), 'o', floppy, 'f', fluixCrystal); + + // top = Iridium plate, Resonant Energycell, Iridium plate + // middle = Singularity, 125 milligram antimatter, Singularity + // bottom = Iridium plate, Ultimate lappack, Iridium plate + GameRegistry.addRecipe(new ItemStack(powerReactorBlock), "iri", "sas", "ili", + 'i', WarpDriveConfig.getIC2Item("iridiumPlate"), + 's', quantumEntangledSingularity, + 'a', antimatter, + 'l', ultimateLappack, + 'r', resonantEnergycell); + + // top = Advanced circuit, Advanced alloy, Advanced alloy + // middle = Advanced circuit, Warp drive laser, Vibrant quartz glass + // bottom = Advanced circuit, Certus quartz tank, Advanced alloy + ItemStack isMiningLaserBlock = new ItemStack(miningLaserBlock.blockID, 1, 0); + ItemStack isCertusQuartzTank = new ItemStack(WarpDriveConfig.AEExtra_certusQuartzTank.blockID, 1, 0); + + GameRegistry.addRecipe(new ItemStack(powerLaserBlock), "caa", "czg", "cta", + 'c', WarpDriveConfig.getIC2Item("advancedCircuit"), + 'a', WarpDriveConfig.getIC2Item("advancedAlloy"), + 'z', isMiningLaserBlock, + 't', isCertusQuartzTank, + 'g', vibrantQuartzGlass); } private static void initIC2Recipes() { @@ -622,6 +730,7 @@ public class WarpDrive implements LoadingCallback { event.registerServerCommand(new SpaceTpCommand()); event.registerServerCommand(new InvisibleCommand()); event.registerServerCommand(new JumpgateCommand()); + event.registerServerCommand(new DebugCommand()); } public Ticket registerChunkLoadTE(WarpChunkTE te, boolean refreshLoading) { diff --git a/src/cr0s/WarpDrive/WarpDriveConfig.java b/src/cr0s/WarpDrive/WarpDriveConfig.java index a2fe03ea..3495e380 100644 --- a/src/cr0s/WarpDrive/WarpDriveConfig.java +++ b/src/cr0s/WarpDrive/WarpDriveConfig.java @@ -43,8 +43,15 @@ public class WarpDriveConfig public static int cloakCoreID; public static int cloakCoilID; public static int laserTreeFarmID; + public static int transporterID; + public static int transportBeaconID; public static int reactorLaserFocusID; public static int reactorMonitorID; + public static int powerReactorID; + public static int powerLaserID; + public static int powerStoreID; + public static int chunkLoaderID; + public static int decorativeID; // Items public static int componentID; @@ -447,7 +454,14 @@ public class WarpDriveConfig cloakCoreID = config.getBlock("cloakcore", 517).getInt(); cloakCoilID = config.getBlock("cloakcoil", 518).getInt(); laserTreeFarmID = config.getBlock("lasertreefarm", 519).getInt(); + transporterID = config.getBlock("transporter", 520).getInt(); + transportBeaconID = config.getBlock("transportBeacon", 521).getInt(); reactorMonitorID = config.getBlock("reactorMonitor", 522).getInt(); + powerLaserID = config.getBlock("powerLaser", 523).getInt(); + powerReactorID = config.getBlock("powerReactor", 524).getInt(); + powerStoreID = config.getBlock("powerStore", 525).getInt(); + chunkLoaderID = config.getBlock("chunkLoader", 526).getInt(); + decorativeID = config.getBlock("decorative",527).getInt(); reactorLaserFocusID = config.getItem("reactorLaserFocus", 8700).getInt(); componentID = config.getItem("component", 8701).getInt(); diff --git a/src/cr0s/WarpDrive/block/BlockDecorative.java b/src/cr0s/WarpDrive/block/BlockDecorative.java new file mode 100644 index 00000000..6ee13676 --- /dev/null +++ b/src/cr0s/WarpDrive/block/BlockDecorative.java @@ -0,0 +1,98 @@ +package cr0s.WarpDrive.block; + +import java.util.List; + +import cpw.mods.fml.common.registry.GameRegistry; + +import cr0s.WarpDrive.WarpDrive; + +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Icon; +import net.minecraftforge.oredict.ShapedOreRecipe; + +public class BlockDecorative extends Block +{ + public static enum decorativeTypes { Plain , Energized , Network }; + private ItemStack[] isCache = new ItemStack[decorativeTypes.values().length]; + private Icon[] iconBuffer = new Icon[decorativeTypes.values().length]; + + public BlockDecorative(int par1) + { + super(par1, Material.iron); + setHardness(0.5f); + setStepSound(Block.soundMetalFootstep); + setCreativeTab(WarpDrive.warpdriveTab); + } + + public boolean isValidDamage(int damage) + { + return damage >= 0 && damage < decorativeTypes.values().length; + } + + @Override + public void getSubBlocks(int par1, CreativeTabs par2CreativeTabs, List par3List) + { + for(decorativeTypes val: decorativeTypes.values()) + par3List.add(new ItemStack(par1, 1, val.ordinal())); + } + + @Override + public void registerIcons(IconRegister ir) + { + for(decorativeTypes val: decorativeTypes.values()) + iconBuffer[val.ordinal()] = ir.registerIcon("warpdrive:decorative" + val.toString()); + } + + @Override + public Icon getIcon(int side, int damage) + { + if(isValidDamage(damage)) + return iconBuffer[damage]; + return iconBuffer[0]; + } + + @Override + public int damageDropped(int damage) + { + return damage; + } + + public ItemStack getIS(int damage) + { + if(!isValidDamage(damage)) + return null; + + if(isCache[damage] == null) + isCache[damage] = getISNoCache(damage); + return isCache[damage]; + } + + public ItemStack getISNoCache(int damage, int amount) + { + if(!isValidDamage(damage)) + return null; + + return new ItemStack(WarpDrive.decorativeBlock,amount,damage); + } + + public ItemStack getISNoCache(int damage) + { + return getISNoCache(damage,1); + } + + public void initRecipes() + { + GameRegistry.addRecipe(new ShapedOreRecipe(getISNoCache(0,8),false, "sss","scs","sss", + 's', Block.stone, + 'c', WarpDrive.componentItem.getIS(0))); + + GameRegistry.addRecipe(new ShapedOreRecipe(getISNoCache(2,8),false, "sss","scs","sss", + 's', getIS(0), + 'c', WarpDrive.componentItem.getIS(5))); + } + +} diff --git a/src/cr0s/WarpDrive/block/BlockTransportBeacon.java b/src/cr0s/WarpDrive/block/BlockTransportBeacon.java new file mode 100644 index 00000000..468c9738 --- /dev/null +++ b/src/cr0s/WarpDrive/block/BlockTransportBeacon.java @@ -0,0 +1,57 @@ +package cr0s.WarpDrive.block; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import cr0s.WarpDrive.WarpDrive; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +public class BlockTransportBeacon extends Block { + public BlockTransportBeacon(int par1) { + super(par1, Material.iron); + setHardness(0.5F); + setStepSound(Block.soundMetalFootstep); + setCreativeTab(WarpDrive.warpdriveTab); + setUnlocalizedName("warpdrive.blocks.transportBeacon"); + } + + @Override + public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) { + return null; + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IconRegister par1IconRegister) { + this.blockIcon = par1IconRegister.registerIcon("warpdrive:transportBeacon"); + } + + @Override + public boolean isOpaqueCube() { + return false; + } + + @Override + public boolean renderAsNormalBlock() { + return false; + } + + @Override + public int getRenderType() { + return 2; + } + + @Override + public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3) { + float f = 0.065F; + this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.6F, 0.5F + f); + + return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3); + } +} diff --git a/src/cr0s/WarpDrive/block/ItemBlockDecorative.java b/src/cr0s/WarpDrive/block/ItemBlockDecorative.java new file mode 100644 index 00000000..45c1c4c8 --- /dev/null +++ b/src/cr0s/WarpDrive/block/ItemBlockDecorative.java @@ -0,0 +1,40 @@ +package cr0s.WarpDrive.block; + +import java.util.List; + +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; + +public class ItemBlockDecorative extends ItemBlock +{ + + public ItemBlockDecorative(int par1) + { + super(par1); + setHasSubtypes(true); + setUnlocalizedName("warpdrive.block.decorative"); + } + + @Override + public int getMetadata (int damage) + { + return damage; + } + + @Override + public void getSubItems(int par1, CreativeTabs par2CreativeTabs, List par3List) + { + for(int i = 0; i < BlockDecorative.decorativeTypes.values().length;i++) + par3List.add(new ItemStack(par1,1,i)); + } + + @Override + public String getUnlocalizedName(ItemStack itemstack) + { + if(itemstack == null) + return getUnlocalizedName(); + return "tile.warpdrive.decorative." + BlockDecorative.decorativeTypes.values()[itemstack.getItemDamage()].toString(); + } + +} diff --git a/src/cr0s/WarpDrive/command/DebugCommand.java b/src/cr0s/WarpDrive/command/DebugCommand.java new file mode 100644 index 00000000..de21f75e --- /dev/null +++ b/src/cr0s/WarpDrive/command/DebugCommand.java @@ -0,0 +1,151 @@ +package cr0s.WarpDrive.command; + +import cpw.mods.fml.common.FMLCommonHandler; +import cr0s.WarpDrive.WarpDriveConfig; +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; + +/* +* /wdebug +*/ + +public class DebugCommand extends CommandBase +{ + @Override + public String getCommandName() + { + return "wdebug"; + } + + @Override + public int getRequiredPermissionLevel() + { + return 2; + } + + @Override + public String getCommandUsage(ICommandSender par1ICommandSender) + { + return "/" + getCommandName() + " ...\n" + + "dimension: 0/world, 2/space, 3/hyperspace\n" + + "coordinates: x,y,z\n" + + "action: I(nvalidate), V(alidate), A(set air), R(emoveEntity), P(setBlock), S(etEntity)"; + } + + @Override + public void processCommand(ICommandSender icommandsender, String[] params) + { + EntityPlayerMP player = (EntityPlayerMP)icommandsender; + if(params.length > 6 ) + { + int dim, x, y, z, blockId, metadata; + String actions; + try + { + String par = params[0].toLowerCase(); + if (par.equals("world") || par.equals("overworld") || par.equals("0")) + { + dim = 0; + } + else if (par.equals("nether") || par.equals("thenether") || par.equals("-1")) + { + dim = -1; + } + else if (par.equals("s") || par.equals("space")) + { + dim = WarpDriveConfig.G_SPACE_DIMENSION_ID; + } + else if (par.equals("h") || par.equals("hyper") || par.equals("hyperspace")) + { + dim = WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID; + } + else + { + dim = Integer.parseInt(par); + } + + x = Integer.parseInt(params[1]); + y = Integer.parseInt(params[2]); + z = Integer.parseInt(params[3]); + blockId = Integer.parseInt(params[4]); + metadata = Integer.parseInt(params[5]); + actions = params[6]; + } + catch (Exception e) + { + e.printStackTrace(); + player.addChatMessage(getCommandUsage(icommandsender)); + return; + } + + notifyAdmins(icommandsender, "/" + getCommandName() + " " + dim + " " + x + "," + y + "," + z + " " + blockId + ":" + metadata + " " + actions); + World worldObj = DimensionManager.getWorld(dim); + TileEntity te = worldObj.getBlockTileEntity(x, y, z); + notifyAdmins(icommandsender, "[" + getCommandName() + "] In dimension " + worldObj.getProviderName() + " - " + worldObj.getWorldInfo().getWorldName() + ", Current block is " + worldObj.getBlockId(x, y, z) + ":" + worldObj.getBlockMetadata(x, y, z) + ", tile entity is " + ((te == null) ? "undefined" : "defined")); + String side = FMLCommonHandler.instance().getEffectiveSide().isClient() ? "Client":"Server"; + + // I(nvalidate), V(alidate), A(set air), R(emoveEntity), P(setBlock), S(etEntity) + boolean bReturn = false; + for (char ch: actions.toUpperCase().toCharArray()) { + switch (ch) { + case 'I': + notifyAdmins(icommandsender, "[" + getCommandName() + "] " + side + ": invalidating"); + if (te != null) { + te.invalidate(); + } + break; + case 'V': + notifyAdmins(icommandsender, "[" + getCommandName() + "] " + side + ": validating"); + if (te != null) { + te.validate(); + } + break; + case 'A': + notifyAdmins(icommandsender, "[" + getCommandName() + "] " + side + ": setting to Air"); + bReturn = worldObj.setBlockToAir(x, y, z); + notifyAdmins(icommandsender, "[" + getCommandName() + "] " + side + ": returned " + bReturn); + break; + case 'R': + notifyAdmins(icommandsender, "[" + getCommandName() + "] " + side + ": remove entity"); + worldObj.removeBlockTileEntity(x, y, z); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + notifyAdmins(icommandsender, "[" + getCommandName() + "] " + side + ": set block " + x + ", " + y + ", " + z + " to " + blockId + ":" + metadata); + bReturn = worldObj.setBlock(x, y, z, blockId, metadata, ch - '0'); + notifyAdmins(icommandsender, "[" + getCommandName() + "] " + side + ": returned " + bReturn); + break; + case 'P': + notifyAdmins(icommandsender, "[" + getCommandName() + "] " + side + ": set block " + x + ", " + y + ", " + z + " to " + blockId + ":" + metadata); + bReturn = worldObj.setBlock(x, y, z, blockId, metadata, 2); + notifyAdmins(icommandsender, "[" + getCommandName() + "] " + side + ": returned " + bReturn); + break; + case 'S': + notifyAdmins(icommandsender, "[" + getCommandName() + "] " + side + ": set entity"); + worldObj.setBlockTileEntity(x, y, z, te); + break; + case 'C': + notifyAdmins(icommandsender, "[" + getCommandName() + "] " + side + ": update containing block info"); + if (te != null) { + te.updateContainingBlockInfo(); + } + break; + } + } + } + else + { + player.addChatMessage(getCommandUsage(icommandsender)); + } + } +} diff --git a/src/cr0s/WarpDrive/item/ItemWarpUpgrade.java b/src/cr0s/WarpDrive/item/ItemWarpUpgrade.java new file mode 100644 index 00000000..179d295d --- /dev/null +++ b/src/cr0s/WarpDrive/item/ItemWarpUpgrade.java @@ -0,0 +1,137 @@ +package cr0s.WarpDrive.item; + +import java.util.List; + +import cpw.mods.fml.common.registry.GameRegistry; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import cr0s.WarpDrive.WarpDrive; +import cr0s.WarpDrive.data.EnumUpgradeTypes; + +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Icon; +import net.minecraftforge.oredict.ShapedOreRecipe; + +public class ItemWarpUpgrade extends Item +{ + private ItemStack[] isCache = new ItemStack[EnumUpgradeTypes.values().length]; + private Icon[] iconBuffer = new Icon[EnumUpgradeTypes.values().length]; + + public ItemWarpUpgrade(int par1) + { + super(par1); + setHasSubtypes(true); + setUnlocalizedName("warpdrive.upgrade.Malformed"); + setCreativeTab(WarpDrive.warpdriveTab); + } + + private boolean isValidDamage(int damage) + { + return damage >= 0 && damage < EnumUpgradeTypes.values().length; + } + + public ItemStack getIS(int damage) + { + if(!isValidDamage(damage)) + return null; + + if(isCache[damage] == null) + isCache[damage] = getISNoCache(damage); + return isCache[damage]; + } + + public ItemStack getISNoCache(int damage) + { + if(!isValidDamage(damage)) + return null; + + return new ItemStack(WarpDrive.upgradeItem,1,damage); + } + + @Override + public String getUnlocalizedName(ItemStack is) + { + if(is == null) + return null; + + int damage = is.getItemDamage(); + if(isValidDamage(damage)) + return "item.warpdrive.upgrade." + EnumUpgradeTypes.values()[damage].toString(); + + return null; + } + + @Override + @SideOnly(Side.CLIENT) + public void getSubItems(int par1, CreativeTabs par2CreativeTabs, List par3List) + { + for(int i=0;i= 0 && damage < EnumUpgradeTypes.values().length) + return iconBuffer[damage]; + return iconBuffer[0]; + } + +} diff --git a/src/cr0s/WarpDrive/machines/BlockChunkLoader.java b/src/cr0s/WarpDrive/machines/BlockChunkLoader.java new file mode 100644 index 00000000..7a9e1c97 --- /dev/null +++ b/src/cr0s/WarpDrive/machines/BlockChunkLoader.java @@ -0,0 +1,37 @@ +package cr0s.WarpDrive.machines; + +import cr0s.WarpDrive.machines.WarpBlockContainer; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraft.world.World; + +public class BlockChunkLoader extends WarpBlockContainer +{ + Icon iconBuffer; + + public BlockChunkLoader(int par1) + { + super(par1); + setUnlocalizedName("warpdrive.machines.ChunkLoader"); + } + + @Override + public TileEntity createNewTileEntity(World world) + { + return new TileEntityChunkLoader(); + } + + @Override + public void registerIcons(IconRegister ir) + { + iconBuffer = ir.registerIcon("warpdrive:chunkLoader"); + } + + @Override + public Icon getIcon(int side, int damage) + { + return iconBuffer; + } + +} diff --git a/src/cr0s/WarpDrive/machines/BlockPowerLaser.java b/src/cr0s/WarpDrive/machines/BlockPowerLaser.java new file mode 100644 index 00000000..9fe0be60 --- /dev/null +++ b/src/cr0s/WarpDrive/machines/BlockPowerLaser.java @@ -0,0 +1,63 @@ +package cr0s.WarpDrive.machines; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraft.world.World; + +public class BlockPowerLaser extends WarpBlockContainer { + static Icon[] iconBuffer = new Icon[16]; + public BlockPowerLaser(int id) { + super(id); + setUnlocalizedName("warpdrive.power.Laser"); + setResistance(100.0F); + } + + @Override + public TileEntity createNewTileEntity(World world) { + return new TileEntityPowerLaser(); + } + + private static boolean isActive(int side, int meta) { + if (side == 3 && meta == 1) { + return true; + } + + if (side == 2 && meta == 2) { + return true; + } + + if (side == 4 && meta == 4) { + return true; + } + + if (side == 5 && meta == 3) { + return true; + } + return false; + } + + @Override + @SideOnly(Side.CLIENT) + public Icon getIcon(int side, int meta) { + if (side == 0 || side == 1) { + return iconBuffer[0]; + } + + if(isActive(side,meta)) { + return iconBuffer[2]; + } + + return iconBuffer[1]; + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IconRegister par1IconRegister) { + iconBuffer[0] = par1IconRegister.registerIcon("warpdrive:powerLaserTopBottom"); + iconBuffer[1] = par1IconRegister.registerIcon("warpdrive:powerLaserSides"); + iconBuffer[2] = par1IconRegister.registerIcon("warpdrive:powerLaserActive"); + } +} \ No newline at end of file diff --git a/src/cr0s/WarpDrive/machines/BlockPowerReactor.java b/src/cr0s/WarpDrive/machines/BlockPowerReactor.java new file mode 100644 index 00000000..0b1a39dd --- /dev/null +++ b/src/cr0s/WarpDrive/machines/BlockPowerReactor.java @@ -0,0 +1,70 @@ +package cr0s.WarpDrive.machines; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraft.world.World; + +public class BlockPowerReactor extends WarpBlockContainer { + Icon[] iconBuffer = new Icon[17]; + + public BlockPowerReactor(int id) { + super(id); + setUnlocalizedName("warpdrive.power.Reactor"); + } + + @Override + public TileEntity createNewTileEntity(World world) { + return new TileEntityPowerReactor(); + } + + @Override + public void breakBlock(World w,int x,int y,int z, int oid,int om) { + super.breakBlock(w, x, y, z, oid, om); + + int[] xo = {-2, 2, 0, 0}; + int[] zo = { 0, 0,-2, 2}; + for(int i = 0; i < 4; i++) { + TileEntity te = w.getBlockTileEntity(x+xo[i], y, z+zo[i]); + if(te instanceof TileEntityPowerLaser) { + ((TileEntityPowerLaser)te).unlink(); + } + } + } + + @Override + @SideOnly(Side.CLIENT) + public Icon getIcon(int side, int meta) { + if (side == 0 || side == 1) { + return iconBuffer[16]; + } + if (meta >= 0 && meta < 16) { + return iconBuffer[meta]; + } + return iconBuffer[0]; + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IconRegister par1IconRegister) { + iconBuffer[16] = par1IconRegister.registerIcon("warpdrive:reactorTB"); + iconBuffer[0] = par1IconRegister.registerIcon("warpdrive:reactorSide00"); + iconBuffer[1] = par1IconRegister.registerIcon("warpdrive:reactorSide01"); + iconBuffer[2] = par1IconRegister.registerIcon("warpdrive:reactorSide02"); + iconBuffer[3] = par1IconRegister.registerIcon("warpdrive:reactorSide03"); + iconBuffer[4] = par1IconRegister.registerIcon("warpdrive:reactorSide10"); + iconBuffer[5] = par1IconRegister.registerIcon("warpdrive:reactorSide11"); + iconBuffer[6] = par1IconRegister.registerIcon("warpdrive:reactorSide12"); + iconBuffer[7] = par1IconRegister.registerIcon("warpdrive:reactorSide13"); + iconBuffer[8] = par1IconRegister.registerIcon("warpdrive:reactorSide20"); + iconBuffer[9] = par1IconRegister.registerIcon("warpdrive:reactorSide21"); + iconBuffer[10] = par1IconRegister.registerIcon("warpdrive:reactorSide22"); + iconBuffer[11] = par1IconRegister.registerIcon("warpdrive:reactorSide23"); + iconBuffer[12] = par1IconRegister.registerIcon("warpdrive:reactorSide30"); + iconBuffer[13] = par1IconRegister.registerIcon("warpdrive:reactorSide31"); + iconBuffer[14] = par1IconRegister.registerIcon("warpdrive:reactorSide32"); + iconBuffer[15] = par1IconRegister.registerIcon("warpdrive:reactorSide33"); + } +} \ No newline at end of file diff --git a/src/cr0s/WarpDrive/machines/BlockPowerStore.java b/src/cr0s/WarpDrive/machines/BlockPowerStore.java new file mode 100644 index 00000000..48f84ffe --- /dev/null +++ b/src/cr0s/WarpDrive/machines/BlockPowerStore.java @@ -0,0 +1,54 @@ +package cr0s.WarpDrive.machines; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraft.world.World; + +public class BlockPowerStore extends WarpBlockContainer { + private Icon iconBuffer; + + public BlockPowerStore(int par1) { + super(par1); + setUnlocalizedName("warpdrive.power.Store"); + } + + @Override + public TileEntity createNewTileEntity(World world) { + return new TileEntityPowerStore(); + } + + @Override + @SideOnly(Side.CLIENT) + public Icon getIcon(int side, int meta) { + return iconBuffer; + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IconRegister par1IconRegister) { + iconBuffer = par1IconRegister.registerIcon("warpdrive:powerStore"); + } + + /** + * Called upon block activation (right click on the block.) + */ + @Override + public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { + return false; + } + + WarpEnergyTE te = (WarpEnergyTE)par1World.getBlockTileEntity(par2, par3, par4); + if (te != null && (par5EntityPlayer.getHeldItem() == null)) { + par5EntityPlayer.addChatMessage(te.getStatus()); + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/cr0s/WarpDrive/machines/BlockTransporter.java b/src/cr0s/WarpDrive/machines/BlockTransporter.java new file mode 100644 index 00000000..35b0c219 --- /dev/null +++ b/src/cr0s/WarpDrive/machines/BlockTransporter.java @@ -0,0 +1,47 @@ +package cr0s.WarpDrive.machines; + +import java.util.Random; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import cr0s.WarpDrive.WarpDrive; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.client.renderer.texture.IconRegister; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Icon; +import net.minecraft.world.World; + +public class BlockTransporter extends WarpBlockContainer { + + private Icon[] iconBuffer; + + public BlockTransporter(int par1, Material par2Material) { + super(par1, par2Material); + setUnlocalizedName("warpdrive.machines.Transporter"); + } + + @Override + public TileEntity createNewTileEntity(World world) { + return new TileEntityTransporter(); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IconRegister par1IconRegister) { + iconBuffer = new Icon[3]; + // Solid textures + iconBuffer[0] = par1IconRegister.registerIcon("warpdrive:transporterBottom"); + iconBuffer[1] = par1IconRegister.registerIcon("warpdrive:transporterTop"); + iconBuffer[2] = par1IconRegister.registerIcon("warpdrive:transporterSide"); + } + + @Override + public Icon getIcon(int side, int metadata) { + if (side == 0 || side == 1) { + return iconBuffer[side]; + } + + return iconBuffer[2]; + } +} \ No newline at end of file diff --git a/src/cr0s/WarpDrive/machines/TileEntityChunkLoader.java b/src/cr0s/WarpDrive/machines/TileEntityChunkLoader.java new file mode 100644 index 00000000..8cd6af25 --- /dev/null +++ b/src/cr0s/WarpDrive/machines/TileEntityChunkLoader.java @@ -0,0 +1,257 @@ +package cr0s.WarpDrive.machines; + +import java.util.Map; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.chunk.Chunk; +import cr0s.WarpDrive.data.EnumUpgradeTypes; +import cr0s.WarpDrive.WarpDrive; +import cr0s.WarpDrive.WarpDriveConfig; +import cr0s.WarpDrive.api.IUpgradable; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; + +public class TileEntityChunkLoader extends WarpChunkTE implements IPeripheral, IUpgradable +{ + private boolean canLoad = false; + private boolean shouldLoad = false; + + private boolean inited = false; + private ChunkCoordIntPair myChunk; + + int negDX, posDX, negDZ, posDZ; + int area = 1; + + private String[] methodArray = { + "energy", + "radius", + "bounds", + "active", + "upgrades", + "help" + }; + + { + negDX = 0; + negDZ = 0; + posDX = 0; + posDZ = 0; + } + + @Override + public int getMaxEnergyStored() + { + return WarpDriveConfig.CL_MAX_ENERGY; + } + + @Override + public boolean shouldChunkLoad() + { + return shouldLoad && canLoad; + } + + @Override + public void updateEntity() + { + super.updateEntity(); + + if(!inited) + { + inited = true; + myChunk = worldObj.getChunkFromBlockCoords(xCoord, zCoord).getChunkCoordIntPair(); + changedDistance(); + } + + if(shouldLoad) + { + canLoad = consumeEnergy(area * WarpDriveConfig.CL_RF_PER_CHUNKTICK, false); + } + else + { + canLoad = consumeEnergy(area * WarpDriveConfig.CL_RF_PER_CHUNKTICK, true); + } + } + + private int clampDistance(int dis) + { + return clamp(dis,0,WarpDriveConfig.CL_MAX_DISTANCE); + } + + private void changedDistance() + { + if(worldObj == null) { + return; + } + if (myChunk == null) { + Chunk aChunk = worldObj.getChunkFromBlockCoords(xCoord, zCoord); + if (aChunk != null) { + myChunk = aChunk.getChunkCoordIntPair(); + } else { + return; + } + } + negDX = -clampDistance(negDX); + posDX = clampDistance(posDX); + negDZ = -clampDistance(negDZ); + posDZ = clampDistance(posDZ); + minChunk = new ChunkCoordIntPair(myChunk.chunkXPos+negDX,myChunk.chunkZPos+negDZ); + maxChunk = new ChunkCoordIntPair(myChunk.chunkXPos+posDX,myChunk.chunkZPos+posDZ); + area = (posDX - negDX + 1) * (posDZ - negDZ + 1); + refreshLoading(true); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) + { + super.readFromNBT(nbt); + negDX = nbt.getInteger("negDX"); + negDZ = nbt.getInteger("negDZ"); + posDX = nbt.getInteger("posDX"); + posDZ = nbt.getInteger("posDZ"); + + changedDistance(); + } + + @Override + public void writeToNBT(NBTTagCompound nbt) + { + super.writeToNBT(nbt); + nbt.setInteger("negDX", negDX); + nbt.setInteger("negDZ", negDZ); + nbt.setInteger("posDX", posDX); + nbt.setInteger("posDZ", posDZ); + } + + @Override + public String getType() + { + return "warpdriveChunkloader"; + } + + @Override + public String[] getMethodNames() + { + return methodArray; + } + + private String helpStr(Object[] args) + { + if(args.length == 1) + { + String m = args[0].toString().toLowerCase(); + if(m.equals("energy")) + return WarpDrive.defEnergyStr; + else if(m.equals("radius")) + return "radius(int): sets the radius in chunks"; + else if(m.equals("bounds")) + return "bounds(int,int,int,int): sets the bounds of chunks to load\nbounds(): returns the 4 bounds\nFormat is -X, +X, -Z, +Z"; + else if(m.equals("active")) + return "active(): returns whether active or not\nactive(boolean): sets whether it should be active or not"; + else if(m.equals("upgrades")) + return WarpDrive.defUpgradeStr; + } + return WarpDrive.defHelpStr; + } + + @Override + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception + { + String meth = methodArray[method]; + + if(meth.equals("energy")) + return getEnergyObject(); + else if(meth.equals("radius")) + { + if(arguments.length == 1) + { + int dist = toInt(arguments[0]); + negDX = dist; + negDZ = dist; + posDX = dist; + posDZ = dist; + changedDistance(); + return new Object[] { true }; + } + return new Object[] { false }; + } + else if(meth.equals("bounds")) + { + if(arguments.length == 4) + { + negDX = toInt(arguments[0]); + posDX = toInt(arguments[1]); + negDZ = toInt(arguments[2]); + posDZ = toInt(arguments[3]); + changedDistance(); + } + return new Object[] { negDX, posDX, negDZ, posDZ }; + } + else if(meth.equals("active")) + { + if(arguments.length == 1) + shouldLoad = toBool(arguments[0]); + return new Object[] { shouldChunkLoad() }; + } + else if(meth.equals("upgrades")) + { + return getUpgrades(); + } + else if(meth.equals("help")) + { + return new Object[] {helpStr(arguments) }; + } + + return null; + } + + @Override + public void attach(IComputerAccess computer) + { + } + + @Override + public void detach(IComputerAccess computer) + { + } + + @Override + public boolean equals(IPeripheral other) + { + return false; + } + + @Override + public boolean takeUpgrade(EnumUpgradeTypes upgradeType, boolean simulate) + { + int max = 0; + if(upgradeType == EnumUpgradeTypes.Energy) + max = 2; + else if(upgradeType == EnumUpgradeTypes.Power) + max = 2; + + if(max == 0) + return false; + + if(upgrades.containsKey(upgradeType)) + if(upgrades.get(upgradeType) >= max) + return false; + + if(!simulate) + { + int c = 0; + if(upgrades.containsKey(upgradeType)) + c = upgrades.get(upgradeType); + upgrades.put(upgradeType, c+1); + } + return true; + } + + @Override + public Map getInstalledUpgrades() + { + return upgrades; + } + +} diff --git a/src/cr0s/WarpDrive/machines/TileEntityPowerLaser.java b/src/cr0s/WarpDrive/machines/TileEntityPowerLaser.java new file mode 100644 index 00000000..5544aa5d --- /dev/null +++ b/src/cr0s/WarpDrive/machines/TileEntityPowerLaser.java @@ -0,0 +1,218 @@ +package cr0s.WarpDrive.machines; + +import cr0s.WarpDrive.api.IBlockUpdateDetector; +import cr0s.WarpDrive.data.Vector3; +import cr0s.WarpDrive.WarpDrive; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; + +public class TileEntityPowerLaser extends TileEntityAbstractLaser implements IPeripheral, IBlockUpdateDetector { + Vector3 myVec; + Vector3 reactorVec; + ForgeDirection side = ForgeDirection.UNKNOWN; + TileEntityParticleBooster booster; + TileEntityPowerReactor reactor; + + boolean useLaser = false; + boolean doOnce = false; + + String[] methodArray = { + "energy", + "hasReactor", + "side", + "sendLaser", + "help" + }; + + @Override + public boolean shouldChunkLoad() { + return false; + } + + public TileEntityPowerReactor scanForReactor() { + reactor = null; + TileEntity te; + //I AM ON THE NORTH SIDE + side = ForgeDirection.UNKNOWN; + te = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord + 2); + if (te instanceof TileEntityPowerReactor && worldObj.isAirBlock(xCoord, yCoord, zCoord + 1)) { + side = ForgeDirection.NORTH; + reactor = (TileEntityPowerReactor) te; + } + + //I AM ON THE SOUTH SIDE + te = worldObj.getBlockTileEntity(xCoord, yCoord, zCoord - 2); + if (te instanceof TileEntityPowerReactor && worldObj.isAirBlock(xCoord, yCoord, zCoord - 1)) { + side = ForgeDirection.SOUTH; + reactor = (TileEntityPowerReactor) te; + } + + //I AM ON THE WEST SIDE + te = worldObj.getBlockTileEntity(xCoord + 2, yCoord, zCoord); + if (te instanceof TileEntityPowerReactor && worldObj.isAirBlock(xCoord + 1, yCoord, zCoord)) { + side = ForgeDirection.WEST; + reactor = (TileEntityPowerReactor) te; + } + + //I AM ON THE EAST SIDE + te = worldObj.getBlockTileEntity(xCoord - 2, yCoord, zCoord); + if (te instanceof TileEntityPowerReactor && worldObj.isAirBlock(xCoord - 1, yCoord, zCoord)) { + side = ForgeDirection.EAST; + reactor = (TileEntityPowerReactor) te; + } + + setMetadata(); + + if (reactor != null) { + reactorVec = new Vector3(reactor).translate(0.5); + } + return reactor; + } + + private void setMetadata() { + int metadata = 0; + if (side != ForgeDirection.UNKNOWN) { + metadata = side.ordinal() - 1; + } + if (getBlockMetadata() != metadata) { + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, metadata, 3); + } + } + + public TileEntityParticleBooster scanForBooster() { + booster = null; + TileEntity te; + te = worldObj.getBlockTileEntity(xCoord, yCoord + 1, zCoord); + if (te != null && te instanceof TileEntityParticleBooster) { + booster = (TileEntityParticleBooster)te; + } + + te = worldObj.getBlockTileEntity(xCoord, yCoord - 1, zCoord); + if (te != null && te instanceof TileEntityParticleBooster) { + booster = (TileEntityParticleBooster)te; + } + + return booster; + } + + @Override + public void updateEntity() { + if (doOnce == false) { + scanForReactor(); + scanForBooster(); + myVec = new Vector3(this).translate(0.5); + doOnce = true; + } + + if (useLaser == true) { + WarpDrive.sendLaserPacket(worldObj, myVec, reactorVec, 0.1F, 0.2F, 1.0F, 25, 50, 100); + useLaser = false; + } + } + + public void unlink() { + side = ForgeDirection.UNKNOWN; + setMetadata(); + } + + @Override + public void updatedNeighbours() { + scanForBooster(); + scanForReactor(); + } + + private void laserReactor(int energy) { + if (energy <= 0) { + return; + } + + scanForBooster(); + scanForReactor(); + if(booster == null) + return; + if(reactor == null) + return; + if (booster.consumeEnergy(energy, false)) { + // WarpDrive.debugPrint("ReactorLaser on " + side.toString() +" side sending " + amount); + useLaser = true; + reactor.decreaseInstability(side, energy); + } + } + + @Override + public void writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + } + + @Override + public String getType() { + return "warpdriveReactorLaser"; + } + + @Override + public String[] getMethodNames() { + return methodArray; + } + + private static String helpStr(Object[] args) { + if (args.length > 0) { + String arg = args[0].toString().toLowerCase(); + if (arg.equals("energy")) { + return WarpDrive.defEnergyStr; + } else if(arg.equals("hasReactor")) { + return "hasReactor(): returns true if the laser can see a reactor and false otherwise"; + } else if(arg.equals("sendlaser")) { + return "sendLaser(int): sends a laser of energy int to the reactor"; + } else if(arg.equals("side")) { + return "side(): returns 0-3 depending on which side of the reactor its on"; + } + } + return WarpDrive.defHelpStr; + } + + @Override + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception { + String methodName = methodArray[method]; + if (methodName.equals("energy")) { + scanForBooster(); + if (booster == null) { + return new Object[] { 0,0 }; + } else { + return new Object[] { booster.getEnergyStored(), booster.getMaxEnergyStored() }; + } + } else if (methodName.equals("hasReactor")) { + return new Object[] { scanForReactor() != null }; + } else if (methodName.equals("sendLaser")) { + if (arguments.length >= 1) { + laserReactor(toInt(arguments[0])); + } + } else if (methodName.equals("help")) { + return new Object[] {helpStr(arguments)}; + } else if (methodName.equals("side")) { + return new Object[] { side.ordinal() - 2 }; + } + return null; + } + + @Override + public void attach(IComputerAccess computer) { + } + + @Override + public void detach(IComputerAccess computer) { + } + + @Override + public boolean equals(IPeripheral other) { + return other == this; + } +} \ No newline at end of file diff --git a/src/cr0s/WarpDrive/machines/TileEntityPowerReactor.java b/src/cr0s/WarpDrive/machines/TileEntityPowerReactor.java new file mode 100644 index 00000000..8f3d1b0f --- /dev/null +++ b/src/cr0s/WarpDrive/machines/TileEntityPowerReactor.java @@ -0,0 +1,543 @@ +package cr0s.WarpDrive.machines; + +import java.util.HashMap; +import java.util.Random; +import java.util.Set; + +import cpw.mods.fml.common.FMLCommonHandler; +import cr0s.WarpDrive.WarpDrive; +import cr0s.WarpDrive.WarpDriveConfig; +import cr0s.WarpDrive.api.IBlockUpdateDetector; +import dan200.computercraft.api.ComputerCraftAPI; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.ForgeDirection; + +public class TileEntityPowerReactor extends WarpEnergyTE implements IPeripheral, IBlockUpdateDetector { + private int containedEnergy = 0; + + // generation & instability is 'per tick' + private static final int PR_MIN_GENERATION = 4; + private static final int PR_MAX_GENERATION = 64000; + private static final double PR_MIN_INSTABILITY = 0.004D; + private static final double PR_MAX_INSTABILITY = 0.060D; + + // explosion parameters + private static final int PR_MAX_EXPLOSION_RADIUS = 6; + private static final double PR_MAX_EXPLOSION_REMOVAL_CHANCE = 0.1D; + + // laser stabilization is per shot + // target is to consume 10% max output power every second, hence 2.5% per side + // laser efficiency is 33% at 16% power (target spot), 50% at 24% power, 84% at 50% power, etc. + // 10% * 20 * PR_MAX_GENERATION / (4 * 0.16) => ~200kRF => ~ max laser energy + private static final double PR_MAX_LASER_ENERGY = 200000.0D; + private static final double PR_MAX_LASER_EFFECT = PR_MAX_INSTABILITY * 20 / 0.33D; + + private int tickCount = 0; + + private double[] instabilityValues = { 0.0D, 0.0D, 0.0D, 0.0D }; // no instability = 0, explosion = 100 + private float lasersReceived = 0; + private int lastGenerationRate = 0; + private int releasedThisTick = 0; // amount of energy released during current tick update + private int releasedThisCycle = 0; // amount of energy released during current cycle + private int releasedLastCycle = 0; + + private boolean hold = true; // hold updates and power output until reactor is controlled (i.e. don't explode on chunk-loading while computer is booting) + private boolean active = false; + private static final int MODE_DONT_RELEASE = 0; + private static final int MODE_MANUAL_RELEASE = 1; + private static final int MODE_RELEASE_ABOVE = 2; + private static final int MODE_RELEASE_AT_RATE = 3; + private static final String[] MODE_STRING = {"OFF", "MANUAL", "ABOVE", "RATE"}; + private int releaseMode = 0; + private int releaseRate = 0; + private int releaseAbove = 0; + + private boolean init = false; + + private String[] methodArray = { + "getActive", + "setActive", // boolean + "energy", // returns energy, maxenergy + "instability", // returns ins0,1,2,3 + "release", // releases all energy + "releaseRate", // releases energy when more than arg0 is produced + "releaseAbove", // releases any energy above arg0 amount + "help" // returns help on arg0 function + }; + private HashMap connectedComputers = new HashMap(); + + private void increaseInstability(ForgeDirection from, boolean isNatural) { + if (canOutputEnergy(from) || hold) { + return; + } + + int side = from.ordinal() - 2; + if (containedEnergy > WarpDriveConfig.PR_TICK_TIME * PR_MIN_GENERATION * 100) { + double amountToIncrease = WarpDriveConfig.PR_TICK_TIME * Math.max(PR_MIN_INSTABILITY, PR_MAX_INSTABILITY * Math.pow((worldObj.rand.nextDouble() * containedEnergy) / WarpDriveConfig.PR_MAX_ENERGY, 0.1)); + //WarpDrive.debugPrint("InsInc" + amountToIncrease); + instabilityValues[side] += amountToIncrease * (isNatural ? 1.0D : 0.25D); + } else { + double amountToDecrease = WarpDriveConfig.PR_TICK_TIME * Math.max(PR_MIN_INSTABILITY, instabilityValues[side] * 0.02D); + instabilityValues[side] = Math.max(0.0D, instabilityValues[side] - amountToDecrease); + } + } + + private void increaseInstability(boolean isNatural) { + increaseInstability(ForgeDirection.NORTH, isNatural); + increaseInstability(ForgeDirection.SOUTH, isNatural); + increaseInstability(ForgeDirection.EAST, isNatural); + increaseInstability(ForgeDirection.WEST, isNatural); + } + + public void decreaseInstability(ForgeDirection from, int energy) { + if (canOutputEnergy(from)) { + return; + } + + // laser is active => start updating reactor + hold = false; + + int amount = convertInternalToRF(energy); + if (amount <= 1) { + return; + } + + lasersReceived = Math.min(10.0F, lasersReceived + 1F / WarpDriveConfig.PR_MAX_LASERS); + double nospamFactor = 1.0; + if (lasersReceived > 1.0F) { + nospamFactor = 0.5; + worldObj.newExplosion((Entity) null, xCoord + from.offsetX, yCoord + from.offsetY, zCoord + from.offsetZ, 1, false, false); + // increaseInstability(from, false); + // increaseInstability(false); + } + double normalisedAmount = Math.min(1.0D, Math.max(0.0D, amount / PR_MAX_LASER_ENERGY)); // 0.0 to 1.0 + double baseLaserEffect = 0.5D + 0.5D * Math.cos(Math.PI - (1.0D + Math.log10(0.1D + 0.9D * normalisedAmount)) * Math.PI); // 0.0 to 1.0 + double randomVariation = 0.8D + 0.4D * worldObj.rand.nextDouble(); // ~1.0 + double amountToRemove = PR_MAX_LASER_EFFECT * baseLaserEffect * randomVariation * nospamFactor; + + int side = from.ordinal() - 2; + + /* + if (side == 3) WarpDrive.debugPrint("Instability on " + from.toString() + " decreased by " + String.format("%.1f", amountToRemove) + "/" + String.format("%.1f", PR_MAX_LASER_EFFECT) + + " after consuming " + amount + "/" + PR_MAX_LASER_ENERGY + " lasersReceived is " + String.format("%.1f", lasersReceived) + " hence nospamFactor is " + nospamFactor); + /**/ + + instabilityValues[side] = Math.max(0, instabilityValues[side] - amountToRemove); + + updateSideTextures(); + } + + private void generateEnergy() { + double stabilityOffset = 0.5; + for(int i = 0; i < 4; i++) { + stabilityOffset *= Math.max(0.01D, instabilityValues[i] / 100.0D); + } + + //WarpDrive.debugPrint("INSOFF" + stabilityOffset); + + if (active) {// producing, instability increase output, you want to take the risk + int amountToGenerate = (int)Math.ceil( WarpDriveConfig.PR_TICK_TIME * (0.5D + stabilityOffset) * (PR_MIN_GENERATION + PR_MAX_GENERATION * Math.pow(containedEnergy / (double) WarpDriveConfig.PR_MAX_ENERGY, 0.6D))); + containedEnergy = Math.min(containedEnergy + amountToGenerate, WarpDriveConfig.PR_MAX_ENERGY); + lastGenerationRate = amountToGenerate / WarpDriveConfig.PR_TICK_TIME; + } else {// decaying over 20s without producing power, you better have power for those lasers + int amountToDecay = (int)( WarpDriveConfig.PR_TICK_TIME * (1.0D - stabilityOffset) * (PR_MIN_GENERATION + containedEnergy * 0.01D) ); + containedEnergy = Math.max(0, containedEnergy - amountToDecay); + lastGenerationRate = 0; + } + } + + @Override + public void updateEntity() { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { + return; + } + super.updateEntity(); + + releasedThisTick = 0; + + lasersReceived = Math.max(0.0F, lasersReceived - 0.05F); + tickCount++; + if (tickCount < WarpDriveConfig.PR_TICK_TIME) { + return; + } + tickCount = 0; + releasedLastCycle = releasedThisCycle; + releasedThisCycle = 0; + + if (!init) { + init = true; + updatedNeighbours(); + } + + updateSideTextures(); + + // unstable at all time + if (shouldExplode()) { + explode(); + } + increaseInstability(true); + + generateEnergy(); + + sendEvent("reactorPulse", new Object[] { lastGenerationRate }); + } + + private void explode() { + // remove blocks randomly up to x blocks around (breaking whatever protection is there) + double normalizedEnergy = containedEnergy / (double)WarpDriveConfig.PR_MAX_ENERGY; + int radius = (int) Math.round(PR_MAX_EXPLOSION_RADIUS * Math.pow(normalizedEnergy, 0.125)); + double c = PR_MAX_EXPLOSION_REMOVAL_CHANCE * Math.pow(normalizedEnergy, 0.125); + WarpDrive.debugPrint(this + " Explosion radius is " + radius + ", Chance of removal is " + c); + if (radius > 1) { + for(int x = xCoord - radius; x <= xCoord + radius; x++) { + for(int y = yCoord - radius; y <= yCoord + radius; y++) { + for(int z = zCoord - radius; z <= zCoord + radius; z++) { + if (z != zCoord || y != yCoord || x != xCoord) { + if (worldObj.rand.nextDouble() < c) { + worldObj.setBlockToAir(x, y, z); + } + } + } + } + } + } + // remove reactor + worldObj.setBlockToAir(xCoord, yCoord, zCoord); + // set a few TnT augmented around reactor + for (int i = 0; i < 3; i++) { + worldObj.newExplosion((Entity) null, + xCoord + worldObj.rand.nextInt(3) - 0.5D, + yCoord + worldObj.rand.nextInt(3) - 0.5D, + zCoord + worldObj.rand.nextInt(3) - 0.5D, + 4.0F + worldObj.rand.nextInt(3), + true, true); + } + } + + private void updateSideTextures() { + double maxInstability = 0.0D; + for (Double ins:instabilityValues) { + if (ins > maxInstability) { + maxInstability = ins; + } + } + int instabilityNibble = (int) Math.max(0, Math.min(3, Math.round( maxInstability / 25.0D))); + int energyNibble = (int) Math.max(0, Math.min(3, Math.round(4.0D * containedEnergy / WarpDriveConfig.PR_MAX_ENERGY))); + + int metadata = 4 * instabilityNibble + energyNibble; + if (getBlockMetadata() != metadata) { + worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, metadata, 3); + } + } + + private boolean shouldExplode() { + boolean exploding = false; + for(int i = 0; i < 4; i++) { + exploding = exploding || (instabilityValues[i] >= 100); + } + exploding &= worldObj.rand.nextBoolean(); + + if (exploding && worldObj.rand.nextBoolean()) { + active = false; + WarpDrive.print(this + String.format(" Explosion trigerred, Instability is [%.2f, %.2f, %.2f, %.2f], Energy stored is %d, Laser received is %.2f, %s", new Object[] { + instabilityValues[0], instabilityValues[1], instabilityValues[2], instabilityValues[3], + this.containedEnergy, + this.lasersReceived, + this.active ? "ACTIVE" : "INACTIVE" })); + } + return exploding; + } + + //Takes the arguments passed by function call and returns an appropriate string + private static String helpStr(Object[] args) { + if (args.length > 0) { + String arg = args[0].toString().toLowerCase(); + if (arg.equals("getactive")) { + return "getActive(): returns true if the reactor is active and false otherwise"; + } else if (arg.equals("setactive")) { + return "setActive(bool): activates the reactor if passed true and deactivates if passed false"; + } else if (arg.equals("energy")) { + return WarpDrive.defEnergyStr; + } else if (arg.equals("instability")) { + return "instability(): returns the 4 instability values (100 is the point when the reactor explodes)"; + } else if (arg.equals("release")) { + return "release(bool): sets the reactor to output all energy or disables outputting of energy"; + } else if (arg.equals("releaserate")) { + return "releaseRate(int): sets the reactor to try to release exactly int/tick"; + } else if (arg.equals("releaseabove")) { + return "releaseAbove(int): releases all energy above stored int"; + } + } + return WarpDrive.defHelpStr; + } + + @Override + public void updatedNeighbours() { + TileEntity te; + super.updatedNeighbours(); + + int[] xo = { 0, 0,-2, 2}; + int[] zo = { 2,-2, 0, 0}; + + for(int i = 0; i < 4; i++) { + te = worldObj.getBlockTileEntity(xCoord + xo[i], yCoord, zCoord + zo[i]); + if (te instanceof TileEntityPowerLaser) { + ((TileEntityPowerLaser)te).scanForReactor(); + } + } + } + + //COMPUTER INTERFACES + @Override + public String getType() { + return "warpdriveReactor"; + } + + @Override + public String[] getMethodNames() { + return methodArray; + } + + @Override + public void attach(IComputerAccess computer) { + int id = computer.getID(); + connectedComputers.put(id, computer); + if (WarpDriveConfig.G_LUA_SCRIPTS != WarpDriveConfig.LUA_SCRIPTS_NONE) { + computer.mount("/power", ComputerCraftAPI.createResourceMount(WarpDrive.class, "warpdrive", "lua/power")); + computer.mount("/warpupdater", ComputerCraftAPI.createResourceMount(WarpDrive.class, "warpdrive", "lua/common/updater")); + if (WarpDriveConfig.G_LUA_SCRIPTS == WarpDriveConfig.LUA_SCRIPTS_ALL) { + computer.mount("/startup", ComputerCraftAPI.createResourceMount(WarpDrive.class, "warpdrive", "lua/power/startup")); + } + } + } + + @Override + public void detach(IComputerAccess computer) { + int id = computer.getID(); + if (connectedComputers.containsKey(id)) { + connectedComputers.remove(id); + } + } + + @Override + public boolean equals(IPeripheral other) { + return other == this; + } + + @Override + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception { + // computer is alive => start updating reactor + hold = false; + + String methodName = methodArray[method]; + + if (methodName.equals("getActive")) { + if (releaseMode == MODE_DONT_RELEASE || releaseMode == MODE_MANUAL_RELEASE) { + return new Object[] { active, MODE_STRING[releaseMode], 0 }; + } else if (releaseMode == MODE_RELEASE_ABOVE) { + return new Object[] { active, MODE_STRING[releaseMode], releaseAbove }; + } else { + return new Object[] { active, MODE_STRING[releaseMode], releaseRate }; + } + } else if (methodName.equals("setActive")) { + boolean activate = false; + try { + activate = toBool(arguments[0]); + } catch(Exception e) { + throw new Exception("Function expects an boolean value"); + } + if (active && !activate) { + sendEvent("reactorDeactivation", null); + } else if(!active && activate) { + sendEvent("reactorActivation", null); + } + active = activate; + } else if (methodName.equals("energy")) { + return new Object[] { containedEnergy, WarpDriveConfig.PR_MAX_ENERGY, releasedLastCycle / WarpDriveConfig.PR_TICK_TIME }; + } else if (methodName.equals("instability")) { + Object[] retVal = new Object[4]; + for(int i = 0; i < 4; i++) { + retVal[i] = instabilityValues[i]; + } + return retVal; + } else if(methodName.equals("release")) { + boolean doRelease = false; + if (arguments.length > 0) { + try { + doRelease = toBool(arguments[0]); + } catch(Exception e) { + throw new Exception("Function expects an boolean value"); + } + + releaseMode = doRelease ? MODE_MANUAL_RELEASE : MODE_DONT_RELEASE; + releaseAbove = 0; + releaseRate = 0; + } + return new Object[] { releaseMode != MODE_DONT_RELEASE }; + } else if(methodName.equals("releaseRate")) { + int rate = -1; + try { + rate = toInt(arguments[0]); + } catch(Exception e) { + throw new Exception("Function expects an integer value"); + } + + if (rate <= 0) { + releaseMode = MODE_DONT_RELEASE; + releaseRate = 0; + } else { +/* releaseAbove = (int)Math.ceil(Math.pow(rate, 1.0 / 0.6)); + WarpDrive.debugPrint("releaseAbove " + releaseAbove); + releaseMode = MODE_RELEASE_ABOVE;/**/ + // player has to adjust it + releaseRate = rate; + releaseMode = MODE_RELEASE_AT_RATE; + } + + return new Object[] { MODE_STRING[releaseMode], releaseRate }; + } else if(methodName.equals("releaseAbove")) { + int above = -1; + try { + above = toInt(arguments[0]); + } catch(Exception e) { + throw new Exception("Function expects an integer value"); + } + + if (above <= 0) { + releaseMode = 0; + releaseAbove = MODE_DONT_RELEASE; + } else { + releaseMode = MODE_RELEASE_ABOVE; + releaseAbove = above; + } + + return new Object[] { MODE_STRING[releaseMode], releaseAbove }; + } else if (methodName.equals("debugLaser")) { + //WarpDrive.debugPrint("debugMethod"); + int side = toInt(arguments[0]); + int amount = toInt(arguments[1]); + + ForgeDirection d; + if (side == 0) { + d = ForgeDirection.NORTH; + } else if (side == 1) { + d = ForgeDirection.SOUTH; + } else if (side == 2) { + d = ForgeDirection.WEST; + } else if (side == 3) { + d = ForgeDirection.EAST; + } else { + d = ForgeDirection.UP; + } + + if (amount < containedEnergy) { + containedEnergy -= amount; + decreaseInstability(d,amount); + } + } else if (methodName.equals("help")) { + return new Object[] { helpStr(arguments) }; + } + + return null; + } + + private void sendEvent(String eventName, Object[] arguments) { + // WarpDrive.debugPrint("" + this + " Sending event '" + eventName + "'"); + Set keys = connectedComputers.keySet(); + for(Integer key:keys) { + IComputerAccess comp = connectedComputers.get(key); + comp.queueEvent(eventName, arguments); + } + } + + // POWER INTERFACES + @Override + public int getPotentialEnergyOutput() { + if (hold) {// still loading/booting => hold output + return 0; + } + int capacity = Math.max(0, 2 * lastGenerationRate - releasedThisTick); + if (releaseMode == MODE_MANUAL_RELEASE) { + return convertRFtoInternal(Math.min(Math.max(0, containedEnergy ), capacity)); + } else if (releaseMode == MODE_RELEASE_ABOVE) { + return convertRFtoInternal(Math.min(Math.max(0, containedEnergy - releaseAbove), capacity)); + } else if (releaseMode == MODE_RELEASE_AT_RATE) { + int remainingRate = Math.max(0, releaseRate - releasedThisTick); + return convertRFtoInternal(Math.min(Math.max(0, containedEnergy ), Math.min(remainingRate, capacity))); + } + return 0; + } + + @Override + public boolean canOutputEnergy(ForgeDirection from) { + if (from.equals(ForgeDirection.UP) || from.equals(ForgeDirection.DOWN)) { + return true; + } + return false; + } + + @Override + protected void energyOutputDone(int energyOutput) { + int energyOutput_RF = convertInternalToRF(energyOutput); + containedEnergy -= energyOutput_RF; + if (containedEnergy < 0) { + containedEnergy = 0; + } + releasedThisTick += energyOutput_RF; + releasedThisCycle += energyOutput_RF; + } + + @Override + public int getEnergyStored() { + return convertRFtoInternal(containedEnergy); + } + + @Override + public int getMaxEnergyStored() { + return convertRFtoInternal(WarpDriveConfig.PR_MAX_ENERGY); + } + + + // Forge overrides + @Override + public void writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + nbt.setInteger("energy", containedEnergy); + nbt.setInteger("releaseMode", releaseMode); + nbt.setInteger("releaseRate", releaseRate); + nbt.setInteger("releaseAbove", releaseAbove); + nbt.setDouble("i0", instabilityValues[0]); + nbt.setDouble("i1", instabilityValues[1]); + nbt.setDouble("i2", instabilityValues[2]); + nbt.setDouble("i3", instabilityValues[3]); + nbt.setBoolean("active", active); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + containedEnergy = nbt.getInteger("energy"); + releaseMode = nbt.getInteger("releaseMode"); + releaseRate = nbt.getInteger("releaseRate"); + releaseAbove = nbt.getInteger("releaseAbove"); + instabilityValues[0] = nbt.getDouble("i0"); + instabilityValues[1] = nbt.getDouble("i1"); + instabilityValues[2] = nbt.getDouble("i2"); + instabilityValues[3] = nbt.getDouble("i3"); + active = nbt.getBoolean("active"); + } + + @Override + public String toString() { + return String.format("%s \'%s\' @ \'%s\' %.2f, %.2f, %.2f", new Object[] { + getClass().getSimpleName(), + this.connectedComputers == null ? "~NULL~" : this.connectedComputers, + worldObj == null ? "~NULL~" : worldObj.getWorldInfo().getWorldName(), + Double.valueOf(xCoord), Double.valueOf(yCoord), Double.valueOf(zCoord)}); + } +} \ No newline at end of file diff --git a/src/cr0s/WarpDrive/machines/TileEntityPowerStore.java b/src/cr0s/WarpDrive/machines/TileEntityPowerStore.java new file mode 100644 index 00000000..eb0f6b90 --- /dev/null +++ b/src/cr0s/WarpDrive/machines/TileEntityPowerStore.java @@ -0,0 +1,73 @@ +package cr0s.WarpDrive.machines; + +import cr0s.WarpDrive.WarpDriveConfig; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import net.minecraftforge.common.ForgeDirection; + +public class TileEntityPowerStore extends WarpEnergyTE implements IPeripheral { + private String[] methodArray = { + "energy" + }; + + @Override + public int getPotentialEnergyOutput() { + return getEnergyStored(); + } + + @Override + protected void energyOutputDone(int energyOutput) { + consumeEnergy(energyOutput, false); + } + + @Override + public int getMaxEnergyStored() { + return WarpDriveConfig.PS_MAX_ENERGY; + } + + @Override + public boolean canInputEnergy(ForgeDirection from) { + return true; + } + + @Override + public boolean canOutputEnergy(ForgeDirection to) { + return true; + } + + // ComputerCraft + @Override + public String getType() { + return "warpdrivePowerStore"; + } + + @Override + public String[] getMethodNames() { + return methodArray; + } + + @Override + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception { + String methodName = methodArray[method]; + if (methodName == "energy") { + return getEnergyObject(); + } + return null; + } + + @Override + public void attach(IComputerAccess computer) { + // nothing to see here + } + + @Override + public void detach(IComputerAccess computer) { + // nothing to see here + } + + @Override + public boolean equals(IPeripheral other) { + return this == other; + } +} \ No newline at end of file diff --git a/src/cr0s/WarpDrive/machines/TileEntityTransporter.java b/src/cr0s/WarpDrive/machines/TileEntityTransporter.java new file mode 100644 index 00000000..e962fad6 --- /dev/null +++ b/src/cr0s/WarpDrive/machines/TileEntityTransporter.java @@ -0,0 +1,497 @@ +package cr0s.WarpDrive.machines; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import cr0s.WarpDrive.api.IUpgradable; +import cr0s.WarpDrive.data.EnumUpgradeTypes; +import cr0s.WarpDrive.data.Vector3; +import cr0s.WarpDrive.WarpDrive; +import cr0s.WarpDrive.WarpDriveConfig; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.ChatMessageComponent; +import net.minecraft.util.DamageSource; +import net.minecraftforge.common.ForgeDirection; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.lua.ILuaContext; +import dan200.computercraft.api.peripheral.IPeripheral; + +public class TileEntityTransporter extends WarpEnergyTE implements IPeripheral, IUpgradable +{ + private double scanRange=2; + + private int scanDist = 4; + + private double beaconEffect = 0; + private double powerBoost = 1; + private double baseLockStrength=-1; + private double lockStrengthMul = 1; + private boolean isLocked=false; + + private final static Vector3 centreOnMe = new Vector3(0.5D, 1.0D, 0.5D); + private Vector3 sourceVec = new Vector3(); + private Vector3 destVec = new Vector3(); + + private TeleporterDamage teleDam = new TeleporterDamage("teleporter"); + + private String[] methodArray = { + "source", + "dest", + "lock", + "release", + "lockStrength", + "energize", + "energy", + "powerBoost", + "energyCost", + "upgrades", + "help" }; + + @Override + public void updateEntity() { + super.updateEntity(); + + if(isLocked) { + if(lockStrengthMul > 0.8) { + lockStrengthMul *= 0.995; + } else { + lockStrengthMul*= 0.98; + } + } + } + + // IPeripheral overrides + @Override + public String getType() { + return "transporter"; + } + + private static String helpStr(Object[] function) { + if (function != null && function.length > 0) { + String fun = function[0].toString().toLowerCase(); + if(fun.equals("source")) { + if(WarpDriveConfig.TR_RELATIVE_COORDS) { + return "source(x,y,z): sets the coordinates (relative to the transporter) to teleport from\ndest(): returns the relative x,y,z coordinates of the source"; + } else { + return "source(x,y,z): sets the absolute coordinates to teleport from\ndest(): returns the x,y,z coordinates of the source"; + } + } else if(fun.equals("dest")) { + if(WarpDriveConfig.TR_RELATIVE_COORDS) { + return "dest(x,y,z): sets the coordinates (relative to the transporter) to teleport to\ndest(): returns the relative x,y,z coordinates of the destination"; + } else { + return "dest(x,y,z): sets the absolute coordinates to teleport to\ndest(): returns the x,y,z coordinates of the destination"; + } + } else if(fun.equals("lock")) { + return "lock(): locks the source and dest coordinates in and returns the lock strength (float)"; + } else if(fun.equals("release")) { + return "release(): releases the current lock"; + } else if(fun.equals("lockstrength")) { + return "lockStrength(): returns the current lock strength (float)"; + } else if(fun.equals("energize")) { + return "energize(): attempts to teleport all entities at source to dest. Returns the number of entities transported (-1 indicates a problem)."; + } else if(fun.equals("powerboost")) { + return "powerBoost(boostAmount): sets the level of power to use (1 being default), returns the level of power\npowerBoost(): returns the level of power"; + } else if(fun.equals("energycost")) { + return "energyCost(): returns the amount of energy it will take for a single entity to transport with the current settings"; + } else if(fun.equals("upgrades")) { + return WarpDrive.defUpgradeStr; + } else if(fun.equals("energy")) { + return WarpDrive.defEnergyStr; + } + } + return WarpDrive.defHelpStr; + } + + @Override + public String[] getMethodNames() { + return methodArray; + } + + private Object[] setVec3(boolean src,Object... arguments) { + Vector3 vec = src ? sourceVec : destVec; + + if (vec == null) { + Vector3 sV = WarpDriveConfig.TR_RELATIVE_COORDS ? new Vector3(this) : new Vector3(0,0,0); + if(src) + sourceVec = sV; + else + destVec = sV; + vec = src ? sourceVec : destVec; + } + + try { + if (arguments.length >= 3) { + unlock(); + vec.x = toDouble(arguments[0]); + vec.y = toDouble(arguments[1]); + vec.z = toDouble(arguments[2]); + } else if(arguments.length == 1) { + unlock(); + if(WarpDriveConfig.TR_RELATIVE_COORDS) { + vec.x = centreOnMe.x; + vec.y = centreOnMe.y; + vec.z = centreOnMe.z; + } else { + vec.x = xCoord + centreOnMe.x; + vec.y = yCoord + centreOnMe.y; + vec.z = zCoord + centreOnMe.z; + } + } + } catch(NumberFormatException e) { + return setVec3(src,"this"); + } + return new Object[] { vec.x, vec.y, vec.z }; + } + + @Override + public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception { + String methodName = methodArray[method]; + if (methodName.equals("energy")) { + return new Object[] { getEnergyStored(), getMaxEnergyStored() }; + } else if (methodName.equals("source")) { + return setVec3(true,arguments); + } else if (methodName.equals("dest")) { + return setVec3(false,arguments); + } else if (methodName.equals("lock")) { + return new Object[] { lock(sourceVec, destVec) }; + } else if (methodName.equals("release")) { + unlock(); + return null; + } else if (methodName.equals("lockStrength")) { + return new Object[] { getLockStrength() }; + } else if (methodName.equals("energize")) { + return new Object[] { energize () }; + } else if (methodName.equals("powerBoost")) { + try { + if (arguments.length >= 1) { + powerBoost = clamp(toDouble(arguments[0]),1,WarpDriveConfig.TR_MAX_BOOST_MUL); + } + } catch(NumberFormatException e) { + powerBoost = 1; + } + return new Object[] { powerBoost }; + } else if (methodName.equals("energyCost")) { + return new Object[] { energyCost() }; + } else if (methodName.equals("help")) { + return new Object[] { helpStr(arguments) }; + } + + return null; + } + + private Integer energyCost() { + if (sourceVec != null && destVec != null) { + return (int) Math.ceil(Math.pow(3, powerBoost - 1) * WarpDriveConfig.TR_EU_PER_METRE * sourceVec.distanceTo(destVec)); + } + return null; + } + + private int energize() { + if (isLocked) { + int count = 0; + double ls = getLockStrength(); + WarpDrive.debugPrint("LS:" + getLockStrength()); + ArrayList entitiesToTransport = findEntities(sourceVec, ls); + Integer energyReq = energyCost(); + if (energyReq == null) { + return -1; + } + Vector3 modDest = destVec.clone().translate(centreOnMe); + for(Entity ent : entitiesToTransport) { + WarpDrive.debugPrint("" + this + " Handling entity " + ent.getEntityName()); + if (consumeEnergy(energyReq, false)) { + WarpDrive.debugPrint("" + this + " Energy taken"); + inflictNegativeEffect(ent, ls); + transportEnt(ent, modDest); + count++; + } else { + break; + } + } + return count; + } + return -1; + } + + private void transportEnt(Entity ent, Vector3 dest) { + if (ent instanceof EntityLivingBase) { + EntityLivingBase livingEnt = (EntityLivingBase) ent; + if (WarpDriveConfig.TR_RELATIVE_COORDS) { + livingEnt.setPositionAndUpdate(xCoord+dest.x, yCoord+dest.y, zCoord+dest.z); + } else { + livingEnt.setPositionAndUpdate(dest.x, dest.y, dest.z); + } + } else { + if (WarpDriveConfig.TR_RELATIVE_COORDS) { + ent.setPosition(xCoord+dest.x, yCoord+dest.y, zCoord+dest.z); + } else { + ent.setPosition(dest.x, dest.y, dest.z); + } + } + } + + private void inflictNegativeEffect(Entity ent, double lockStrength) { + double value = Math.random() + lockStrength; + + WarpDrive.debugPrint("TRANSPORTER INFLICTION: " + value); + if (value < 0.1) { + ent.attackEntityFrom(teleDam, 1000); + } + + if (value < 0.2) { + ent.attackEntityFrom(teleDam, 10); + } + + if (value < 0.5) { + ent.attackEntityFrom(teleDam, 1); + } + } + + private double beaconScan(int xV, int yV, int zV) + { + WarpDrive.debugPrint("BeaconScan:" + xV + ","+yV + "," + zV); + double beacon = 0; + int beaconCount = 0; + int xL = xV - scanDist; + int xU = xV + scanDist; + int yL = yV - scanDist; + int yU = yV + scanDist; + int zL = zV - scanDist; + int zU = zV + scanDist; + for(int x=xL;x<=xU;x++) + { + for(int y=yL;y<=yU;y++) + { + if(y < 0 || y > 254) { + continue; + } + + for(int z=zL;z<=zU;z++) + { + if(worldObj.getBlockId(x, y, z) != WarpDriveConfig.transportBeaconID) { + continue; + } + double dist = 1 + Math.abs(x - xV) + Math.abs(y - yV) + Math.abs(z - zV); + beaconCount++; + if (worldObj.getBlockMetadata(x, y, z) == 0) { + beacon += 1/dist; + } else { + beacon -= 1/dist; + } + } + } + } + if (beaconCount > 0) { + beacon /= Math.sqrt(beaconCount); + } + return beacon; + } + + private double beaconScan(Vector3 s, Vector3 d) + { + s = absoluteVector(s); + d = absoluteVector(d); + return beaconScan(toInt(s.x), toInt(s.y), toInt(s.z)) + beaconScan(toInt(d.x), toInt(d.y), toInt(d.z)); + } + + private Vector3 absoluteVector(Vector3 a) + { + if(WarpDriveConfig.TR_RELATIVE_COORDS) + return a.clone().translate(new Vector3(this)); + else + return a; + } + + private double calculatePower(Vector3 d) + { + Vector3 myCoords; + if(WarpDriveConfig.TR_RELATIVE_COORDS) + myCoords = centreOnMe; + else + myCoords = new Vector3(this).translate(centreOnMe); + return calculatePower(myCoords,d); + } + + private static double calculatePower(Vector3 s, Vector3 d) + { + double dist = s.distanceTo(d); + return clamp(Math.pow(Math.E, -dist / 300), 0, 1); + } + + private static double min(double... ds) + { + double curMin = Double.MAX_VALUE; + for(double d: ds) + curMin = Math.min(curMin, d); + return curMin; + } + + private double getLockStrength() { + if (isLocked) { + double upgradeBoost = 1; + if (upgrades.containsKey(EnumUpgradeTypes.Range)) + upgradeBoost = Math.pow(1.2, upgrades.get(EnumUpgradeTypes.Range)); + return clamp(baseLockStrength * lockStrengthMul * Math.pow(2, powerBoost-1) * upgradeBoost * (1 + beaconEffect), 0, 1); + } + return -1; + } + + private void unlock() { + isLocked = false; + baseLockStrength = 0; + } + + private double lock(Vector3 source,Vector3 dest) { + if (source != null && dest != null) { + double basePower = min(calculatePower(source), calculatePower(dest), calculatePower(source,dest)); + beaconEffect = beaconScan(source, dest); + WarpDrive.debugPrint("BEACON:" + beaconEffect); + baseLockStrength = basePower; + lockStrengthMul = 1; + isLocked = true; + WarpDrive.debugPrint(baseLockStrength + "," + getLockStrength()); + return getLockStrength(); + } else { + unlock(); + return 0; + } + } + + private AxisAlignedBB getAABB() { + Vector3 tS = new Vector3(this); + Vector3 bS = new Vector3(this); + Vector3 scanPos = new Vector3( scanRange/2, 2, scanRange/2); + Vector3 scanNeg = new Vector3(-scanRange/2,-1,-scanRange/2); + if(WarpDriveConfig.TR_RELATIVE_COORDS) { + tS.translate(sourceVec).translate(scanPos); + bS.translate(sourceVec).translate(scanNeg); + } else { + tS = sourceVec.clone().translate(scanPos); + bS = sourceVec.clone().translate(scanNeg); + } + return AxisAlignedBB.getBoundingBox(bS.x,bS.y,bS.z,tS.x,tS.y,tS.z); + } + + private ArrayList findEntities(Vector3 source, double lockStrength) { + AxisAlignedBB bb = getAABB(); + WarpDrive.debugPrint("Transporter:" +bb.toString()); + List data = worldObj.getEntitiesWithinAABBExcludingEntity(null, bb); + ArrayList output = new ArrayList(data.size()); + for(Object ent : data) { + if (lockStrength >= 1 || worldObj.rand.nextDouble() < lockStrength) {// If weak lock, don't transport + WarpDrive.debugPrint("" + this + " Entity '" + ent.toString() + "' found and added"); + if (ent instanceof Entity) { + output.add((Entity) ent); + } + } else { + WarpDrive.debugPrint("" + this + " Entity '" + ent.toString() + "' discarded"); + } + } + return output; + } + + @Override + public void attach(IComputerAccess computer) {} + + @Override + public void detach(IComputerAccess computer) {} + + @Override + public int getMaxEnergyStored() { + int max = WarpDriveConfig.TR_MAX_ENERGY; + if (upgrades.containsKey(EnumUpgradeTypes.Energy)) { + max = (int) Math.floor(max * Math.pow(1.2, upgrades.get(EnumUpgradeTypes.Energy))); + } + return max; + } + + @Override + public boolean canInputEnergy(ForgeDirection from) { + if (from == ForgeDirection.UP) { + return false; + } + return true; + } + + @Override + public int getMaxSafeInput() { + return Integer.MAX_VALUE; + } + + @Override + public void writeToNBT(NBTTagCompound tag) { + super.writeToNBT(tag); + tag.setDouble("powerBoost", powerBoost); + } + + @Override + public void readFromNBT(NBTTagCompound tag) { + super.readFromNBT(tag); + powerBoost = tag.getDouble("powerBoost"); + } + + class TeleporterDamage extends DamageSource { + protected TeleporterDamage(String par1Str) { + super(par1Str); + } + + @Override + public ChatMessageComponent getDeathMessage(EntityLivingBase e) { + String mess = ""; + if(e instanceof EntityPlayer || e instanceof EntityPlayerMP) { + mess = ((EntityPlayer) e).username + " was killed by a teleporter malfunction"; + } else { + mess = e.getEntityName() + " was killed by a teleporter malfunction"; + } + + WarpDrive.debugPrint(mess); + return ChatMessageComponent.createFromText(mess); + } + } + + @Override + public boolean equals(IPeripheral other) { + return other == this; + } + + @Override + public boolean takeUpgrade(EnumUpgradeTypes upgradeType, boolean simulate) + { + int max = 0; + if(upgradeType == EnumUpgradeTypes.Energy) + max = 2; + else if(upgradeType == EnumUpgradeTypes.Power) + max = 4; + else if(upgradeType == EnumUpgradeTypes.Range) + max = 4; + + if(max == 0) + return false; + + if(upgrades.containsKey(upgradeType)) + if(upgrades.get(upgradeType) >= max) + return false; + + if(!simulate) + { + int c = 0; + if(upgrades.containsKey(upgradeType)) + c = upgrades.get(upgradeType); + upgrades.put(upgradeType, c+1); + } + return true; + } + + @Override + public Map getInstalledUpgrades() + { + return upgrades; + } +} diff --git a/src/cr0s/WarpDrive/machines/WarpBlockContainer.java b/src/cr0s/WarpDrive/machines/WarpBlockContainer.java index 93fde8f5..df15dbf2 100644 --- a/src/cr0s/WarpDrive/machines/WarpBlockContainer.java +++ b/src/cr0s/WarpDrive/machines/WarpBlockContainer.java @@ -5,6 +5,7 @@ import cr0s.WarpDrive.WarpDrive; import cr0s.WarpDrive.api.IBlockUpdateDetector; import cr0s.WarpDrive.api.IUpgradable; import cr0s.WarpDrive.data.EnumUpgradeTypes; +import cr0s.WarpDrive.item.ItemWarpUpgrade; import net.minecraft.block.Block; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; @@ -35,6 +36,44 @@ public abstract class WarpBlockContainer extends BlockContainer { } } + /* FIXME untested + @Override + public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int par6, float par7, float par8, float par9) + { + if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { + return false; + } + + boolean hasResponse = false; + TileEntity te = world.getBlockTileEntity(x, y, z); + if(te != null && te instanceof IUpgradable) + { + IUpgradable upgradable = (IUpgradable)te; + ItemStack is = player.inventory.getCurrentItem(); + if(is != null) + { + Item i = is.getItem(); + if(i instanceof ItemWarpUpgrade) + { + if(upgradable.takeUpgrade(EnumUpgradeTypes.values()[is.getItemDamage()],false)) + { + if(!player.capabilities.isCreativeMode) + player.inventory.decrStackSize(player.inventory.currentItem, 1); + player.addChatMessage("Upgrade accepted"); + } + else + { + player.addChatMessage("Upgrade declined"); + } + hasResponse = true; + } + } + } + + return hasResponse; + } + /**/ + @Override public void onNeighborBlockChange(World w, int x, int y, int z, int b) { super.onNeighborBlockChange(w, x, y, z, b);