diff --git a/LICENSE b/LICENSE
index e4a728039..730f0b8c4 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2013-2014 Florian "Sangar" Nücke
+Copyright (c) 2013-2015 Florian "Sangar" Nücke
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 1daa8f8da..fb9f75438 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ A few useful links:
You can find experimental builds [on the build server][jenkins]. Expect these to be generally more unstable than builds marked as releases. Use these **at your own risk**, but - when using the latest one - please *do* report bugs you encounter using them. Thanks!
## License / Use in Modpacks
-This mod is [licensed under the **MIT license**](https://github.com/MightyPirates/OpenComputers/blob/master/LICENSE). All **assets are public domain**, unless otherwise stated; all are free to be distributed as long as the license / source credits are kept. This means you can use this mod in any mod pack **as you please**. I'd be happy to hear about you using it, though, just out of curiosity.
+This mod is [licensed under the **MIT license**](https://github.com/MightyPirates/OpenComputers/blob/master-MC1.7.10/LICENSE). All **assets are public domain**, unless otherwise stated; all are free to be distributed as long as the license / source credits are kept. This means you can use this mod in any mod pack **as you please**. I'd be happy to hear about you using it, though, just out of curiosity.
## Contributing
###Assets and Localizations
diff --git a/build.gradle b/build.gradle
index 01568b464..8409c5c16 100644
--- a/build.gradle
+++ b/build.gradle
@@ -17,6 +17,7 @@ buildscript {
apply plugin: 'scala'
apply plugin: 'forge'
+apply plugin: 'idea'
apply plugin: 'maven-publish'
file "build.properties" withReader {
@@ -136,6 +137,10 @@ repositories {
name 'Railcraft'
artifactPattern "http://addons.cursecdn.com/files/${config.rc.cf}/[module]_[revision].[ext]"
}
+ ivy {
+ name 'BloodMagic'
+ artifactPattern "http://addons.cursecdn.com/files/${config.bloodmagic.cf}/[module]-${config.minecraft.version}-[revision].[ext]"
+ }
*/
}
@@ -173,6 +178,8 @@ dependencies {
provided name: 'ComputerCraft', version: config.cc.version, ext: 'jar'
provided name: 'EnderIO', version: config.eio.version, ext: 'jar'
provided name: 'Railcraft', version: config.rc.version, ext: 'jar'
+ provided name: 'BloodMagic', version: config.bloodmagic.version, ext: 'jar'
+
*/
compile 'com.google.code.findbugs:jsr305:1.3.9' // Annotations used by google libs.
@@ -317,8 +324,8 @@ publishing {
}
// this is needed for IntelliJ so we don't have to copy over the assets manually every time
-sourceSets {
- main {
- output.resourcesDir = output.classesDir
+idea {
+ module {
+ outputDir = file('build/classes/main')
}
}
diff --git a/build.properties b/build.properties
index c03c07a4c..5232bceff 100644
--- a/build.properties
+++ b/build.properties
@@ -1,17 +1,19 @@
minecraft.version=1.8
forge.version=11.14.0.1280-1.8
-oc.version=2.0.0
+oc.version=1.4.6
oc.subversion=dev
ae2.version=rv1-stable-1
bc.version=6.2.6
+bloodmagic.cf=2223/203
+bloodmagic.version=1.3.0a-1
cc.cf=2216/236
cc.version=1.65
ccc.version=1.0.5.34
ccl.version=1.1.2.115
-cofhlib.cf=2212/893
-cofhlib.version=[1.7.10]1.0.0B6-dev-26
+cofhlib.cf=2218/257
+cofhlib.version=[1.7.10]1.0.0B7-dev-29
eio.cf=2219/296
eio.version=1.7.10-2.2.1.276
es.version=1.4.5.24
diff --git a/src/main/java/li/cil/oc/api/component/TextBuffer.java b/src/main/java/li/cil/oc/api/component/TextBuffer.java
index e45c40af4..774255ded 100644
--- a/src/main/java/li/cil/oc/api/component/TextBuffer.java
+++ b/src/main/java/li/cil/oc/api/component/TextBuffer.java
@@ -341,6 +341,71 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
*/
boolean isBackgroundFromPalette(int column, int row);
+ /**
+ * Overwrites a portion of the text in raw mode.
+ *
+ * This will copy the given char array into the buffer, starting at the
+ * specified column and row. The array is expected to be indexed row-
+ * first, i.e. the first dimension is the vertical axis, the second
+ * the horizontal.
+ *
+ * Important: this performs no checks as to whether something
+ * actually changed. It will always send the changed patch to clients.
+ * It will also not crop the specified array to the actually used range.
+ * In other words, this is not intended to be exposed as-is to user code,
+ * it should always be called with validated, and, as necessary, cropped
+ * values.
+ *
+ * @param column the horizontal index.
+ * @param row the vertical index.
+ * @param text the text to write.
+ */
+ void rawSetText(int column, int row, char[][] text);
+
+ /**
+ * Overwrites a portion of the foreground color information in raw mode.
+ *
+ * This will convert the specified RGB data (in 0xRRGGBB format)
+ * to the internal, packed representation and copy it into the buffer,
+ * starting at the specified column and row. The array is expected to be
+ * indexed row-first, i.e. the first dimension is the vertical axis, the
+ * second the horizontal.
+ *
+ * Important: this performs no checks as to whether something
+ * actually changed. It will always send the changed patch to clients.
+ * It will also not crop the specified array to the actually used range.
+ * In other words, this is not intended to be exposed as-is to user code,
+ * it should always be called with validated, and, as necessary, cropped
+ * values.
+ *
+ * @param column the horizontal index.
+ * @param row the vertical index.
+ * @param color the foreground color data to write.
+ */
+ void rawSetForeground(int column, int row, int[][] color);
+
+ /**
+ * Overwrites a portion of the background color information in raw mode.
+ *
+ * This will convert the specified RGB data (in 0xRRGGBB format)
+ * to the internal, packed representation and copy it into the buffer,
+ * starting at the specified column and row. The array is expected to be
+ * indexed row-first, i.e. the first dimension is the vertical axis, the
+ * second the horizontal.
+ *
+ * Important: this performs no checks as to whether something
+ * actually changed. It will always send the changed patch to clients.
+ * It will also not crop the specified array to the actually used range.
+ * In other words, this is not intended to be exposed as-is to user code,
+ * it should always be called with validated, and, as necessary, cropped
+ * values.
+ *
+ * @param column the horizontal index.
+ * @param row the vertical index.
+ * @param color the background color data to write.
+ */
+ void rawSetBackground(int column, int row, int[][] color);
+
// ----------------------------------------------------------------------- //
/**
@@ -452,7 +517,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
* @param button the button of the mouse that was pressed.
* @param player the player that pressed the mouse button. Pass null on the client side.
*/
- void mouseDown(int x, int y, int button, EntityPlayer player);
+ void mouseDown(double x, double y, int button, EntityPlayer player);
/**
* Signals a mouse drag event for the buffer.
@@ -465,7 +530,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
* @param button the button of the mouse that is pressed.
* @param player the player that moved the mouse. Pass null on the client side.
*/
- void mouseDrag(int x, int y, int button, EntityPlayer player);
+ void mouseDrag(double x, double y, int button, EntityPlayer player);
/**
* Signals a mouse button release event for the buffer.
@@ -478,7 +543,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
* @param button the button of the mouse that was released.
* @param player the player that released the mouse button. Pass null on the client side.
*/
- void mouseUp(int x, int y, int button, EntityPlayer player);
+ void mouseUp(double x, double y, int button, EntityPlayer player);
/**
* Signals a mouse wheel scroll event for the buffer.
@@ -491,7 +556,7 @@ public interface TextBuffer extends ManagedEnvironment, Persistable {
* @param delta indicates the direction of the mouse scroll.
* @param player the player that scrolled the mouse wheel. Pass null on the client side.
*/
- void mouseScroll(int x, int y, int delta, EntityPlayer player);
+ void mouseScroll(double x, double y, int delta, EntityPlayer player);
// ----------------------------------------------------------------------- //
diff --git a/src/main/java/li/cil/oc/api/network/ManagedPeripheral.java b/src/main/java/li/cil/oc/api/network/ManagedPeripheral.java
index b12c8ff9e..3e69def05 100644
--- a/src/main/java/li/cil/oc/api/network/ManagedPeripheral.java
+++ b/src/main/java/li/cil/oc/api/network/ManagedPeripheral.java
@@ -6,7 +6,7 @@ import li.cil.oc.api.machine.Context;
/**
* This interface can be used with an {@link li.cil.oc.api.network.Environment}
* and is intended to be used for environments wrapping a ComputerCraft
- * peripheral. Tt could be used for other purposes as well, though. It allows
+ * peripheral. It could be used for other purposes as well, though. It allows
* providing method names in addition to those defined via the
* {@link li.cil.oc.api.machine.Callback} annotation, and invoking said methods.
*/
diff --git a/src/main/java/li/cil/oc/api/network/SidedComponent.java b/src/main/java/li/cil/oc/api/network/SidedComponent.java
new file mode 100644
index 000000000..bc5eea0dd
--- /dev/null
+++ b/src/main/java/li/cil/oc/api/network/SidedComponent.java
@@ -0,0 +1,26 @@
+package li.cil.oc.api.network;
+
+import net.minecraft.util.EnumFacing;
+
+/**
+ * This is an extended version of {@link li.cil.oc.api.network.SimpleComponent}
+ * which allows controlling connectivity on a side-by-side basis.
+ *
+ * Like the SimpleComponent interface, this is intended to be used
+ * with tile entities that should act as OC components. Please see the
+ * SimpleComponent interface for more information.
+ */
+public interface SidedComponent {
+ /**
+ * Whether this component can connect to a node on the specified side.
+ *
+ * The provided side is relative to the component, i.e. when the tile
+ * entity sits at (0, 0, 0) and is asked for its southern node (positive
+ * Z axis) it has to return the connectivity for the face between it and
+ * the block at (0, 0, 1).
+ *
+ * @param side the side to check for.
+ * @return whether the component may be connected to from the specified side.
+ */
+ boolean canConnectNode(EnumFacing side);
+}
diff --git a/src/main/resources/LICENSE b/src/main/resources/LICENSE
index 68dd6e055..8e9ad6ecb 100644
--- a/src/main/resources/LICENSE
+++ b/src/main/resources/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2013-2014 Florian "Sangar" Nücke
+Copyright (c) 2013-2015 Florian "Sangar" Nücke
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf
index c79466de2..ec5211626 100644
--- a/src/main/resources/application.conf
+++ b/src/main/resources/application.conf
@@ -105,6 +105,18 @@ opencomputers {
# importantly, can only render code page 437 (as opposed to...
# a *lot* of unicode).
fontRenderer: "unifont"
+
+ # The sample rate used for generating beeps of computers' internal
+ # speakers. Use custom values at your own responsibility here; if it
+ # breaks OC you'll get no support. Some potentially reasonable
+ # lower values are 16000 or even 8000 (which was the old default, but
+ # leads to artifacting on certain frequencies).
+ beepSampleRate: 44100
+
+ # The base volume of beeps generated by computers. This may be in a
+ # range of [0, 127], where 0 means mute (the sound will not even be
+ # generated), and 127 means maximum amplitude / volume.
+ beepVolume: 32
}
# Computer related settings, concerns server performance and security.
@@ -675,11 +687,11 @@ opencomputers {
# each point of complexity.
tabletAssemblyComplexity: 5000
- # The base energy cost for assembling a microcontroller.
+ # The base energy cost for assembling a drone.
droneAssemblyBase: 25000
# The additional amount of energy required to assemble a
- # microcontroller for each point of complexity.
+ # drone for each point of complexity.
droneAssemblyComplexity: 15000
# The amount of energy it takes to extract one ingredient from an
diff --git a/src/main/resources/assets/opencomputers/lang/en_US.lang b/src/main/resources/assets/opencomputers/lang/en_US.lang
index b962ef1bd..c2854fe7b 100644
--- a/src/main/resources/assets/opencomputers/lang/en_US.lang
+++ b/src/main/resources/assets/opencomputers/lang/en_US.lang
@@ -298,7 +298,7 @@ oc:tooltip.UpgradePiston=This upgrade is very pushy. It allows moving blocks, si
oc:tooltip.UpgradeSign=Allows reading text on and writing text to signs.
oc:tooltip.UpgradeSolarGenerator=Can be used to generate energy from sunlight on the go. Requires a clear line of sight to the sky above the device. Generates energy at %s%% of the speed of a Stirling Engine.
oc:tooltip.UpgradeTank=This upgrade provides a tank for fluid storage for robots and drones. Without one of these, they will not be able to store fluids internally.
-oc:tooltip.UpgradeTankController=This upgrade allows the robots and drones more control in how they interacts with external tanks, and allows them to transfer fluids into and out of fluid tank items in their inventory.
+oc:tooltip.UpgradeTankController=This upgrade allows robots and drones more control in how they interacts with external tanks, and allows them to transfer fluids into and out of fluid tank items in their inventory.
oc:tooltip.UpgradeTractorBeam=Equips a device with extremely advanced technology, nicknamed the "Item Magnet". Allows the device to pick up items anywhere within 3 blocks of its location.
oc:tooltip.WirelessNetworkCard=Allows wireless sending of network messages in addition to normal ones. You can adjust the §fsignal strength§7 to control how far messages are sent. Higher signal strength results in higher energy consumption.
oc:tooltip.WorldSensorCard=Allows reading out information about the world, such as its gravity and whether it has a breathable atmosphere. Use results at own risk. The manufacturer takes no responsibility for bodily or material harm caused by decisions made upon the cards' outputs. We have lawyers. And money. Don't even try.
@@ -308,7 +308,7 @@ item.oc.AbstractBusCard.usage=This card allows computers, servers and robots to
item.oc.Analyzer.usage=The §oAnalyzer§r is a handy tool for getting some information about OpenComputers-related blocks in the world. Simply (sneak-)activate a block to get some information printed to the chat. This ranges from basic things like the address of components, to power levels in the subnetwork the block is in, and information on the error lead to a computer to crash, for example.[nl][nl]Another useful functionality is that when using the using the analyzer on a block while holding down [Ctrl] the address of the block component will be copied to the clipboard.
item.oc.ComponentBus.usage=A §oComponent Bus§r is a server-specific upgrade that allows the server to communicate with more components at the same time, without shutting down. Like with CPUs, higher tier buses provide higher component limits.
item.oc.CPU.usage=The §oCentral Processing Unit§r is a core part for each computer. It defines the architecture of the computer, and the number of components that can be connected to the computer before it stops working. Higher tier CPUs also provide a higher per-tick direct call limit to the computer - in simpler terms: better CPUs run faster.
-item.oc.DebugCard.usage=The §oDebug Card§r is a non-craftable item that was originally only intended to make debugging things easier, by automating some processes. It has since gotten a bunch more functionality, making it quite useful for custom map-making.
+item.oc.DebugCard.usage=The §oDebug Card§r is a non-craftable item that was originally only intended to make debugging things easier, by automating some processes. It has since gotten a bunch more functionality, making it quite useful for custom map-making.[nl][nl]Note that you can use shift-rightclick while holding the card to bind it to you / unbind it, meaning §orunCommand§r will be performed using your permission levels instead of the default OpenComputers ones.
item.oc.DroneCase.usage=The §oDrone Case§r is used to build Drones in the Assembler. Drones are light-weight, fast and very mobile machines with limited functionality. Unlike Robots they cannot use tools, and can interact with the world only in a relatively limited manner.[nl][nl]They make up for their limitations with speed and lower running energy costs. They are well suited for transport of small amounts of items, and ideal for reconnaissance. Pairing a Drone with a Robot can be quite powerful, with the Robot doing the "hard work", and the Drone providing information about the environment and transporting items to and from a central hub, for example.[nl][nl]Like microcontrollers, Drones can only be programmed using their EEPROM. Accordingly, the EEPROM can be changed by recrafting the Drone with another EEPROM.
item.oc.eeprom.usage=The §oEEPROM§r is what contains the code used to initialize a computer when it is being booted. This data is stored as a plain byte array, and may mean different things to different CPU architectures. For example, for Lua it is usually a small script that searches for file systems with an init script, for other architectures it may be actual machine code.
item.oc.FloppyDisk.usage=The §oFloppy Disk§r is the cheapest and smallest type of storage medium in OpenComputers. It is a handy early game way of storing data and transferring it between computers and robots. You may also find floppy disks with useful programs on them in dungeon chests.[nl][nl]Beware: shift-rightclicking while holding a floppy disk in your hand will wipe the floppy disk!
diff --git a/src/main/resources/assets/opencomputers/loot/OpenIRC/irc.lua b/src/main/resources/assets/opencomputers/loot/OpenIRC/irc.lua
index 9e0d7bee3..bd3018aa5 100644
--- a/src/main/resources/assets/opencomputers/loot/OpenIRC/irc.lua
+++ b/src/main/resources/assets/opencomputers/loot/OpenIRC/irc.lua
@@ -17,13 +17,17 @@ local text = require("text")
local args, options = shell.parse(...)
if #args < 1 then
- print("Usage: irc [server:port]")
+ print("Usage: irc [server[:port]]")
return
end
local nick = args[1]
local host = args[2] or "irc.esper.net:6667"
+if not host:find(":") then
+ host = host .. ":6667"
+end
+
-- try to connect to server.
local sock, reason = internet.open(host)
if not sock then
diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/boot/04_component.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/boot/04_component.lua
index 287f27862..c58ca54c0 100644
--- a/src/main/resources/assets/opencomputers/loot/OpenOS/boot/04_component.lua
+++ b/src/main/resources/assets/opencomputers/loot/OpenOS/boot/04_component.lua
@@ -27,7 +27,7 @@ end
function component.isAvailable(componentType)
checkArg(1, componentType, "string")
- if not primaries[componentType] then
+ if not primaries[componentType] and not adding[componentType] then
-- This is mostly to avoid out of memory errors preventing proxy
-- creation cause confusion by trying to create the proxy again,
-- causing the oom error to be thrown again.
diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/filesystem.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/filesystem.lua
index 0ab4e4e63..9904ed9d8 100644
--- a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/filesystem.lua
+++ b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/filesystem.lua
@@ -351,8 +351,8 @@ function filesystem.list(path)
table.remove(result, i)
else
f = result[i]
+ i = i + 1
end
- i = i + 1
end
local i = 0
return function()
@@ -376,22 +376,31 @@ function filesystem.makeDirectory(path)
end
function filesystem.remove(path)
- local node, rest, vnode, vrest = findNode(filesystem.path(path))
- local name = filesystem.name(path)
- if vnode.children[name] then
- vnode.children[name] = nil
- removeEmptyNodes(vnode)
- return true
- elseif vnode.links[name] then
- vnode.links[name] = nil
- removeEmptyNodes(vnode)
- return true
- else
+ local function removeVirtual()
+ local node, rest, vnode, vrest = findNode(filesystem.path(path))
+ local name = filesystem.name(path)
+ if vnode.children[name] then
+ vnode.children[name] = nil
+ removeEmptyNodes(vnode)
+ return true
+ elseif vnode.links[name] then
+ vnode.links[name] = nil
+ removeEmptyNodes(vnode)
+ return true
+ end
+ return false
+ end
+ local function removePhysical()
node, rest = findNode(path)
if node.fs and rest then
return component.proxy(node.fs).remove(rest)
end
- return nil, "no such file or directory"
+ return false
+ end
+ local success = removeVirtual()
+ success = removePhysical() or success -- Always run.
+ if success then return true
+ else return nil, "no such file or directory"
end
end
diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/term.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/term.lua
index 03a53556e..617441312 100644
--- a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/term.lua
+++ b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/term.lua
@@ -108,10 +108,11 @@ function term.isAvailable()
return component.isAvailable("gpu") and component.isAvailable("screen")
end
-function term.read(history, dobreak, hint, pwchar)
+function term.read(history, dobreak, hint, pwchar, filter)
checkArg(1, history, "table", "nil")
checkArg(3, hint, "function", "table", "nil")
checkArg(4, pwchar, "string", "nil")
+ checkArg(5, filter, "string", "function", "nil")
history = history or {}
table.insert(history, "")
local offset = term.getCursor() - 1
@@ -130,6 +131,13 @@ function term.read(history, dobreak, hint, pwchar)
pwchar = unicode.sub(pwchar, 1, 1)
end
+ if type(filter) == "string" then
+ local pattern = filter
+ filter = function(line)
+ return line:match(pattern)
+ end
+ end
+
local function masktext(str)
return pwchar and pwchar:rep(unicode.len(str)) or str
end
@@ -327,12 +335,16 @@ function term.read(history, dobreak, hint, pwchar)
elseif code == keyboard.keys.tab and hint then
tab(keyboard.isShiftDown() and -1 or 1)
elseif code == keyboard.keys.enter then
- local cbx, cby = getCursor()
- if cby ~= #history then -- bring entry to front
- history[#history] = line()
- table.remove(history, cby)
+ if not filter or filter(line() or "") then
+ local cbx, cby = getCursor()
+ if cby ~= #history then -- bring entry to front
+ history[#history] = line()
+ table.remove(history, cby)
+ end
+ return true, history[#history] .. "\n"
+ else
+ computer.beep(2000, 0.1)
end
- return true, history[#history] .. "\n"
elseif keyboard.isControlDown() and code == keyboard.keys.d then
if line() == "" then
history[#history] = ""
diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/echo b/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/echo
index b6337a2b1..d867b58e6 100644
--- a/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/echo
+++ b/src/main/resources/assets/opencomputers/loot/OpenOS/usr/man/echo
@@ -9,7 +9,7 @@ DESCRIPTION
EXAMPLES
echo test
- Print `test` to the terminal.
+ Print `test` to the standard output (which is usually the terminal).
- echo "a b" > test
- Writes the string `a b` to the standard output, which is redirected into file `test`.
\ No newline at end of file
+ echo "a b"
+ Writes the string `a b`.
\ No newline at end of file
diff --git a/src/main/resources/assets/opencomputers/sounds/preload.cfg b/src/main/resources/assets/opencomputers/sounds/preload.cfg
new file mode 100644
index 000000000..e7334d6c8
--- /dev/null
+++ b/src/main/resources/assets/opencomputers/sounds/preload.cfg
@@ -0,0 +1,16 @@
+assets/opencomputers/sounds/computer_running.ogg
+assets/opencomputers/sounds/floppy_access1.ogg
+assets/opencomputers/sounds/floppy_access2.ogg
+assets/opencomputers/sounds/floppy_access3.ogg
+assets/opencomputers/sounds/floppy_access4.ogg
+assets/opencomputers/sounds/floppy_access5.ogg
+assets/opencomputers/sounds/floppy_access6.ogg
+assets/opencomputers/sounds/floppy_eject.ogg
+assets/opencomputers/sounds/floppy_insert.ogg
+assets/opencomputers/sounds/hdd_access1.ogg
+assets/opencomputers/sounds/hdd_access2.ogg
+assets/opencomputers/sounds/hdd_access3.ogg
+assets/opencomputers/sounds/hdd_access4.ogg
+assets/opencomputers/sounds/hdd_access5.ogg
+assets/opencomputers/sounds/hdd_access6.ogg
+assets/opencomputers/sounds/hdd_access7.ogg
\ No newline at end of file
diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala
index c00f41c4d..6d88581cc 100644
--- a/src/main/scala/li/cil/oc/Settings.scala
+++ b/src/main/scala/li/cil/oc/Settings.scala
@@ -49,6 +49,8 @@ class Settings(val config: Config) {
}
val monochromeColor = Integer.decode(config.getString("client.monochromeColor"))
val fontRenderer = config.getString("client.fontRenderer")
+ val beepSampleRate = config.getInt("client.beepSampleRate")
+ val beepAmplitude = config.getInt("client.beepVolume") max 0 min Byte.MaxValue
// ----------------------------------------------------------------------- //
// computer
diff --git a/src/main/scala/li/cil/oc/client/KeyBindings.scala b/src/main/scala/li/cil/oc/client/KeyBindings.scala
index 55dbb5c21..154749ba8 100644
--- a/src/main/scala/li/cil/oc/client/KeyBindings.scala
+++ b/src/main/scala/li/cil/oc/client/KeyBindings.scala
@@ -5,9 +5,13 @@ import net.minecraftforge.fml.client.FMLClientHandler
import org.lwjgl.input.Keyboard
object KeyBindings {
- def showExtendedTooltips = Keyboard.isCreated && Keyboard.isKeyDown(extendedTooltip.getKeyCode)
+ def showExtendedTooltips = Keyboard.isCreated && (try Keyboard.isKeyDown(extendedTooltip.getKeyCode) catch {
+ case _: Throwable => false // Don't ask me, sometimes things can apparently screw up LWJGL's keyboard handling.
+ })
- def showMaterialCosts = Keyboard.isCreated && Keyboard.isKeyDown(materialCosts.getKeyCode)
+ def showMaterialCosts = Keyboard.isCreated && (try Keyboard.isKeyDown(materialCosts.getKeyCode) catch {
+ case _: Throwable => false // Don't ask me, sometimes things can apparently screw up LWJGL's keyboard handling.
+ })
def extendedTooltip = FMLClientHandler.instance.getClient.gameSettings.keyBindSneak
diff --git a/src/main/scala/li/cil/oc/client/PacketHandler.scala b/src/main/scala/li/cil/oc/client/PacketHandler.scala
index cdb79a1d7..2ff1f5f27 100644
--- a/src/main/scala/li/cil/oc/client/PacketHandler.scala
+++ b/src/main/scala/li/cil/oc/client/PacketHandler.scala
@@ -355,6 +355,9 @@ object PacketHandler extends CommonPacketHandler {
case PacketType.TextBufferMultiResolutionChange => onTextBufferMultiResolutionChange(p, buffer)
case PacketType.TextBufferMultiMaxResolutionChange => onTextBufferMultiMaxResolutionChange(p, buffer)
case PacketType.TextBufferMultiSet => onTextBufferMultiSet(p, buffer)
+ case PacketType.TextBufferMultiRawSetText => onTextBufferMultiRawSetText(p, buffer)
+ case PacketType.TextBufferMultiRawSetBackground => onTextBufferMultiRawSetBackground(p, buffer)
+ case PacketType.TextBufferMultiRawSetForeground => onTextBufferMultiRawSetForeground(p, buffer)
case _ => // Invalid packet.
}
}
@@ -426,6 +429,60 @@ object PacketHandler extends CommonPacketHandler {
buffer.set(col, row, s, vertical)
}
+ def onTextBufferMultiRawSetText(p: PacketParser, buffer: component.TextBuffer) {
+ val col = p.readInt()
+ val row = p.readInt()
+
+ val rows = p.readShort()
+ val text = new Array[Array[Char]](rows)
+ for (y <- 0 until rows) {
+ val cols = p.readShort()
+ val line = new Array[Char](cols)
+ for (x <- 0 until cols) {
+ line(x) = p.readChar()
+ }
+ text(y) = line
+ }
+
+ buffer.rawSetText(col, row, text)
+ }
+
+ def onTextBufferMultiRawSetBackground(p: PacketParser, buffer: component.TextBuffer) {
+ val col = p.readInt()
+ val row = p.readInt()
+
+ val rows = p.readShort()
+ val color = new Array[Array[Int]](rows)
+ for (y <- 0 until rows) {
+ val cols = p.readShort()
+ val line = new Array[Int](cols)
+ for (x <- 0 until cols) {
+ line(x) = p.readInt()
+ }
+ color(y) = line
+ }
+
+ buffer.rawSetBackground(col, row, color)
+ }
+
+ def onTextBufferMultiRawSetForeground(p: PacketParser, buffer: component.TextBuffer) {
+ val col = p.readInt()
+ val row = p.readInt()
+
+ val rows = p.readShort()
+ val color = new Array[Array[Int]](rows)
+ for (y <- 0 until rows) {
+ val cols = p.readShort()
+ val line = new Array[Int](cols)
+ for (x <- 0 until cols) {
+ line(x) = p.readInt()
+ }
+ color(y) = line
+ }
+
+ buffer.rawSetForeground(col, row, color)
+ }
+
def onScreenTouchMode(p: PacketParser) =
p.readTileEntity[Screen]() match {
case Some(t) => t.invertTouchMode = p.readBoolean()
diff --git a/src/main/scala/li/cil/oc/client/PacketSender.scala b/src/main/scala/li/cil/oc/client/PacketSender.scala
index 4e18b9378..3182a73aa 100644
--- a/src/main/scala/li/cil/oc/client/PacketSender.scala
+++ b/src/main/scala/li/cil/oc/client/PacketSender.scala
@@ -76,35 +76,35 @@ object PacketSender {
}
}
- def sendMouseClick(address: String, x: Int, y: Int, drag: Boolean, button: Int) {
+ def sendMouseClick(address: String, x: Double, y: Double, drag: Boolean, button: Int) {
val pb = new SimplePacketBuilder(PacketType.MouseClickOrDrag)
pb.writeUTF(address)
- pb.writeShort(x)
- pb.writeShort(y)
+ pb.writeFloat(x.toFloat)
+ pb.writeFloat(y.toFloat)
pb.writeBoolean(drag)
pb.writeByte(button.toByte)
pb.sendToServer()
}
- def sendMouseScroll(address: String, x: Int, y: Int, scroll: Int) {
+ def sendMouseScroll(address: String, x: Double, y: Double, scroll: Int) {
val pb = new SimplePacketBuilder(PacketType.MouseScroll)
pb.writeUTF(address)
- pb.writeShort(x)
- pb.writeShort(y)
+ pb.writeFloat(x.toFloat)
+ pb.writeFloat(y.toFloat)
pb.writeByte(scroll)
pb.sendToServer()
}
- def sendMouseUp(address: String, x: Int, y: Int, button: Int) {
+ def sendMouseUp(address: String, x: Double, y: Double, button: Int) {
val pb = new SimplePacketBuilder(PacketType.MouseUp)
pb.writeUTF(address)
- pb.writeShort(x)
- pb.writeShort(y)
+ pb.writeFloat(x.toFloat)
+ pb.writeFloat(y.toFloat)
pb.writeByte(button.toByte)
pb.sendToServer()
diff --git a/src/main/scala/li/cil/oc/client/Sound.scala b/src/main/scala/li/cil/oc/client/Sound.scala
index d9a24fa5b..2d66d4e3c 100644
--- a/src/main/scala/li/cil/oc/client/Sound.scala
+++ b/src/main/scala/li/cil/oc/client/Sound.scala
@@ -8,6 +8,7 @@ import java.util.Timer
import java.util.TimerTask
import java.util.UUID
+import com.google.common.base.Charsets
import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import net.minecraft.client.Minecraft
@@ -19,11 +20,13 @@ import net.minecraftforge.client.event.sound.SoundLoadEvent
import net.minecraftforge.event.world.WorldEvent
import net.minecraftforge.fml.client.FMLClientHandler
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent
import net.minecraftforge.fml.relauncher.ReflectionHelper
import paulscode.sound.SoundSystem
import paulscode.sound.SoundSystemConfig
import scala.collection.mutable
+import scala.io.Source
object Sound {
private val sources = mutable.Map.empty[TileEntity, PseudoLoopingStream]
@@ -100,6 +103,33 @@ object Sound {
manager = event.manager
}
+ private var hasPreloaded = Settings.get.soundVolume <= 0
+
+ @SubscribeEvent
+ def onTick(e: ClientTickEvent) {
+ if (!hasPreloaded && soundSystem != null) {
+ hasPreloaded = true
+ new Thread(new Runnable() {
+ override def run(): Unit = {
+ val preloadConfigLocation = new ResourceLocation(Settings.resourceDomain, "sounds/preload.cfg")
+ val preloadConfigResource = Minecraft.getMinecraft.getResourceManager.getResource(preloadConfigLocation)
+ for (location <- Source.fromInputStream(preloadConfigResource.getInputStream)(Charsets.UTF_8).getLines()) {
+ val url = getClass.getClassLoader.getResource(location)
+ if (url != null) try {
+ val sourceName = "preload_" + location
+ soundSystem.newSource(false, sourceName, url, location, true, 0, 0, 0, SoundSystemConfig.ATTENUATION_NONE, 16)
+ soundSystem.activate(sourceName)
+ soundSystem.removeSource(sourceName)
+ } catch {
+ case _: Throwable => // Meh.
+ }
+ else OpenComputers.log.warn(s"Couldn't preload sound $location!")
+ }
+ }
+ })
+ }
+ }
+
@SubscribeEvent
def onWorldUnload(event: WorldEvent.Unload) {
commandQueue.synchronized(commandQueue.clear())
diff --git a/src/main/scala/li/cil/oc/client/gui/Adapter.scala b/src/main/scala/li/cil/oc/client/gui/Adapter.scala
index 5f46e94c3..88bf8d7b9 100644
--- a/src/main/scala/li/cil/oc/client/gui/Adapter.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Adapter.scala
@@ -6,8 +6,8 @@ import li.cil.oc.common.tileentity
import net.minecraft.entity.player.InventoryPlayer
class Adapter(playerInventory: InventoryPlayer, val adapter: tileentity.Adapter) extends DynamicGuiContainer(new container.Adapter(playerInventory, adapter)) {
- override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawGuiContainerForegroundLayer(mouseX, mouseY)
+ override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
+ super.drawSecondaryForegroundLayer(mouseX, mouseY)
fontRendererObj.drawString(
Localization.localizeImmediately(adapter.getName),
8, 6, 0x404040)
diff --git a/src/main/scala/li/cil/oc/client/gui/Assembler.scala b/src/main/scala/li/cil/oc/client/gui/Assembler.scala
index c0d860536..fbe0fa444 100644
--- a/src/main/scala/li/cil/oc/client/gui/Assembler.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Assembler.scala
@@ -60,7 +60,7 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse
add(buttonList, runButton)
}
- override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
+ override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) // Me lazy... prevents NEI render glitch.
if (!assemblerContainer.isAssembling) {
val message =
diff --git a/src/main/scala/li/cil/oc/client/gui/Case.scala b/src/main/scala/li/cil/oc/client/gui/Case.scala
index e8ae0b803..2c767b804 100644
--- a/src/main/scala/li/cil/oc/client/gui/Case.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Case.scala
@@ -33,9 +33,8 @@ class Case(playerInventory: InventoryPlayer, val computer: tileentity.Case) exte
add(buttonList, powerButton)
}
- override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawGuiContainerForegroundLayer(mouseX, mouseY)
- GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) // Me lazy... prevents NEI render glitch.
+ override protected def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
+ super.drawSecondaryForegroundLayer(mouseX, mouseY)
fontRendererObj.drawString(
Localization.localizeImmediately(computer.getName),
8, 6, 0x404040)
@@ -44,7 +43,6 @@ class Case(playerInventory: InventoryPlayer, val computer: tileentity.Case) exte
tooltip.add(if (computer.isRunning) Localization.Computer.TurnOff else Localization.Computer.TurnOn)
copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj)
}
- GL11.glPopAttrib()
}
override def drawSecondaryBackgroundLayer() {
diff --git a/src/main/scala/li/cil/oc/client/gui/Charger.scala b/src/main/scala/li/cil/oc/client/gui/Charger.scala
index f27af6a15..12344a4c2 100644
--- a/src/main/scala/li/cil/oc/client/gui/Charger.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Charger.scala
@@ -6,8 +6,8 @@ import li.cil.oc.common.tileentity
import net.minecraft.entity.player.InventoryPlayer
class Charger(playerInventory: InventoryPlayer, val charger: tileentity.Charger) extends DynamicGuiContainer(new container.Charger(playerInventory, charger)) {
- override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawGuiContainerForegroundLayer(mouseX, mouseY)
+ override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
+ super.drawSecondaryForegroundLayer(mouseX, mouseY)
fontRendererObj.drawString(
Localization.localizeImmediately(charger.getName),
8, 6, 0x404040)
diff --git a/src/main/scala/li/cil/oc/client/gui/Database.scala b/src/main/scala/li/cil/oc/client/gui/Database.scala
index 153e56437..31cf5bd1d 100644
--- a/src/main/scala/li/cil/oc/client/gui/Database.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Database.scala
@@ -11,7 +11,7 @@ import org.lwjgl.opengl.GL11
class Database(playerInventory: InventoryPlayer, val databaseInventory: DatabaseInventory) extends DynamicGuiContainer(new container.Database(playerInventory, databaseInventory)) {
ySize = 256
- override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) {}
+ override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) {}
override protected def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
GL11.glColor4f(1, 1, 1, 1)
diff --git a/src/main/scala/li/cil/oc/client/gui/Disassembler.scala b/src/main/scala/li/cil/oc/client/gui/Disassembler.scala
index 395642a40..041261a04 100644
--- a/src/main/scala/li/cil/oc/client/gui/Disassembler.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Disassembler.scala
@@ -13,7 +13,7 @@ class Disassembler(playerInventory: InventoryPlayer, val disassembler: tileentit
val progress = addWidget(new ProgressBar(18, 65))
- override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
+ override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
fontRendererObj.drawString(
Localization.localizeImmediately(disassembler.getName),
8, 6, 0x404040)
diff --git a/src/main/scala/li/cil/oc/client/gui/DiskDrive.scala b/src/main/scala/li/cil/oc/client/gui/DiskDrive.scala
index 21e6c0e34..1fbe026c5 100644
--- a/src/main/scala/li/cil/oc/client/gui/DiskDrive.scala
+++ b/src/main/scala/li/cil/oc/client/gui/DiskDrive.scala
@@ -6,8 +6,8 @@ import li.cil.oc.common.tileentity
import net.minecraft.entity.player.InventoryPlayer
class DiskDrive(playerInventory: InventoryPlayer, val drive: tileentity.DiskDrive) extends DynamicGuiContainer(new container.DiskDrive(playerInventory, drive)) {
- override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawGuiContainerForegroundLayer(mouseX, mouseY)
+ override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
+ super.drawSecondaryForegroundLayer(mouseX, mouseY)
fontRendererObj.drawString(
Localization.localizeImmediately(drive.getName),
8, 6, 0x404040)
diff --git a/src/main/scala/li/cil/oc/client/gui/Drone.scala b/src/main/scala/li/cil/oc/client/gui/Drone.scala
index 202e3bfd5..7c6444c3c 100644
--- a/src/main/scala/li/cil/oc/client/gui/Drone.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Drone.scala
@@ -87,7 +87,7 @@ class Drone(playerInventory: InventoryPlayer, val drone: entity.Drone) extends D
override protected def changeSize(w: Double, h: Double, recompile: Boolean) = 2.0
- override protected def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) {
+ override protected def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) {
drawBufferLayer()
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) // Me lazy... prevents NEI render glitch.
if (isPointInRegion(power.x, power.y, power.width, power.height, mouseX, mouseY)) {
diff --git a/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala b/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala
index 318560a02..f011cfde3 100644
--- a/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala
+++ b/src/main/scala/li/cil/oc/client/gui/DynamicGuiContainer.scala
@@ -1,18 +1,21 @@
package li.cil.oc.client.gui
+import codechicken.nei.ItemPanel
+import codechicken.nei.LayoutManager
import li.cil.oc.Localization
import li.cil.oc.client.Textures
import li.cil.oc.common
import li.cil.oc.common.container.ComponentSlot
import li.cil.oc.common.container.Player
+import li.cil.oc.integration.Mods
import li.cil.oc.integration.util.NEI
import li.cil.oc.util.RenderState
import net.minecraft.client.gui.Gui
-import net.minecraft.client.renderer.GlStateManager
import net.minecraft.client.renderer.Tessellator
import net.minecraft.inventory.Container
import net.minecraft.inventory.Slot
import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.Optional
import org.lwjgl.opengl.GL11
import scala.collection.convert.WrapAsScala._
@@ -22,12 +25,24 @@ abstract class DynamicGuiContainer(container: Container) extends CustomGuiContai
protected var hoveredStackNEI: Option[ItemStack] = None
- override protected def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) {
+ protected def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) {
fontRendererObj.drawString(
Localization.localizeImmediately("container.inventory"),
8, ySize - 96 + 2, 0x404040)
}
+ override protected def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) {
+ GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
+
+ drawSecondaryForegroundLayer(mouseX, mouseY)
+
+ for (slot <- 0 until inventorySlots.inventorySlots.size()) {
+ drawSlotHighlight(inventorySlots.inventorySlots.get(slot).asInstanceOf[Slot])
+ }
+
+ GL11.glPopAttrib()
+ }
+
protected def drawSecondaryBackgroundLayer() {}
override protected def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
@@ -41,9 +56,11 @@ abstract class DynamicGuiContainer(container: Container) extends CustomGuiContai
GL11.glPushMatrix()
GL11.glTranslatef(guiLeft, guiTop, 0)
+ GL11.glDisable(GL11.GL_DEPTH_TEST)
for (slot <- 0 until inventorySlots.inventorySlots.size()) {
drawSlotInventory(inventorySlots.inventorySlots.get(slot).asInstanceOf[Slot])
}
+ GL11.glEnable(GL11.GL_DEPTH_TEST)
GL11.glPopMatrix()
}
@@ -55,12 +72,11 @@ abstract class DynamicGuiContainer(container: Container) extends CustomGuiContai
super.drawScreen(mouseX, mouseY, dt)
- GL11.glPushMatrix()
- GL11.glTranslatef(guiLeft, guiTop, 0)
- for (slot <- 0 until inventorySlots.inventorySlots.size()) {
- drawSlotHighlight(inventorySlots.inventorySlots.get(slot).asInstanceOf[Slot])
+ if (Mods.NotEnoughItems.isAvailable) {
+ GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
+ drawNEIHighlights()
+ GL11.glPopAttrib()
}
- GL11.glPopMatrix()
}
protected def drawSlotInventory(slot: Slot) {
@@ -70,13 +86,13 @@ abstract class DynamicGuiContainer(container: Container) extends CustomGuiContai
drawDisabledSlot(component)
}
case _ =>
+ zLevel += 1
if (!isInPlayerInventory(slot)) {
drawSlotBackground(slot.xDisplayPosition - 1, slot.yDisplayPosition - 1)
}
if (!slot.getHasStack) {
slot match {
case component: ComponentSlot =>
- GL11.glDisable(GL11.GL_DEPTH_TEST)
if (component.tierIcon != null) {
mc.getTextureManager.bindTexture(component.tierIcon)
Gui.drawModalRectWithCustomSizedTexture(slot.xDisplayPosition, slot.yDisplayPosition, 0, 0, 16, 16, 16, 16)
@@ -85,38 +101,37 @@ abstract class DynamicGuiContainer(container: Container) extends CustomGuiContai
mc.getTextureManager.bindTexture(slot.getBackgroundLocation)
Gui.drawModalRectWithCustomSizedTexture(slot.xDisplayPosition, slot.yDisplayPosition, 0, 0, 16, 16, 16, 16)
}
- GL11.glEnable(GL11.GL_DEPTH_TEST)
case _ =>
}
+ zLevel -= 1
}
}
}
protected def drawSlotHighlight(slot: Slot) {
- slot match {
+ if (mc.thePlayer.inventory.getItemStack == null) slot match {
case component: ComponentSlot if component.slot == common.Slot.None || component.tier == common.Tier.None => // Ignore.
case _ =>
- if (mc.thePlayer.inventory.getItemStack == null) {
- val currentIsInPlayerInventory = isInPlayerInventory(slot)
- val drawHighlight = hoveredSlot match {
- case Some(hovered) =>
- val hoveredIsInPlayerInventory = isInPlayerInventory(hovered)
- (currentIsInPlayerInventory != hoveredIsInPlayerInventory) &&
- ((currentIsInPlayerInventory && slot.getHasStack && isSelectiveSlot(hovered) && hovered.isItemValid(slot.getStack)) ||
- (hoveredIsInPlayerInventory && hovered.getHasStack && isSelectiveSlot(slot) && slot.isItemValid(hovered.getStack)))
- case _ => hoveredStackNEI match {
- case Some(stack) => !currentIsInPlayerInventory && isSelectiveSlot(slot) && slot.isItemValid(stack)
- case _ => false
- }
- }
- if (drawHighlight) {
- GlStateManager.disableLighting()
- GL11.glDisable(GL11.GL_DEPTH_TEST)
- drawGradientRect(slot.xDisplayPosition, slot.yDisplayPosition, slot.xDisplayPosition + 16, slot.yDisplayPosition + 16, 0x80FFFFFF, 0x80FFFFFF)
- GlStateManager.enableLighting()
- GL11.glEnable(GL11.GL_DEPTH_TEST)
+ val currentIsInPlayerInventory = isInPlayerInventory(slot)
+ val drawHighlight = hoveredSlot match {
+ case Some(hovered) =>
+ val hoveredIsInPlayerInventory = isInPlayerInventory(hovered)
+ (currentIsInPlayerInventory != hoveredIsInPlayerInventory) &&
+ ((currentIsInPlayerInventory && slot.getHasStack && isSelectiveSlot(hovered) && hovered.isItemValid(slot.getStack)) ||
+ (hoveredIsInPlayerInventory && hovered.getHasStack && isSelectiveSlot(slot) && slot.isItemValid(hovered.getStack)))
+ case _ => hoveredStackNEI match {
+ case Some(stack) => !currentIsInPlayerInventory && isSelectiveSlot(slot) && slot.isItemValid(stack)
+ case _ => false
}
}
+ if (drawHighlight) {
+ zLevel += 100
+ drawGradientRect(
+ slot.xDisplayPosition, slot.yDisplayPosition,
+ slot.xDisplayPosition + 16, slot.yDisplayPosition + 16,
+ 0x80FFFFFF, 0x80FFFFFF)
+ zLevel -= 100
+ }
}
}
@@ -128,11 +143,7 @@ abstract class DynamicGuiContainer(container: Container) extends CustomGuiContai
protected def drawDisabledSlot(slot: ComponentSlot) {
GL11.glColor4f(1, 1, 1, 1)
mc.getTextureManager.bindTexture(slot.tierIcon)
- GL11.glDisable(GL11.GL_DEPTH_TEST)
- GL11.glDisable(GL11.GL_LIGHTING)
Gui.drawModalRectWithCustomSizedTexture(slot.xDisplayPosition, slot.yDisplayPosition, 0, 0, 16, 16, 16, 16)
- GL11.glEnable(GL11.GL_LIGHTING)
- GL11.glEnable(GL11.GL_DEPTH_TEST)
}
protected def drawSlotBackground(x: Int, y: Int) {
@@ -152,4 +163,26 @@ abstract class DynamicGuiContainer(container: Container) extends CustomGuiContai
case player: Player => slot.inventory == player.playerInventory
case _ => false
}
+
+ @Optional.Method(modid = Mods.IDs.NotEnoughItems)
+ private def drawNEIHighlights(): Unit = {
+ val panel = LayoutManager.itemPanel
+ if (panel == null) return
+ zLevel += 350
+ for (index <- 0 until ItemPanel.items.size()) {
+ val rect = panel.getSlotRect(index)
+ val slot = panel.getSlotMouseOver(rect.x, rect.y)
+ if (slot != null) hoveredSlot match {
+ case Some(hovered) =>
+ if (!isInPlayerInventory(hovered) && isSelectiveSlot(hovered) && hovered.isItemValid(slot.item)) {
+ drawGradientRect(
+ rect.x1 + 1, rect.y1 + 1,
+ rect.x2, rect.y2,
+ 0x40FFFFFF, 0x40FFFFFF)
+ }
+ case _ =>
+ }
+ }
+ zLevel -= 350
+ }
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Raid.scala b/src/main/scala/li/cil/oc/client/gui/Raid.scala
index 496bb6b0f..8ff5d4fbe 100644
--- a/src/main/scala/li/cil/oc/client/gui/Raid.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Raid.scala
@@ -8,8 +8,8 @@ import net.minecraft.entity.player.InventoryPlayer
import org.lwjgl.opengl.GL11
class Raid(playerInventory: InventoryPlayer, val raid: tileentity.Raid) extends DynamicGuiContainer(new container.Raid(playerInventory, raid)) {
- override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawGuiContainerForegroundLayer(mouseX, mouseY)
+ override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
+ super.drawSecondaryForegroundLayer(mouseX, mouseY)
fontRendererObj.drawString(
Localization.localizeImmediately(raid.getName),
8, 6, 0x404040)
diff --git a/src/main/scala/li/cil/oc/client/gui/Robot.scala b/src/main/scala/li/cil/oc/client/gui/Robot.scala
index 30e6b227e..9605b2fe8 100644
--- a/src/main/scala/li/cil/oc/client/gui/Robot.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Robot.scala
@@ -128,7 +128,7 @@ class Robot(playerInventory: InventoryPlayer, val robot: tileentity.Robot) exten
}
}
- override protected def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) {
+ override protected def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) {
drawBufferLayer()
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) // Me lazy... prevents NEI render glitch.
if (isPointInRegion(power.x, power.y, power.width, power.height, mouseX, mouseY)) {
diff --git a/src/main/scala/li/cil/oc/client/gui/Screen.scala b/src/main/scala/li/cil/oc/client/gui/Screen.scala
index 984e57fe5..2c6e80fe2 100644
--- a/src/main/scala/li/cil/oc/client/gui/Screen.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Screen.scala
@@ -20,18 +20,18 @@ class Screen(val buffer: api.component.TextBuffer, val hasMouse: Boolean, val ha
private var x, y = 0
- private var mx, my = 0
+ private var mx, my = -1
override def handleMouseInput() {
super.handleMouseInput()
if (hasMouse && Mouse.hasWheel && Mouse.getEventDWheel != 0) {
val mouseX = Mouse.getEventX * width / mc.displayWidth
val mouseY = height - Mouse.getEventY * height / mc.displayHeight - 1
- val bx = (mouseX - x - bufferMargin) / TextBufferRenderCache.renderer.charRenderWidth + 1
- val by = (mouseY - y - bufferMargin) / TextBufferRenderCache.renderer.charRenderHeight + 1
+ val bx = (mouseX - x - bufferMargin) / TextBufferRenderCache.renderer.charRenderWidth.toDouble
+ val by = (mouseY - y - bufferMargin) / TextBufferRenderCache.renderer.charRenderHeight.toDouble
val bw = buffer.getWidth
val bh = buffer.getHeight
- if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
+ if (bx >= 0 && by >= 0 && bx < bw && by < bh) {
val scroll = math.signum(Mouse.getEventDWheel)
buffer.mouseScroll(bx, by, scroll, null)
}
@@ -60,35 +60,35 @@ class Screen(val buffer: api.component.TextBuffer, val hasMouse: Boolean, val ha
super.mouseReleased(mouseX, mouseY, button)
if (hasMouse && button >= 0) {
if (didDrag) {
- val bx = ((mouseX - x - bufferMargin) / scale / TextBufferRenderCache.renderer.charRenderWidth).toInt + 1
- val by = ((mouseY - y - bufferMargin) / scale / TextBufferRenderCache.renderer.charRenderHeight).toInt + 1
+ val bx = (mouseX - x - bufferMargin) / scale / TextBufferRenderCache.renderer.charRenderWidth
+ val by = (mouseY - y - bufferMargin) / scale / TextBufferRenderCache.renderer.charRenderHeight
val bw = buffer.getWidth
val bh = buffer.getHeight
- if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
+ if (bx >= 0 && by >= 0 && bx < bw && by < bh) {
buffer.mouseUp(bx, by, button, null)
}
else {
- buffer.mouseUp(-1, -1, button, null)
+ buffer.mouseUp(-1.0, -1.0, button, null)
}
}
didDrag = false
- mx = 0
- my = 0
+ mx = -1
+ my = -1
}
}
private def clickOrDrag(mouseX: Int, mouseY: Int, button: Int) {
- val bx = ((mouseX - x - bufferMargin) / scale / TextBufferRenderCache.renderer.charRenderWidth).toInt + 1
- val by = ((mouseY - y - bufferMargin) / scale / TextBufferRenderCache.renderer.charRenderHeight).toInt + 1
+ val bx = (mouseX - x - bufferMargin) / scale / TextBufferRenderCache.renderer.charRenderWidth
+ val by = (mouseY - y - bufferMargin) / scale / TextBufferRenderCache.renderer.charRenderHeight
val bw = buffer.getWidth
val bh = buffer.getHeight
- if (bx > 0 && by > 0 && bx <= bw && by <= bh) {
- if (bx != mx || by != my) {
- if (mx > 0 && my > 0) buffer.mouseDrag(bx, by, button, null)
+ if (bx >= 0 && by >= 0 && bx < bw && by < bh) {
+ if (bx.toInt != mx || by.toInt != my) {
+ if (mx >= 0 && my >= 0) buffer.mouseDrag(bx, by, button, null)
else buffer.mouseDown(bx, by, button, null)
- didDrag = mx > 0 && my > 0
- mx = bx
- my = by
+ didDrag = mx >= 0 && my >= 0
+ mx = bx.toInt
+ my = by.toInt
}
}
}
diff --git a/src/main/scala/li/cil/oc/client/gui/Server.scala b/src/main/scala/li/cil/oc/client/gui/Server.scala
index d455e2b2d..a8f4fee93 100644
--- a/src/main/scala/li/cil/oc/client/gui/Server.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Server.scala
@@ -9,8 +9,8 @@ import net.minecraft.inventory.Slot
import org.lwjgl.opengl.GL11
class Server(playerInventory: InventoryPlayer, serverInventory: ServerInventory) extends DynamicGuiContainer(new container.Server(playerInventory, serverInventory)) {
- override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) {
- super.drawGuiContainerForegroundLayer(mouseX, mouseY)
+ override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) {
+ super.drawSecondaryForegroundLayer(mouseX, mouseY)
fontRendererObj.drawString(
Localization.localizeImmediately(serverInventory.getName),
8, 6, 0x404040)
diff --git a/src/main/scala/li/cil/oc/client/gui/ServerRack.scala b/src/main/scala/li/cil/oc/client/gui/ServerRack.scala
index 246b521e8..feff32150 100644
--- a/src/main/scala/li/cil/oc/client/gui/ServerRack.scala
+++ b/src/main/scala/li/cil/oc/client/gui/ServerRack.scala
@@ -73,8 +73,8 @@ class ServerRack(playerInventory: InventoryPlayer, val rack: tileentity.ServerRa
add(buttonList, switchButton)
}
- override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawGuiContainerForegroundLayer(mouseX, mouseY)
+ override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
+ super.drawSecondaryForegroundLayer(mouseX, mouseY)
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) // Prevents NEI render glitch.
fontRendererObj.drawString(
diff --git a/src/main/scala/li/cil/oc/client/gui/Switch.scala b/src/main/scala/li/cil/oc/client/gui/Switch.scala
index ac3938225..e56d20e63 100644
--- a/src/main/scala/li/cil/oc/client/gui/Switch.scala
+++ b/src/main/scala/li/cil/oc/client/gui/Switch.scala
@@ -11,8 +11,8 @@ class Switch(playerInventory: InventoryPlayer, val switch: tileentity.Switch) ex
private val switchContainer = inventorySlots.asInstanceOf[container.Switch]
private val format = new DecimalFormat("#.##hz")
- override def drawGuiContainerForegroundLayer(mouseX: Int, mouseY: Int) = {
- super.drawGuiContainerForegroundLayer(mouseX, mouseY)
+ override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
+ super.drawSecondaryForegroundLayer(mouseX, mouseY)
fontRendererObj.drawString(
Localization.localizeImmediately(switch.getName),
8, 6, 0x404040)
diff --git a/src/main/scala/li/cil/oc/common/EventHandler.scala b/src/main/scala/li/cil/oc/common/EventHandler.scala
index 3fe8e2db5..e8a88959e 100644
--- a/src/main/scala/li/cil/oc/common/EventHandler.scala
+++ b/src/main/scala/li/cil/oc/common/EventHandler.scala
@@ -7,6 +7,7 @@ import li.cil.oc.api.Network
import li.cil.oc.api.detail.ItemInfo
import li.cil.oc.client.renderer.PetRenderer
import li.cil.oc.client.{PacketSender => ClientPacketSender}
+import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.integration.Mods
import li.cil.oc.integration.util
import li.cil.oc.server.{PacketSender => ServerPacketSender}
@@ -45,7 +46,7 @@ object EventHandler {
def scheduleWirelessRedstone(rs: server.component.RedstoneWireless) {
if (SideTracker.isServer) pending.synchronized {
- pending += (() => if (!rs.owner.isInvalid) {
+ pending += (() => if (rs.node.network != null) {
util.WirelessRedstone.addReceiver(rs)
util.WirelessRedstone.updateOutput(rs)
})
@@ -90,11 +91,18 @@ object EventHandler {
@SubscribeEvent
def clientLoggedIn(e: ClientConnectedToServerEvent) {
- PetRenderer.hidden.clear()
- if (Settings.get.hideOwnPet) {
- PetRenderer.hidden += Minecraft.getMinecraft.thePlayer.getName
+ try {
+ PetRenderer.hidden.clear()
+ if (Settings.get.hideOwnPet) {
+ PetRenderer.hidden += Minecraft.getMinecraft.thePlayer.getName
+ }
+ ClientPacketSender.sendPetVisibility()
+ }
+ catch {
+ case _: Throwable =>
+ // Reportedly, things can derp if this is called at inopportune moments,
+ // such as the server shutting down.
}
- ClientPacketSender.sendPetVisibility()
}
lazy val drone = api.Items.get("drone")
@@ -116,12 +124,12 @@ object EventHandler {
didRecraft = recraft(e, mcu, stack => {
// Restore EEPROM currently used in microcontroller.
- new ItemUtils.MicrocontrollerData(stack).components.find(api.Items.get(_) == eeprom)
+ new MicrocontrollerData(stack).components.find(api.Items.get(_) == eeprom)
}) || didRecraft
didRecraft = recraft(e, drone, stack => {
// Restore EEPROM currently used in drone.
- new ItemUtils.MicrocontrollerData(stack).components.find(api.Items.get(_) == eeprom)
+ new MicrocontrollerData(stack).components.find(api.Items.get(_) == eeprom)
}) || didRecraft
// Presents?
diff --git a/src/main/scala/li/cil/oc/common/PacketType.scala b/src/main/scala/li/cil/oc/common/PacketType.scala
index cb9aa5d2d..6cd957cc2 100644
--- a/src/main/scala/li/cil/oc/common/PacketType.scala
+++ b/src/main/scala/li/cil/oc/common/PacketType.scala
@@ -40,6 +40,9 @@ object PacketType extends Enumeration {
TextBufferMultiResolutionChange,
TextBufferMultiMaxResolutionChange,
TextBufferMultiSet,
+ TextBufferMultiRawSetText,
+ TextBufferMultiRawSetBackground,
+ TextBufferMultiRawSetForeground,
TextBufferPowerChange,
ScreenTouchMode,
ServerPresence,
diff --git a/src/main/scala/li/cil/oc/common/block/Adapter.scala b/src/main/scala/li/cil/oc/common/block/Adapter.scala
index 8f0562934..8a0f2e905 100644
--- a/src/main/scala/li/cil/oc/common/block/Adapter.scala
+++ b/src/main/scala/li/cil/oc/common/block/Adapter.scala
@@ -1,33 +1,23 @@
package li.cil.oc.common.block
-import li.cil.oc.OpenComputers
import li.cil.oc.common.GuiType
import li.cil.oc.common.tileentity
import net.minecraft.block.Block
import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.player.EntityPlayer
import net.minecraft.util.BlockPos
import net.minecraft.util.EnumFacing
import net.minecraft.world.IBlockAccess
import net.minecraft.world.World
-class Adapter extends SimpleBlock {
+class Adapter extends SimpleBlock with traits.GUI {
+ override def guiType = GuiType.Adapter
+
override def hasTileEntity(state: IBlockState) = true
override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Adapter()
// ----------------------------------------------------------------------- //
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
- if (!player.isSneaking) {
- if (!world.isRemote) {
- player.openGui(OpenComputers, GuiType.Adapter.id, world, pos.getX, pos.getY, pos.getZ)
- }
- true
- }
- else false
- }
-
override def onNeighborBlockChange(world: World, pos: BlockPos, state: IBlockState, neighborBlock: Block) =
world.getTileEntity(pos) match {
case adapter: tileentity.Adapter => adapter.neighborChanged()
diff --git a/src/main/scala/li/cil/oc/common/block/Assembler.scala b/src/main/scala/li/cil/oc/common/block/Assembler.scala
index 9ab930bc4..cbad9e7cb 100644
--- a/src/main/scala/li/cil/oc/common/block/Assembler.scala
+++ b/src/main/scala/li/cil/oc/common/block/Assembler.scala
@@ -1,17 +1,15 @@
package li.cil.oc.common.block
-import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.common.GuiType
import li.cil.oc.common.tileentity
import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.player.EntityPlayer
import net.minecraft.util.BlockPos
import net.minecraft.util.EnumFacing
import net.minecraft.world.IBlockAccess
import net.minecraft.world.World
-class Assembler extends SimpleBlock with traits.PowerAcceptor with traits.StateAware {
+class Assembler extends SimpleBlock with traits.PowerAcceptor with traits.StateAware with traits.GUI {
setLightLevel(0.34f)
override def isOpaqueCube = false
@@ -20,23 +18,15 @@ class Assembler extends SimpleBlock with traits.PowerAcceptor with traits.StateA
override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN || side == EnumFacing.UP
+ override def isSideSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN || side == EnumFacing.UP
+
// ----------------------------------------------------------------------- //
override def energyThroughput = Settings.get.assemblerRate
+ override def guiType = GuiType.Assembler
+
override def hasTileEntity(state: IBlockState) = true
override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Assembler()
-
- // ----------------------------------------------------------------------- //
-
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
- if (!player.isSneaking) {
- if (!world.isRemote) {
- player.openGui(OpenComputers, GuiType.Assembler.id, world, pos.getX, pos.getY, pos.getZ)
- }
- true
- }
- else false
- }
}
diff --git a/src/main/scala/li/cil/oc/common/block/Cable.scala b/src/main/scala/li/cil/oc/common/block/Cable.scala
index a63508731..bf67d839c 100644
--- a/src/main/scala/li/cil/oc/common/block/Cable.scala
+++ b/src/main/scala/li/cil/oc/common/block/Cable.scala
@@ -8,7 +8,9 @@ import codechicken.multipart.TFacePart
import codechicken.multipart.TileMultipart
import li.cil.oc.integration.fmp.CablePart
*/
+
import li.cil.oc.api.network.Environment
+import li.cil.oc.api.network.SidedComponent
import li.cil.oc.api.network.SidedEnvironment
import li.cil.oc.common.tileentity
import li.cil.oc.integration.Mods
@@ -65,6 +67,8 @@ class Cable extends SimpleBlock with traits.Extended {
override def shouldSideBeRendered(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = true
+ override def isSideSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
+
// ----------------------------------------------------------------------- //
override def hasTileEntity(state: IBlockState) = true
@@ -142,12 +146,15 @@ object Cable {
case host: SidedEnvironment =>
if (host.getWorld.isRemote) host.canConnect(side)
else host.sidedNode(side) != null
+ case host: Environment with SidedComponent =>
+ host.canConnectNode(side)
case host: Environment => true
case host if Mods.ForgeMultipart.isAvailable => hasMultiPartNode(tileEntity)
case _ => false
}
private def hasMultiPartNode(tileEntity: TileEntity) = false
+
/* TODO FMP
tileEntity match {
case host: TileMultipart => host.partList.exists(_.isInstanceOf[CablePart])
@@ -164,6 +171,7 @@ object Cable {
}
private def cableColorFMP(tileEntity: TileEntity) = EnumDyeColor.SILVER
+
/* TODO FMP
tileEntity match {
case host: TileMultipart => (host.partList collect {
@@ -179,6 +187,7 @@ object Cable {
}
private def canConnectFromSideFMP(tileEntity: TileEntity, side: EnumFacing) = true
+
/* TODO FMP
tileEntity match {
case host: TileMultipart =>
diff --git a/src/main/scala/li/cil/oc/common/block/Capacitor.scala b/src/main/scala/li/cil/oc/common/block/Capacitor.scala
index 6585e85c2..a2a701035 100644
--- a/src/main/scala/li/cil/oc/common/block/Capacitor.scala
+++ b/src/main/scala/li/cil/oc/common/block/Capacitor.scala
@@ -1,5 +1,7 @@
package li.cil.oc.common.block
+import java.util.Random
+
import li.cil.oc.common.tileentity
import net.minecraft.block.Block
import net.minecraft.block.state.IBlockState
@@ -8,6 +10,7 @@ import net.minecraft.world.World
class Capacitor extends SimpleBlock {
setLightLevel(0.34f)
+ setTickRandomly(true)
// ----------------------------------------------------------------------- //
@@ -17,6 +20,21 @@ class Capacitor extends SimpleBlock {
// ----------------------------------------------------------------------- //
+ override def hasComparatorInputOverride = true
+
+ override def getComparatorInputOverride(world: World, pos: BlockPos): Int =
+ world.getTileEntity(pos) match {
+ case capacitor: tileentity.Capacitor if !world.isRemote =>
+ math.round(15 * capacitor.node.localBuffer / capacitor.node.localBufferSize).toInt
+ case _ => 0
+ }
+
+ override def updateTick(world: World, pos: BlockPos, state: IBlockState, rand: Random): Unit = {
+ world.notifyNeighborsOfStateChange(pos, this)
+ }
+
+ override def tickRate(world: World) = 1
+
override def onNeighborBlockChange(world: World, pos: BlockPos, state: IBlockState, neighborBlock: Block) =
world.getTileEntity(pos) match {
case capacitor: tileentity.Capacitor => capacitor.recomputeCapacity()
diff --git a/src/main/scala/li/cil/oc/common/block/Case.scala b/src/main/scala/li/cil/oc/common/block/Case.scala
index 63a18bdcb..4042703aa 100644
--- a/src/main/scala/li/cil/oc/common/block/Case.scala
+++ b/src/main/scala/li/cil/oc/common/block/Case.scala
@@ -2,11 +2,9 @@ package li.cil.oc.common.block
import java.util
-import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.common.GuiType
import li.cil.oc.common.tileentity
-import li.cil.oc.integration.util.Wrench
import li.cil.oc.util.Color
import li.cil.oc.util.Rarity
import li.cil.oc.util.Tooltip
@@ -28,7 +26,7 @@ object Case {
final val Running = PropertyBool.create("running")
}
-class Case(val tier: Int) extends RedstoneAware with traits.PowerAcceptor with traits.Rotatable with traits.StateAware {
+class Case(val tier: Int) extends RedstoneAware with traits.PowerAcceptor with traits.Rotatable with traits.StateAware with traits.GUI {
def getRunning(state: IBlockState) =
if (state.getBlock == this)
state.getValue(Case.Running).asInstanceOf[Boolean]
@@ -69,27 +67,21 @@ class Case(val tier: Int) extends RedstoneAware with traits.PowerAcceptor with t
override def energyThroughput = Settings.get.caseRate(tier)
+ override def guiType = GuiType.Case
+
override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Case(tier)
// ----------------------------------------------------------------------- //
override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
- if (!player.isSneaking && !Wrench.holdsApplicableWrench(player, pos)) {
- if (!world.isRemote) {
- player.openGui(OpenComputers, GuiType.Case.id, world, pos.getX, pos.getY, pos.getZ)
+ if (player.isSneaking) {
+ if (!world.isRemote) world.getTileEntity(pos) match {
+ case computer: tileentity.Case if !computer.machine.isRunning => computer.machine.start()
+ case _ =>
}
true
}
- else if (player.getCurrentEquippedItem == null) {
- if (!world.isRemote) {
- world.getTileEntity(pos) match {
- case computer: tileentity.Case if !computer.machine.isRunning => computer.machine.start()
- case _ =>
- }
- }
- true
- }
- else false
+ else super.localOnBlockActivated(world, pos, player, side, hitX, hitY, hitZ)
}
override def removedByPlayer(world: World, pos: BlockPos, player: EntityPlayer, willHarvest: Boolean) =
diff --git a/src/main/scala/li/cil/oc/common/block/Charger.scala b/src/main/scala/li/cil/oc/common/block/Charger.scala
index 6789dfd1c..1b21d92f1 100644
--- a/src/main/scala/li/cil/oc/common/block/Charger.scala
+++ b/src/main/scala/li/cil/oc/common/block/Charger.scala
@@ -1,6 +1,5 @@
package li.cil.oc.common.block
-import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.common.GuiType
import li.cil.oc.common.tileentity
@@ -14,11 +13,13 @@ import net.minecraft.util.EnumFacing
import net.minecraft.world.IBlockAccess
import net.minecraft.world.World
-class Charger extends RedstoneAware with traits.PowerAcceptor with traits.Rotatable with traits.StateAware {
+class Charger extends RedstoneAware with traits.PowerAcceptor with traits.Rotatable with traits.StateAware with traits.GUI {
override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state)
override def energyThroughput = Settings.get.chargerRate
+ override def guiType = GuiType.Charger
+
override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Charger()
// ----------------------------------------------------------------------- //
@@ -28,26 +29,18 @@ class Charger extends RedstoneAware with traits.PowerAcceptor with traits.Rotata
// ----------------------------------------------------------------------- //
override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) =
- world.getTileEntity(pos) match {
+ if (Wrench.holdsApplicableWrench(player, pos)) world.getTileEntity(pos) match {
case charger: tileentity.Charger =>
- if (Wrench.holdsApplicableWrench(player, pos)) {
- if (!world.isRemote) {
- charger.invertSignal = !charger.invertSignal
- charger.chargeSpeed = 1.0 - charger.chargeSpeed
- PacketSender.sendChargerState(charger)
- Wrench.wrenchUsed(player, pos)
- }
- true
+ if (!world.isRemote) {
+ charger.invertSignal = !charger.invertSignal
+ charger.chargeSpeed = 1.0 - charger.chargeSpeed
+ PacketSender.sendChargerState(charger)
+ Wrench.wrenchUsed(player, pos)
}
- else if (!player.isSneaking) {
- if (!world.isRemote) {
- player.openGui(OpenComputers, GuiType.Charger.id, world, pos.getX, pos.getY, pos.getZ)
- }
- true
- }
- else false
- case _ => super.localOnBlockActivated(world, pos, player, side, hitX, hitY, hitZ)
+ true
+ case _ => false
}
+ else super.localOnBlockActivated(world, pos, player, side, hitX, hitY, hitZ)
override def onNeighborBlockChange(world: World, pos: BlockPos, state: IBlockState, neighborBlock: Block) {
world.getTileEntity(pos) match {
diff --git a/src/main/scala/li/cil/oc/common/block/Disassembler.scala b/src/main/scala/li/cil/oc/common/block/Disassembler.scala
index fd4b5ad4c..8e25576da 100644
--- a/src/main/scala/li/cil/oc/common/block/Disassembler.scala
+++ b/src/main/scala/li/cil/oc/common/block/Disassembler.scala
@@ -1,6 +1,5 @@
package li.cil.oc.common.block
-import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.common.GuiType
import li.cil.oc.common.tileentity
@@ -8,11 +7,9 @@ import li.cil.oc.util.Tooltip
import net.minecraft.block.state.IBlockState
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
-import net.minecraft.util.BlockPos
-import net.minecraft.util.EnumFacing
import net.minecraft.world.World
-class Disassembler extends SimpleBlock with traits.PowerAcceptor with traits.StateAware {
+class Disassembler extends SimpleBlock with traits.PowerAcceptor with traits.StateAware with traits.GUI {
override protected def tooltipBody(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: java.util.List[String], advanced: Boolean) {
tooltip.addAll(Tooltip.get(getClass.getSimpleName, (Settings.get.disassemblerBreakChance * 100).toInt.toString))
}
@@ -21,19 +18,9 @@ class Disassembler extends SimpleBlock with traits.PowerAcceptor with traits.Sta
override def energyThroughput = Settings.get.disassemblerRate
+ override def guiType = GuiType.Disassembler
+
override def hasTileEntity(state: IBlockState) = true
override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Disassembler()
-
- // ----------------------------------------------------------------------- //
-
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
- if (!player.isSneaking) {
- if (!world.isRemote) {
- player.openGui(OpenComputers, GuiType.Disassembler.id, world, pos.getX, pos.getY, pos.getZ)
- }
- true
- }
- else false
- }
}
diff --git a/src/main/scala/li/cil/oc/common/block/DiskDrive.scala b/src/main/scala/li/cil/oc/common/block/DiskDrive.scala
index 8ddc4d0d9..ff950df55 100644
--- a/src/main/scala/li/cil/oc/common/block/DiskDrive.scala
+++ b/src/main/scala/li/cil/oc/common/block/DiskDrive.scala
@@ -1,6 +1,5 @@
package li.cil.oc.common.block
-import li.cil.oc.OpenComputers
import li.cil.oc.common.GuiType
import li.cil.oc.common.tileentity
import li.cil.oc.integration.Mods
@@ -12,7 +11,7 @@ import net.minecraft.util.BlockPos
import net.minecraft.util.EnumFacing
import net.minecraft.world.World
-class DiskDrive extends SimpleBlock with traits.Rotatable {
+class DiskDrive extends SimpleBlock with traits.Rotatable with traits.GUI {
override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state)
override protected def tooltipTail(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: java.util.List[String], advanced: Boolean) {
@@ -24,6 +23,8 @@ class DiskDrive extends SimpleBlock with traits.Rotatable {
// ----------------------------------------------------------------------- //
+ override def guiType = GuiType.DiskDrive
+
override def hasTileEntity(state: IBlockState) = true
override def createNewTileEntity(world: World, metadata: Int) = new tileentity.DiskDrive()
@@ -41,30 +42,23 @@ class DiskDrive extends SimpleBlock with traits.Rotatable {
// ----------------------------------------------------------------------- //
override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
- world.getTileEntity(pos) match {
+ // Behavior: sneaking -> Insert[+Eject], not sneaking -> GUI.
+ if (player.isSneaking) world.getTileEntity(pos) match {
case drive: tileentity.DiskDrive =>
- // Behavior: sneaking -> Insert[+Eject], not sneaking -> GUI.
- if (!player.isSneaking) {
+ val isDiskInDrive = drive.getStackInSlot(0) != null
+ val isHoldingDisk = drive.isItemValidForSlot(0, player.getCurrentEquippedItem)
+ if (isDiskInDrive) {
if (!world.isRemote) {
- player.openGui(OpenComputers, GuiType.DiskDrive.id, world, pos.getX, pos.getY, pos.getZ)
+ drive.dropSlot(0, 1, Option(drive.facing))
}
- true
}
- else {
- val isDiskInDrive = drive.getStackInSlot(0) != null
- val isHoldingDisk = drive.isItemValidForSlot(0, player.getCurrentEquippedItem)
- if (isDiskInDrive) {
- if (!world.isRemote) {
- drive.dropSlot(0, 1, Option(drive.facing))
- }
- }
- if (isHoldingDisk) {
- // Insert the disk.
- drive.setInventorySlotContents(0, player.inventory.decrStackSize(player.inventory.currentItem, 1))
- }
- isDiskInDrive || isHoldingDisk
+ if (isHoldingDisk) {
+ // Insert the disk.
+ drive.setInventorySlotContents(0, player.inventory.decrStackSize(player.inventory.currentItem, 1))
}
+ isDiskInDrive || isHoldingDisk
case _ => false
}
+ else super.localOnBlockActivated(world, pos, player, side, hitX, hitY, hitZ)
}
}
diff --git a/src/main/scala/li/cil/oc/common/block/Hologram.scala b/src/main/scala/li/cil/oc/common/block/Hologram.scala
index d1e71d7f2..c7f10fa4b 100644
--- a/src/main/scala/li/cil/oc/common/block/Hologram.scala
+++ b/src/main/scala/li/cil/oc/common/block/Hologram.scala
@@ -32,6 +32,8 @@ class Hologram(val tier: Int) extends SimpleBlock {
super.shouldSideBeRendered(world, pos, side) || side == EnumFacing.UP
}
+ override def isSideSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.DOWN
+
// ----------------------------------------------------------------------- //
override def rarity(stack: ItemStack) = Rarity.byTier(tier)
diff --git a/src/main/scala/li/cil/oc/common/block/Item.scala b/src/main/scala/li/cil/oc/common/block/Item.scala
index 081ef8183..b267bc333 100644
--- a/src/main/scala/li/cil/oc/common/block/Item.scala
+++ b/src/main/scala/li/cil/oc/common/block/Item.scala
@@ -5,6 +5,7 @@ import java.util
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.client.KeyBindings
+import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.tileentity
import li.cil.oc.util.Color
import li.cil.oc.util.ItemCosts
@@ -83,7 +84,7 @@ class Item(value: Block) extends ItemBlock(value) {
// manually before it's placed to ensure different component addresses
// in the different robots, to avoid interference of screens e.g.
val needsCopying = player.capabilities.isCreativeMode && api.Items.get(stack) == api.Items.get("robot")
- val stackToUse = if (needsCopying) new ItemUtils.RobotData(stack).copyItemStack() else stack
+ val stackToUse = if (needsCopying) new RobotData(stack).copyItemStack() else stack
if (super.placeBlockAt(stackToUse, player, world, pos, side, hitX, hitY, hitZ, newState)) {
// If it's a rotatable block try to make it face the player.
world.getTileEntity(pos) match {
diff --git a/src/main/scala/li/cil/oc/common/block/Microcontroller.scala b/src/main/scala/li/cil/oc/common/block/Microcontroller.scala
index 4e4c6a3e4..b53f3abe5 100644
--- a/src/main/scala/li/cil/oc/common/block/Microcontroller.scala
+++ b/src/main/scala/li/cil/oc/common/block/Microcontroller.scala
@@ -5,13 +5,12 @@ import java.util
import li.cil.oc.Settings
import li.cil.oc.client.KeyBindings
import li.cil.oc.common.Tier
+import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.NEI
import li.cil.oc.integration.util.Wrench
-import li.cil.oc.util.BlockPosition
-import li.cil.oc.util.InventoryUtils
-import li.cil.oc.util.ItemUtils
import li.cil.oc.util.Rarity
+import net.minecraft.block.Block
import net.minecraft.block.state.IBlockState
import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.player.EntityPlayer
@@ -19,10 +18,11 @@ import net.minecraft.item.ItemStack
import net.minecraft.util.BlockPos
import net.minecraft.util.EnumFacing
import net.minecraft.util.MovingObjectPosition
-import net.minecraft.world.IBlockAccess
import net.minecraft.world.World
-class Microcontroller extends RedstoneAware with traits.PowerAcceptor with traits.Rotatable with traits.StateAware {
+import scala.reflect.ClassTag
+
+class Microcontroller(protected implicit val tileTag: ClassTag[tileentity.Microcontroller]) extends RedstoneAware with traits.PowerAcceptor with traits.Rotatable with traits.StateAware with traits.CustomDrops[tileentity.Microcontroller] {
setCreativeTab(null)
NEI.hide(this)
@@ -36,17 +36,12 @@ class Microcontroller extends RedstoneAware with traits.PowerAcceptor with trait
case _ => null
}
- // Custom drop logic for NBT tagged item stack.
- override def getDrops(world: IBlockAccess, pos: BlockPos, state: IBlockState, fortune: Int) = new java.util.ArrayList[ItemStack]()
-
- override def onBlockHarvested(worldIn: World, pos: BlockPos, state: IBlockState, player: EntityPlayer) {}
-
// ----------------------------------------------------------------------- //
override protected def tooltipTail(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
super.tooltipTail(metadata, stack, player, tooltip, advanced)
if (KeyBindings.showExtendedTooltips) {
- val info = new ItemUtils.MicrocontrollerData(stack)
+ val info = new MicrocontrollerData(stack)
for (component <- info.components) {
tooltip.add("- " + component.getDisplayName)
}
@@ -54,7 +49,7 @@ class Microcontroller extends RedstoneAware with traits.PowerAcceptor with trait
}
override def rarity(stack: ItemStack) = {
- val data = new ItemUtils.MicrocontrollerData(stack)
+ val data = new MicrocontrollerData(stack)
Rarity.byTier(data.tier)
}
@@ -81,26 +76,16 @@ class Microcontroller extends RedstoneAware with traits.PowerAcceptor with trait
else false
}
- override def onBlockPlacedBy(world: World, pos: BlockPos, state: IBlockState, placer: EntityLivingBase, stack: ItemStack) {
- super.onBlockPlacedBy(world, pos, state, placer, stack)
- if (!world.isRemote) world.getTileEntity(pos) match {
- case mcu: tileentity.Microcontroller =>
- mcu.info.load(stack)
- mcu.snooperNode.changeBuffer(mcu.info.storedEnergy - mcu.snooperNode.localBuffer)
- case _ =>
- }
+ override protected def doCustomInit(tileEntity: tileentity.Microcontroller, player: EntityLivingBase, stack: ItemStack): Unit = {
+ super.doCustomInit(tileEntity, player, stack)
+ tileEntity.info.load(stack)
+ tileEntity.snooperNode.changeBuffer(tileEntity.info.storedEnergy - tileEntity.snooperNode.localBuffer)
}
- override def removedByPlayer(world: World, pos: BlockPos, player: EntityPlayer, willHarvest: Boolean) = {
- if (!world.isRemote) {
- world.getTileEntity(pos) match {
- case mcu: tileentity.Microcontroller =>
- mcu.saveComponents()
- mcu.info.storedEnergy = mcu.snooperNode.localBuffer.toInt
- InventoryUtils.spawnStackInWorld(BlockPosition(pos, world), mcu.info.createItemStack())
- case _ =>
- }
- }
- super.removedByPlayer(world, pos, player, willHarvest)
+ override protected def doCustomDrops(tileEntity: tileentity.Microcontroller, player: EntityPlayer, willHarvest: Boolean): Unit = {
+ super.doCustomDrops(tileEntity, player, willHarvest)
+ tileEntity.saveComponents()
+ tileEntity.info.storedEnergy = tileEntity.snooperNode.localBuffer.toInt
+ Block.spawnAsEntity(tileEntity.world, tileEntity.getPos, tileEntity.info.createItemStack())
}
}
diff --git a/src/main/scala/li/cil/oc/common/block/Raid.scala b/src/main/scala/li/cil/oc/common/block/Raid.scala
index e9a199c8f..e243e30ff 100644
--- a/src/main/scala/li/cil/oc/common/block/Raid.scala
+++ b/src/main/scala/li/cil/oc/common/block/Raid.scala
@@ -1,19 +1,40 @@
package li.cil.oc.common.block
-import li.cil.oc.OpenComputers
+import java.util
+
+import li.cil.oc.client.KeyBindings
import li.cil.oc.common.GuiType
+import li.cil.oc.common.item.data.RaidData
import li.cil.oc.common.tileentity
+import net.minecraft.block.Block
import net.minecraft.block.state.IBlockState
+import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.item.ItemStack
import net.minecraft.util.BlockPos
-import net.minecraft.util.EnumFacing
import net.minecraft.world.World
-class Raid extends SimpleBlock with traits.Rotatable {
+import scala.reflect.ClassTag
+
+class Raid(protected implicit val tileTag: ClassTag[tileentity.Raid]) extends SimpleBlock with traits.Rotatable with traits.GUI with traits.CustomDrops[tileentity.Raid] {
override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state)
override def hasTileEntity(state: IBlockState) = true
+ override protected def tooltipTail(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
+ super.tooltipTail(metadata, stack, player, tooltip, advanced)
+ if (KeyBindings.showExtendedTooltips) {
+ val data = new RaidData(stack)
+ for (disk <- data.disks) {
+ tooltip.add("- " + disk.getDisplayName)
+ }
+ }
+ }
+
+ // ----------------------------------------------------------------------- //
+
+ override def guiType = GuiType.Raid
+
override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Raid()
// ----------------------------------------------------------------------- //
@@ -26,16 +47,27 @@ class Raid extends SimpleBlock with traits.Rotatable {
case _ => 0
}
- // ----------------------------------------------------------------------- //
-
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
- world.getTileEntity(pos) match {
- case drive: tileentity.Raid if !player.isSneaking =>
- if (!world.isRemote) {
- player.openGui(OpenComputers, GuiType.Raid.id, world, pos.getX, pos.getY, pos.getZ)
- }
- true
- case _ => false
+ override protected def doCustomInit(tileEntity: tileentity.Raid, player: EntityLivingBase, stack: ItemStack): Unit = {
+ super.doCustomInit(tileEntity, player, stack)
+ val data = new RaidData(stack)
+ for (i <- 0 until math.min(data.disks.length, tileEntity.getSizeInventory)) {
+ tileEntity.setInventorySlotContents(i, data.disks(i))
+ }
+ data.label.foreach(tileEntity.label.setLabel)
+ if (!data.filesystem.hasNoTags) {
+ tileEntity.tryCreateRaid(data.filesystem.getCompoundTag("node").getString("address"))
+ tileEntity.filesystem.foreach(_.load(data.filesystem))
}
}
+
+ override protected def doCustomDrops(tileEntity: tileentity.Raid, player: EntityPlayer, willHarvest: Boolean): Unit = {
+ super.doCustomDrops(tileEntity, player, willHarvest)
+ val stack = createItemStack()
+ val data = new RaidData()
+ data.disks = tileEntity.items.map(_.orNull)
+ tileEntity.filesystem.foreach(_.save(data.filesystem))
+ data.label = Option(tileEntity.label.getLabel)
+ data.save(stack)
+ Block.spawnAsEntity(tileEntity.world, tileEntity.getPos, stack)
+ }
}
diff --git a/src/main/scala/li/cil/oc/common/block/RobotAfterimage.scala b/src/main/scala/li/cil/oc/common/block/RobotAfterimage.scala
index 9055f23e0..2388ff489 100644
--- a/src/main/scala/li/cil/oc/common/block/RobotAfterimage.scala
+++ b/src/main/scala/li/cil/oc/common/block/RobotAfterimage.scala
@@ -4,9 +4,9 @@ import java.util.Random
import li.cil.oc.Settings
import li.cil.oc.api
+import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.NEI
-import li.cil.oc.util.ItemUtils
import li.cil.oc.util.Rarity
import net.minecraft.block.state.IBlockState
import net.minecraft.entity.player.EntityPlayer
@@ -30,6 +30,8 @@ class RobotAfterimage extends SimpleBlock {
override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
+ override def isSideSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
+
override def getPickBlock(target: MovingObjectPosition, world: World, pos: BlockPos) =
findMovingRobot(world, pos) match {
case Some(robot) => robot.info.createItemStack()
@@ -43,7 +45,7 @@ class RobotAfterimage extends SimpleBlock {
// ----------------------------------------------------------------------- //
override def rarity(stack: ItemStack) = {
- val data = new ItemUtils.RobotData(stack)
+ val data = new RobotData(stack)
Rarity.byTier(data.tier)
}
diff --git a/src/main/scala/li/cil/oc/common/block/RobotProxy.scala b/src/main/scala/li/cil/oc/common/block/RobotProxy.scala
index 936e27962..a15d4264d 100644
--- a/src/main/scala/li/cil/oc/common/block/RobotProxy.scala
+++ b/src/main/scala/li/cil/oc/common/block/RobotProxy.scala
@@ -7,13 +7,13 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.client.KeyBindings
import li.cil.oc.common.GuiType
+import li.cil.oc.common.item.data.RobotData
import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.NEI
import li.cil.oc.server.PacketSender
import li.cil.oc.server.component.robot
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.InventoryUtils
-import li.cil.oc.util.ItemUtils
import li.cil.oc.util.Rarity
import li.cil.oc.util.Tooltip
import net.minecraft.block.state.IBlockState
@@ -46,6 +46,8 @@ class RobotProxy extends RedstoneAware with traits.StateAware {
override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
+ override def isSideSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = false
+
override def getPickBlock(target: MovingObjectPosition, world: World, pos: BlockPos) =
world.getTileEntity(pos) match {
case proxy: tileentity.RobotProxy => proxy.robot.info.copyItemStack()
@@ -55,7 +57,7 @@ class RobotProxy extends RedstoneAware with traits.StateAware {
// ----------------------------------------------------------------------- //
override def rarity(stack: ItemStack) = {
- val data = new ItemUtils.RobotData(stack)
+ val data = new RobotData(stack)
Rarity.byTier(data.tier)
}
@@ -71,7 +73,7 @@ class RobotProxy extends RedstoneAware with traits.StateAware {
override protected def tooltipTail(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean) {
super.tooltipTail(metadata, stack, player, tooltip, advanced)
if (KeyBindings.showExtendedTooltips) {
- val info = new ItemUtils.RobotData(stack)
+ val info = new RobotData(stack)
val components = info.containers ++ info.components
if (components.length > 0) {
tooltip.addAll(Tooltip.get("Server.Components"))
diff --git a/src/main/scala/li/cil/oc/common/block/Screen.scala b/src/main/scala/li/cil/oc/common/block/Screen.scala
index 6ce1cfb36..b2b3656d1 100644
--- a/src/main/scala/li/cil/oc/common/block/Screen.scala
+++ b/src/main/scala/li/cil/oc/common/block/Screen.scala
@@ -36,6 +36,8 @@ object Screen {
class Screen(val tier: Int) extends RedstoneAware with traits.OmniRotatable {
setLightLevel(0.34f)
+ override def isSideSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = toLocal(world, pos, side) != EnumFacing.SOUTH
+
override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state)
override protected def addExtendedState(state: IBlockState, world: IBlockAccess, pos: BlockPos) =
@@ -83,8 +85,9 @@ class Screen(val tier: Int) extends RedstoneAware with traits.OmniRotatable {
override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = rightClick(world, pos, player, side, hitX, hitY, hitZ, force = false)
- def rightClick(world: World, pos: BlockPos, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float, force: Boolean) =
- if (Wrench.holdsApplicableWrench(player, pos)) false
+ def rightClick(world: World, pos: BlockPos, player: EntityPlayer,
+ side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float, force: Boolean) = {
+ if (Wrench.holdsApplicableWrench(player, pos) && getValidRotations(world, pos).contains(side) && !force) false
else world.getTileEntity(pos) match {
case screen: tileentity.Screen if screen.hasKeyboard && (force || player.isSneaking == screen.invertTouchMode) =>
// Yep, this GUI is actually purely client side. We could skip this
@@ -98,6 +101,7 @@ class Screen(val tier: Int) extends RedstoneAware with traits.OmniRotatable {
screen.click(player, hitX, hitY, hitZ)
case _ => false
}
+ }
override def onEntityCollidedWithBlock(world: World, pos: BlockPos, entity: Entity) =
if (world.isRemote) (entity, world.getTileEntity(pos)) match {
diff --git a/src/main/scala/li/cil/oc/common/block/ServerRack.scala b/src/main/scala/li/cil/oc/common/block/ServerRack.scala
index 92faf2fbf..82a78ccff 100644
--- a/src/main/scala/li/cil/oc/common/block/ServerRack.scala
+++ b/src/main/scala/li/cil/oc/common/block/ServerRack.scala
@@ -1,11 +1,9 @@
package li.cil.oc.common.block
-import li.cil.oc.OpenComputers
import li.cil.oc.Settings
import li.cil.oc.common.GuiType
import li.cil.oc.common.tileentity
import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.player.EntityPlayer
import net.minecraft.util.BlockPos
import net.minecraft.util.EnumFacing
import net.minecraft.world.IBlockAccess
@@ -13,7 +11,7 @@ import net.minecraft.world.World
import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly
-class ServerRack extends RedstoneAware with traits.PowerAcceptor with traits.Rotatable with traits.StateAware {
+class ServerRack extends RedstoneAware with traits.PowerAcceptor with traits.Rotatable with traits.StateAware with traits.GUI {
override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state)
@SideOnly(Side.CLIENT)
@@ -31,23 +29,15 @@ class ServerRack extends RedstoneAware with traits.PowerAcceptor with traits.Rot
override def isBlockSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = side == EnumFacing.SOUTH
+ override def isSideSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = toLocal(world, pos, side) != EnumFacing.SOUTH
+
// ----------------------------------------------------------------------- //
override def energyThroughput = Settings.get.serverRackRate
+ override def guiType = GuiType.Rack
+
override def hasTileEntity(state: IBlockState) = true
override def createNewTileEntity(world: World, metadata: Int) = new tileentity.ServerRack()
-
- // ----------------------------------------------------------------------- //
-
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
- if (!player.isSneaking) {
- if (!world.isRemote) {
- player.openGui(OpenComputers, GuiType.Rack.id, world, pos.getX, pos.getY, pos.getZ)
- }
- true
- }
- else false
- }
}
diff --git a/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala b/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala
index d67aa71a2..12f690080 100644
--- a/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala
+++ b/src/main/scala/li/cil/oc/common/block/SimpleBlock.scala
@@ -156,7 +156,7 @@ abstract class SimpleBlock(material: Material = Material.iron) extends BlockCont
// Block
// ----------------------------------------------------------------------- //
- override def isNormalCube(world: IBlockAccess, pos: BlockPos) = true
+ override def isSideSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = true
override def canHarvestBlock(world: IBlockAccess, pos: BlockPos, player: EntityPlayer) = true
diff --git a/src/main/scala/li/cil/oc/common/block/Switch.scala b/src/main/scala/li/cil/oc/common/block/Switch.scala
index e5e66b83c..ab8c82e1d 100644
--- a/src/main/scala/li/cil/oc/common/block/Switch.scala
+++ b/src/main/scala/li/cil/oc/common/block/Switch.scala
@@ -1,31 +1,14 @@
package li.cil.oc.common.block
-import li.cil.oc.OpenComputers
import li.cil.oc.common.GuiType
import li.cil.oc.common.tileentity
import net.minecraft.block.state.IBlockState
-import net.minecraft.entity.player.EntityPlayer
-import net.minecraft.util.BlockPos
-import net.minecraft.util.EnumFacing
import net.minecraft.world.World
-class Switch extends SimpleBlock {
+class Switch extends SimpleBlock with traits.GUI {
+ override def guiType = GuiType.Switch
+
override def hasTileEntity(state: IBlockState) = true
override def createNewTileEntity(world: World, metadata: Int) = new tileentity.Switch()
-
- // ----------------------------------------------------------------------- //
-
- override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = {
- world.getTileEntity(pos) match {
- case switch: tileentity.Switch =>
- if (!player.isSneaking) {
- if (!world.isRemote) {
- player.openGui(OpenComputers, GuiType.Switch.id, world, pos.getX, pos.getY, pos.getZ)
- }
- true
- }
- else false
- }
- }
}
diff --git a/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala b/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala
new file mode 100644
index 000000000..cc15911ff
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/block/traits/CustomDrops.scala
@@ -0,0 +1,50 @@
+package li.cil.oc.common.block.traits
+
+import java.util
+
+import li.cil.oc.common.block.SimpleBlock
+import net.minecraft.block.state.IBlockState
+import net.minecraft.entity.EntityLivingBase
+import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.item.ItemStack
+import net.minecraft.tileentity.TileEntity
+import net.minecraft.util.BlockPos
+import net.minecraft.world.IBlockAccess
+import net.minecraft.world.World
+
+import scala.reflect.ClassTag
+
+trait CustomDrops[Tile <: TileEntity] extends SimpleBlock {
+ protected def tileTag: ClassTag[Tile]
+
+ override def getDrops(world: IBlockAccess, pos: BlockPos, state: IBlockState, fortune: Int): util.List[ItemStack] = new java.util.ArrayList[ItemStack]()
+
+ override def breakBlock(world: World, pos: BlockPos, state: IBlockState): Unit = {}
+
+
+ override def removedByPlayer(world: World, pos: BlockPos, player: EntityPlayer, willHarvest: Boolean): Boolean = {
+ if (!world.isRemote) {
+ val matcher = tileTag
+ world.getTileEntity(pos) match {
+ case matcher(tileEntity) => doCustomDrops(tileEntity, player, willHarvest)
+ case _ =>
+ }
+ }
+ super.removedByPlayer(world, pos, player, willHarvest)
+ }
+
+ override def onBlockPlacedBy(world: World, pos: BlockPos, state: IBlockState, placer: EntityLivingBase, stack: ItemStack): Unit = {
+ super.onBlockPlacedBy(world, pos, state, placer, stack)
+ if (!world.isRemote) {
+ val matcher = tileTag
+ world.getTileEntity(pos) match {
+ case matcher(tileEntity) => doCustomInit(tileEntity, placer, stack)
+ case _ =>
+ }
+ }
+ }
+
+ protected def doCustomInit(tileEntity: Tile, player: EntityLivingBase, stack: ItemStack): Unit = {}
+
+ protected def doCustomDrops(tileEntity: Tile, player: EntityPlayer, willHarvest: Boolean): Unit = {}
+}
diff --git a/src/main/scala/li/cil/oc/common/block/traits/GUI.scala b/src/main/scala/li/cil/oc/common/block/traits/GUI.scala
new file mode 100644
index 000000000..3b224f612
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/block/traits/GUI.scala
@@ -0,0 +1,24 @@
+package li.cil.oc.common.block.traits
+
+import li.cil.oc.OpenComputers
+import li.cil.oc.common.GuiType
+import li.cil.oc.common.block.SimpleBlock
+import net.minecraft.block.state.IBlockState
+import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.util.BlockPos
+import net.minecraft.util.EnumFacing
+import net.minecraft.world.World
+
+trait GUI extends SimpleBlock {
+ def guiType: GuiType.EnumVal
+
+ override def localOnBlockActivated(world: World, pos: BlockPos, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
+ if (!player.isSneaking) {
+ if (!world.isRemote) {
+ player.openGui(OpenComputers, guiType.id, world, pos.getX, pos.getY, pos.getZ)
+ }
+ true
+ }
+ else super.localOnBlockActivated(world, pos, player, side, hitX, hitY, hitZ)
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/component/TextBuffer.scala b/src/main/scala/li/cil/oc/common/component/TextBuffer.scala
index d4a80c7a1..d7a660e98 100644
--- a/src/main/scala/li/cil/oc/common/component/TextBuffer.scala
+++ b/src/main/scala/li/cil/oc/common/component/TextBuffer.scala
@@ -41,14 +41,16 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
withConnector().
create()
- private var maxResolution = Settings.screenResolutionsByTier(0)
+ private var maxResolution = Settings.screenResolutionsByTier(Tier.One)
- private var maxDepth = Settings.screenDepthsByTier(0)
+ private var maxDepth = Settings.screenDepthsByTier(Tier.One)
private var aspectRatio = (1.0, 1.0)
private var powerConsumptionPerTick = Settings.get.screenCost
+ private var precisionMode = false
+
// For client side only.
private var isRendering = true
@@ -162,6 +164,21 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
}
}
+ @Callback(direct = true, doc = """function():boolean -- Returns whether the screen is in high precision mode (sub-pixel mouse event positions).""")
+ def isPrecise(computer: Context, args: Arguments): Array[AnyRef] = result(precisionMode)
+
+ @Callback(doc = """function(enabled:boolean):boolean -- Set whether to use high precision mode (sub-pixel mouse event positions).""")
+ def setPrecise(computer: Context, args: Arguments): Array[AnyRef] = {
+ // Available for T3 screens only... easiest way to check for us is to
+ // base it off of the maximum color depth.
+ if (maxDepth == Settings.screenDepthsByTier(Tier.Three)) {
+ val oldValue = precisionMode
+ precisionMode = args.checkBoolean(0)
+ result(oldValue)
+ }
+ else result(Unit, "unsupported operation")
+ }
+
// ----------------------------------------------------------------------- //
override def setEnergyCostPerTick(value: Double) {
@@ -189,7 +206,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
if (height < 1) throw new IllegalArgumentException("height must be larger or equal to one")
maxResolution = (width, height)
fullyLitCost = computeFullyLitCost()
- proxy.onScreenMaxResolutionChange(width, width)
+ proxy.onBufferMaxResolutionChange(width, width)
}
override def getMaximumWidth = maxResolution._1
@@ -205,7 +222,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
if (w < 1 || h < 1 || w > mw || h > mw || h * w > mw * mh)
throw new IllegalArgumentException("unsupported resolution")
// Always send to clients, their state might be dirty.
- proxy.onScreenResolutionChange(w, h)
+ proxy.onBufferResolutionChange(w, h)
if (data.size = (w, h)) {
if (node != null) {
node.sendToReachable("computer.signal", "screen_resized", Int.box(w), Int.box(h))
@@ -227,7 +244,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
if (depth.ordinal > maxDepth.ordinal)
throw new IllegalArgumentException("unsupported depth")
// Always send to clients, their state might be dirty.
- proxy.onScreenDepthChange(depth)
+ proxy.onBufferDepthChange(depth)
data.format = PackedColor.Depth.format(depth)
}
@@ -236,7 +253,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
override def setPaletteColor(index: Int, color: Int) = data.format match {
case palette: PackedColor.MutablePaletteFormat =>
palette(index) = color
- proxy.onScreenPaletteChange(index)
+ proxy.onBufferPaletteChange(index)
case _ => throw new Exception("palette not available")
}
@@ -251,7 +268,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
val value = PackedColor.Color(color, isFromPalette)
if (data.foreground != value) {
data.foreground = value
- proxy.onScreenColorChange()
+ proxy.onBufferColorChange()
}
}
@@ -265,7 +282,7 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
val value = PackedColor.Color(color, isFromPalette)
if (data.background != value) {
data.background = value
- proxy.onScreenColorChange()
+ proxy.onBufferColorChange()
}
}
@@ -275,27 +292,28 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
def copy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) =
if (data.copy(col, row, w, h, tx, ty))
- proxy.onScreenCopy(col, row, w, h, tx, ty)
+ proxy.onBufferCopy(col, row, w, h, tx, ty)
def fill(col: Int, row: Int, w: Int, h: Int, c: Char) =
if (data.fill(col, row, w, h, c))
- proxy.onScreenFill(col, row, w, h, c)
+ proxy.onBufferFill(col, row, w, h, c)
- def set(col: Int, row: Int, s: String, vertical: Boolean) = if (col < data.width && (col >= 0 || -col < s.length)) {
- // Make sure the string isn't longer than it needs to be, in particular to
- // avoid sending too much data to our clients.
- val (x, y, truncated) =
- if (vertical) {
- if (row < 0) (col, 0, s.substring(-row))
- else (col, row, s.substring(0, math.min(s.length, data.height - row)))
- }
- else {
- if (col < 0) (0, row, s.substring(-col))
- else (col, row, s.substring(0, math.min(s.length, data.width - col)))
- }
- if (data.set(x, y, truncated, vertical))
- proxy.onScreenSet(x, row, truncated, vertical)
- }
+ def set(col: Int, row: Int, s: String, vertical: Boolean): Unit =
+ if (col < data.width && (col >= 0 || -col < s.length)) {
+ // Make sure the string isn't longer than it needs to be, in particular to
+ // avoid sending too much data to our clients.
+ val (x, y, truncated) =
+ if (vertical) {
+ if (row < 0) (col, 0, s.substring(-row))
+ else (col, row, s.substring(0, math.min(s.length, data.height - row)))
+ }
+ else {
+ if (col < 0) (0, row, s.substring(-col))
+ else (col, row, s.substring(0, math.min(s.length, data.width - col)))
+ }
+ if (data.set(x, y, truncated, vertical))
+ proxy.onBufferSet(x, row, truncated, vertical)
+ }
def get(col: Int, row: Int) = data.get(col, row)
@@ -321,6 +339,40 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
override def isBackgroundFromPalette(column: Int, row: Int) =
data.format.isFromPalette(PackedColor.extractBackground(color(column, row)))
+ override def rawSetText(col: Int, row: Int, text: Array[Array[Char]]): Unit = {
+ for (y <- row until ((row + text.length) min data.height)) {
+ val line = text(y - row)
+ Array.copy(line, 0, data.buffer(y), col, line.length min data.width)
+ }
+ proxy.onBufferRawSetText(col, row, text)
+ }
+
+ override def rawSetBackground(col: Int, row: Int, color: Array[Array[Int]]): Unit = {
+ for (y <- row until ((row + color.length) min data.height)) {
+ val line = color(y - row)
+ for (x <- col until ((col + line.length) min data.width)) {
+ val packedBackground = data.color(row)(col) & 0x00FF
+ val packedForeground = (data.format.deflate(PackedColor.Color(line(x - col))) << PackedColor.ForegroundShift) & 0xFF00
+ data.color(row)(col) = (packedForeground | packedBackground).toShort
+ }
+ }
+ // TODO Better for bandwidth to send packed shorts here. Would need a special case for handling on client, though...
+ proxy.onBufferRawSetBackground(col, row, color)
+ }
+
+ override def rawSetForeground(col: Int, row: Int, color: Array[Array[Int]]): Unit = {
+ for (y <- row until ((row + color.length) min data.height)) {
+ val line = color(y - row)
+ for (x <- col until ((col + line.length) min data.width)) {
+ val packedBackground = data.format.deflate(PackedColor.Color(line(x - col))) & 0x00FF
+ val packedForeground = data.color(row)(col) & 0xFF00
+ data.color(row)(col) = (packedForeground | packedBackground).toShort
+ }
+ }
+ // TODO Better for bandwidth to send packed shorts here. Would need a special case for handling on client, though...
+ proxy.onBufferRawSetForeground(col, row, color)
+ }
+
private def color(column: Int, row: Int) = {
if (column < 0 || column >= getWidth || row < 0 || row >= getHeight)
throw new IndexOutOfBoundsException()
@@ -351,16 +403,16 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
override def clipboard(value: String, player: EntityPlayer) =
proxy.clipboard(value, player)
- override def mouseDown(x: Int, y: Int, button: Int, player: EntityPlayer) =
+ override def mouseDown(x: Double, y: Double, button: Int, player: EntityPlayer) =
proxy.mouseDown(x, y, button, player)
- override def mouseDrag(x: Int, y: Int, button: Int, player: EntityPlayer) =
+ override def mouseDrag(x: Double, y: Double, button: Int, player: EntityPlayer) =
proxy.mouseDrag(x, y, button, player)
- override def mouseUp(x: Int, y: Int, button: Int, player: EntityPlayer) =
+ override def mouseUp(x: Double, y: Double, button: Int, player: EntityPlayer) =
proxy.mouseUp(x, y, button, player)
- override def mouseScroll(x: Int, y: Int, delta: Int, player: EntityPlayer) =
+ override def mouseScroll(x: Double, y: Double, delta: Int, player: EntityPlayer) =
proxy.mouseScroll(x, y, delta, player)
// ----------------------------------------------------------------------- //
@@ -403,6 +455,12 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
if (nbt.hasKey(Settings.namespace + "hasPower")) {
hasPower = nbt.getBoolean(Settings.namespace + "hasPower")
}
+ if (nbt.hasKey(Settings.namespace + "maxWidth") && nbt.hasKey(Settings.namespace + "maxHeight")) {
+ val maxWidth = nbt.getInteger(Settings.namespace + "maxWidth")
+ val maxHeight = nbt.getInteger(Settings.namespace + "maxHeight")
+ maxResolution = (maxWidth, maxHeight)
+ }
+ precisionMode = nbt.getBoolean(Settings.namespace + "precise")
}
// Null check for Waila (and other mods that may call this client side).
@@ -428,6 +486,9 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
SaveHandler.scheduleSave(host, nbt, node.address + "_buffer", data.save _)
nbt.setBoolean(Settings.namespace + "isOn", isDisplaying)
nbt.setBoolean(Settings.namespace + "hasPower", hasPower)
+ nbt.setInteger(Settings.namespace + "maxWidth", maxResolution._1)
+ nbt.setInteger(Settings.namespace + "maxHeight", maxResolution._2)
+ nbt.setBoolean(Settings.namespace + "precise", precisionMode)
}
}
@@ -477,28 +538,40 @@ object TextBuffer {
def render() = false
- def onScreenColorChange(): Unit
+ def onBufferColorChange(): Unit
- def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
+ def onBufferCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
owner.relativeLitArea = -1
}
- def onScreenDepthChange(depth: ColorDepth): Unit
+ def onBufferDepthChange(depth: ColorDepth): Unit
- def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
+ def onBufferFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
owner.relativeLitArea = -1
}
- def onScreenPaletteChange(index: Int): Unit
+ def onBufferPaletteChange(index: Int): Unit
- def onScreenResolutionChange(w: Int, h: Int) {
+ def onBufferResolutionChange(w: Int, h: Int) {
owner.relativeLitArea = -1
}
- def onScreenMaxResolutionChange(w: Int, h: Int) {
+ def onBufferMaxResolutionChange(w: Int, h: Int) {
}
- def onScreenSet(col: Int, row: Int, s: String, vertical: Boolean) {
+ def onBufferSet(col: Int, row: Int, s: String, vertical: Boolean) {
+ owner.relativeLitArea = -1
+ }
+
+ def onBufferRawSetText(col: Int, row: Int, text: Array[Array[Char]]) {
+ owner.relativeLitArea = -1
+ }
+
+ def onBufferRawSetBackground(col: Int, row: Int, color: Array[Array[Int]]) {
+ owner.relativeLitArea = -1
+ }
+
+ def onBufferRawSetForeground(col: Int, row: Int, color: Array[Array[Int]]) {
owner.relativeLitArea = -1
}
@@ -508,13 +581,13 @@ object TextBuffer {
def clipboard(value: String, player: EntityPlayer): Unit
- def mouseDown(x: Int, y: Int, button: Int, player: EntityPlayer): Unit
+ def mouseDown(x: Double, y: Double, button: Int, player: EntityPlayer): Unit
- def mouseDrag(x: Int, y: Int, button: Int, player: EntityPlayer): Unit
+ def mouseDrag(x: Double, y: Double, button: Int, player: EntityPlayer): Unit
- def mouseUp(x: Int, y: Int, button: Int, player: EntityPlayer): Unit
+ def mouseUp(x: Double, y: Double, button: Int, player: EntityPlayer): Unit
- def mouseScroll(x: Int, y: Int, delta: Int, player: EntityPlayer): Unit
+ def mouseScroll(x: Double, y: Double, delta: Int, player: EntityPlayer): Unit
}
class ClientProxy(val owner: TextBuffer) extends Proxy {
@@ -532,35 +605,35 @@ object TextBuffer {
wasDirty
}
- override def onScreenColorChange() {
+ override def onBufferColorChange() {
markDirty()
}
- override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
- super.onScreenCopy(col, row, w, h, tx, ty)
+ override def onBufferCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
+ super.onBufferCopy(col, row, w, h, tx, ty)
markDirty()
}
- override def onScreenDepthChange(depth: ColorDepth) {
+ override def onBufferDepthChange(depth: ColorDepth) {
markDirty()
}
- override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
- super.onScreenFill(col, row, w, h, c)
+ override def onBufferFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
+ super.onBufferFill(col, row, w, h, c)
markDirty()
}
- override def onScreenPaletteChange(index: Int) {
+ override def onBufferPaletteChange(index: Int) {
markDirty()
}
- override def onScreenResolutionChange(w: Int, h: Int) {
- super.onScreenResolutionChange(w, h)
+ override def onBufferResolutionChange(w: Int, h: Int) {
+ super.onBufferResolutionChange(w, h)
markDirty()
}
- override def onScreenSet(col: Int, row: Int, s: String, vertical: Boolean) {
- super.onScreenSet(col, row, s, vertical)
+ override def onBufferSet(col: Int, row: Int, s: String, vertical: Boolean) {
+ super.onBufferSet(col, row, s, vertical)
dirty = true
}
@@ -579,22 +652,22 @@ object TextBuffer {
ClientPacketSender.sendClipboard(nodeAddress, value)
}
- override def mouseDown(x: Int, y: Int, button: Int, player: EntityPlayer) {
+ override def mouseDown(x: Double, y: Double, button: Int, player: EntityPlayer) {
debug(s"{type = mouseDown, x = $x, y = $y, button = $button}")
ClientPacketSender.sendMouseClick(nodeAddress, x, y, drag = false, button)
}
- override def mouseDrag(x: Int, y: Int, button: Int, player: EntityPlayer) {
+ override def mouseDrag(x: Double, y: Double, button: Int, player: EntityPlayer) {
debug(s"{type = mouseDrag, x = $x, y = $y, button = $button}")
ClientPacketSender.sendMouseClick(nodeAddress, x, y, drag = true, button)
}
- override def mouseUp(x: Int, y: Int, button: Int, player: EntityPlayer) {
+ override def mouseUp(x: Double, y: Double, button: Int, player: EntityPlayer) {
debug(s"{type = mouseUp, x = $x, y = $y, button = $button}")
ClientPacketSender.sendMouseUp(nodeAddress, x, y, button)
}
- override def mouseScroll(x: Int, y: Int, delta: Int, player: EntityPlayer) {
+ override def mouseScroll(x: Double, y: Double, delta: Int, player: EntityPlayer) {
debug(s"{type = mouseScroll, x = $x, y = $y, delta = $delta}")
ClientPacketSender.sendMouseScroll(nodeAddress, x, y, delta)
}
@@ -609,53 +682,71 @@ object TextBuffer {
}
class ServerProxy(val owner: TextBuffer) extends Proxy {
- override def onScreenColorChange() {
+ override def onBufferColorChange() {
owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferColorChange(owner.pendingCommands, owner.data.foreground, owner.data.background))
}
- override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
- super.onScreenCopy(col, row, w, h, tx, ty)
+ override def onBufferCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
+ super.onBufferCopy(col, row, w, h, tx, ty)
owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferCopy(owner.pendingCommands, col, row, w, h, tx, ty))
}
- override def onScreenDepthChange(depth: ColorDepth) {
+ override def onBufferDepthChange(depth: ColorDepth) {
owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferDepthChange(owner.pendingCommands, depth))
}
- override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
- super.onScreenFill(col, row, w, h, c)
+ override def onBufferFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
+ super.onBufferFill(col, row, w, h, c)
owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferFill(owner.pendingCommands, col, row, w, h, c))
}
- override def onScreenPaletteChange(index: Int) {
+ override def onBufferPaletteChange(index: Int) {
owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferPaletteChange(owner.pendingCommands, index, owner.getPaletteColor(index)))
}
- override def onScreenResolutionChange(w: Int, h: Int) {
- super.onScreenResolutionChange(w, h)
+ override def onBufferResolutionChange(w: Int, h: Int) {
+ super.onBufferResolutionChange(w, h)
owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferResolutionChange(owner.pendingCommands, w, h))
}
- override def onScreenMaxResolutionChange(w: Int, h: Int) {
+ override def onBufferMaxResolutionChange(w: Int, h: Int) {
if (owner.node.network != null) {
- super.onScreenMaxResolutionChange(w, h)
+ super.onBufferMaxResolutionChange(w, h)
owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferMaxResolutionChange(owner.pendingCommands, w, h))
}
}
- override def onScreenSet(col: Int, row: Int, s: String, vertical: Boolean) {
- super.onScreenSet(col, row, s, vertical)
+ override def onBufferSet(col: Int, row: Int, s: String, vertical: Boolean) {
+ super.onBufferSet(col, row, s, vertical)
owner.host.markChanged()
owner.synchronized(ServerPacketSender.appendTextBufferSet(owner.pendingCommands, col, row, s, vertical))
}
+ override def onBufferRawSetText(col: Int, row: Int, text: Array[Array[Char]]) {
+ super.onBufferRawSetText(col, row, text)
+ owner.host.markChanged()
+ owner.synchronized(ServerPacketSender.appendTextBufferRawSetText(owner.pendingCommands, col, row, text))
+ }
+
+ override def onBufferRawSetBackground(col: Int, row: Int, color: Array[Array[Int]]) {
+ super.onBufferRawSetBackground(col, row, color)
+ owner.host.markChanged()
+ owner.synchronized(ServerPacketSender.appendTextBufferRawSetBackground(owner.pendingCommands, col, row, color))
+ }
+
+ override def onBufferRawSetForeground(col: Int, row: Int, color: Array[Array[Int]]) {
+ super.onBufferRawSetForeground(col, row, color)
+ owner.host.markChanged()
+ owner.synchronized(ServerPacketSender.appendTextBufferRawSetForeground(owner.pendingCommands, col, row, color))
+ }
+
override def keyDown(character: Char, code: Int, player: EntityPlayer) {
sendToKeyboards("keyboard.keyDown", player, Char.box(character), Int.box(code))
}
@@ -668,24 +759,41 @@ object TextBuffer {
sendToKeyboards("keyboard.clipboard", player, value)
}
- override def mouseDown(x: Int, y: Int, button: Int, player: EntityPlayer) {
- if (Settings.get.inputUsername) owner.node.sendToReachable("computer.checked_signal", player, "touch", Int.box(x), Int.box(y), Int.box(button), player.getName)
- else owner.node.sendToReachable("computer.checked_signal", player, "touch", Int.box(x), Int.box(y), Int.box(button))
+ override def mouseDown(x: Double, y: Double, button: Int, player: EntityPlayer) {
+ sendMouseEvent(player, "touch", x, y, button)
}
- override def mouseDrag(x: Int, y: Int, button: Int, player: EntityPlayer) {
- if (Settings.get.inputUsername) owner.node.sendToReachable("computer.checked_signal", player, "drag", Int.box(x), Int.box(y), Int.box(button), player.getName)
- else owner.node.sendToReachable("computer.checked_signal", player, "drag", Int.box(x), Int.box(y), Int.box(button))
+ override def mouseDrag(x: Double, y: Double, button: Int, player: EntityPlayer) {
+ sendMouseEvent(player, "drag", x, y, button)
}
- override def mouseUp(x: Int, y: Int, button: Int, player: EntityPlayer) {
- if (Settings.get.inputUsername) owner.node.sendToReachable("computer.checked_signal", player, "drop", Int.box(x), Int.box(y), Int.box(button), player.getName)
- else owner.node.sendToReachable("computer.checked_signal", player, "drop", Int.box(x), Int.box(y), Int.box(button))
+ override def mouseUp(x: Double, y: Double, button: Int, player: EntityPlayer) {
+ sendMouseEvent(player, "drop", x, y, button)
}
- override def mouseScroll(x: Int, y: Int, delta: Int, player: EntityPlayer) {
- if (Settings.get.inputUsername) owner.node.sendToReachable("computer.checked_signal", player, "scroll", Int.box(x), Int.box(y), Int.box(delta), player.getName)
- else owner.node.sendToReachable("computer.checked_signal", player, "scroll", Int.box(x), Int.box(y), Int.box(delta))
+ override def mouseScroll(x: Double, y: Double, delta: Int, player: EntityPlayer) {
+ sendMouseEvent(player, "scroll", x, y, delta)
+ }
+
+ private def sendMouseEvent(player: EntityPlayer, name: String, x: Double, y: Double, data: Int) = {
+ val args = mutable.ArrayBuffer.empty[AnyRef]
+
+ args += player
+ args += name
+ if (owner.precisionMode) {
+ args += double2Double(x)
+ args += double2Double(y)
+ }
+ else {
+ args += int2Integer(x.toInt + 1)
+ args += int2Integer(y.toInt + 1)
+ }
+ args += int2Integer(data)
+ if (Settings.get.inputUsername) {
+ args += player.getName
+ }
+
+ owner.node.sendToReachable("computer.checked_signal", args: _*)
}
private def sendToKeyboards(name: String, values: AnyRef*) {
diff --git a/src/main/scala/li/cil/oc/common/container/ComponentSlot.scala b/src/main/scala/li/cil/oc/common/container/ComponentSlot.scala
index f7847bf3f..6ddce3ba2 100644
--- a/src/main/scala/li/cil/oc/common/container/ComponentSlot.scala
+++ b/src/main/scala/li/cil/oc/common/container/ComponentSlot.scala
@@ -39,6 +39,15 @@ abstract class ComponentSlot(inventory: IInventory, index: Int, x: Int, y: Int)
}
}
+ override def putStack(stack: ItemStack): Unit = {
+ super.putStack(stack)
+ inventory match {
+ case playerAware: common.tileentity.traits.PlayerInputAware =>
+ playerAware.onSetInventorySlotContents(container.playerInventory.player, getSlotIndex, stack)
+ case _ =>
+ }
+ }
+
override def onSlotChanged() {
super.onSlotChanged()
for (slot <- container.inventorySlots) slot match {
diff --git a/src/main/scala/li/cil/oc/common/entity/Drone.scala b/src/main/scala/li/cil/oc/common/entity/Drone.scala
index 5b803db74..80ee3ca7b 100644
--- a/src/main/scala/li/cil/oc/common/entity/Drone.scala
+++ b/src/main/scala/li/cil/oc/common/entity/Drone.scala
@@ -18,12 +18,12 @@ import li.cil.oc.common.Slot
import li.cil.oc.common.inventory.ComponentInventory
import li.cil.oc.common.inventory.Inventory
import li.cil.oc.common.inventory.MultiTank
+import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.server.component
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.InventoryUtils
-import li.cil.oc.util.ItemUtils
import net.minecraft.block.material.Material
import net.minecraft.entity.Entity
import net.minecraft.entity.item.EntityItem
@@ -61,7 +61,7 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
var lastEnergyUpdate = 0
// Logic stuff, components, machine and such.
- val info = new ItemUtils.MicrocontrollerData()
+ val info = new MicrocontrollerData()
val machine = if (!world.isRemote) {
val m = Machine.create(this)
m.node.asInstanceOf[Connector].setLocalBufferSize(0)
@@ -296,6 +296,7 @@ class Drone(val world: World) extends Entity(world) with MachineHost with intern
def setRunning(value: Boolean) = dataWatcher.updateObject(5, byte2Byte(if (value) 1: Byte else 0: Byte))
+
// Round target values to low accuracy to avoid floating point errors accumulating.
def targetX_=(value: Float): Unit = dataWatcher.updateObject(6, float2Float(math.round(value * 4) / 4f))
diff --git a/src/main/scala/li/cil/oc/common/init/Items.scala b/src/main/scala/li/cil/oc/common/init/Items.scala
index dd658b25d..285f101f9 100644
--- a/src/main/scala/li/cil/oc/common/init/Items.scala
+++ b/src/main/scala/li/cil/oc/common/init/Items.scala
@@ -13,10 +13,12 @@ import li.cil.oc.common.block.SimpleBlock
import li.cil.oc.common.item
import li.cil.oc.common.item.Delegator
import li.cil.oc.common.item.SimpleItem
+import li.cil.oc.common.item.data.MicrocontrollerData
+import li.cil.oc.common.item.data.RobotData
+import li.cil.oc.common.item.data.TabletData
import li.cil.oc.common.recipe.Recipes
import li.cil.oc.integration.Mods
import li.cil.oc.util.Color
-import li.cil.oc.util.ItemUtils
import net.minecraft.block.Block
import net.minecraft.creativetab.CreativeTabs
import net.minecraft.item.Item
@@ -149,7 +151,7 @@ object Items extends ItemAPI {
}
def createConfiguredDrone() = {
- val data = new ItemUtils.MicrocontrollerData()
+ val data = new MicrocontrollerData()
data.tier = Tier.Four
data.storedEnergy = Settings.get.bufferDrone.toInt
@@ -175,7 +177,7 @@ object Items extends ItemAPI {
}
def createConfiguredMicrocontroller() = {
- val data = new ItemUtils.MicrocontrollerData()
+ val data = new MicrocontrollerData()
data.tier = Tier.Four
data.storedEnergy = Settings.get.bufferMicrocontroller.toInt
@@ -198,7 +200,7 @@ object Items extends ItemAPI {
}
def createConfiguredRobot() = {
- val data = new ItemUtils.RobotData()
+ val data = new RobotData()
data.name = "Creatix"
data.tier = Tier.Four
@@ -241,6 +243,37 @@ object Items extends ItemAPI {
stack
}
+ def createConfiguredTablet() = {
+ val data = new TabletData()
+
+ data.energy = Settings.get.bufferTablet
+ data.maxEnergy = data.energy
+ data.items = Array(
+ Option(get("screen1").createItemStack(1)),
+ Option(get("keyboard").createItemStack(1)),
+
+ Option(get("signUpgrade").createItemStack(1)),
+ Option(get("pistonUpgrade").createItemStack(1)),
+
+ Option(get("graphicsCard2").createItemStack(1)),
+ Option(get("redstoneCard2").createItemStack(1)),
+ Option(get("wlanCard").createItemStack(1)),
+
+ Option(get("cpu3").createItemStack(1)),
+ Option(get("ram6").createItemStack(1)),
+ Option(get("ram6").createItemStack(1)),
+
+ Option(createLuaBios()),
+ Option(createOpenOS()),
+ Option(get("hdd3").createItemStack(1))
+ )
+
+ val stack = get("tablet").createItemStack(1)
+ data.save(stack)
+
+ stack
+ }
+
// ----------------------------------------------------------------------- //
def init() {
@@ -397,7 +430,8 @@ object Items extends ItemAPI {
Items.createLuaBios(),
Items.createConfiguredDrone(),
Items.createConfiguredMicrocontroller(),
- Items.createConfiguredRobot()
+ Items.createConfiguredRobot(),
+ Items.createConfiguredTablet()
)
override def getSubItems(item: Item, tab: CreativeTabs, list: util.List[_]): Unit = {
diff --git a/src/main/scala/li/cil/oc/common/item/DebugCard.scala b/src/main/scala/li/cil/oc/common/item/DebugCard.scala
index d52b29603..5791287bc 100644
--- a/src/main/scala/li/cil/oc/common/item/DebugCard.scala
+++ b/src/main/scala/li/cil/oc/common/item/DebugCard.scala
@@ -1,3 +1,27 @@
package li.cil.oc.common.item
-class DebugCard(val parent: Delegator) extends Delegate
+import java.util
+
+import li.cil.oc.common.item.data.DebugCardData
+import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.item.ItemStack
+import net.minecraft.world.World
+
+class DebugCard(val parent: Delegator) extends Delegate {
+ override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]): Unit = {
+ super.tooltipExtended(stack, tooltip)
+ val data = new DebugCardData(stack)
+ data.player.foreach(name => tooltip.add(s"§8$name§r"))
+ }
+
+ override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer): ItemStack = {
+ if (player.isSneaking) {
+ val data = new DebugCardData(stack)
+ if (data.player.contains(player.getName)) data.player = None
+ else data.player = Option(player.getName)
+ data.save(stack)
+ player.swingItem()
+ }
+ stack
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/item/Delegator.scala b/src/main/scala/li/cil/oc/common/item/Delegator.scala
index c5b6c83e2..99154391d 100644
--- a/src/main/scala/li/cil/oc/common/item/Delegator.scala
+++ b/src/main/scala/li/cil/oc/common/item/Delegator.scala
@@ -25,10 +25,11 @@ import scala.collection.mutable
object Delegator {
def subItem(stack: ItemStack) =
- stack.getItem match {
+ if (stack != null) stack.getItem match {
case delegator: Delegator => delegator.subItem(stack.getItemDamage)
case _ => None
}
+ else None
}
class Delegator extends Item {
diff --git a/src/main/scala/li/cil/oc/common/item/Drone.scala b/src/main/scala/li/cil/oc/common/item/Drone.scala
index 19be55688..94e8c3990 100644
--- a/src/main/scala/li/cil/oc/common/item/Drone.scala
+++ b/src/main/scala/li/cil/oc/common/item/Drone.scala
@@ -4,9 +4,9 @@ import java.util
import li.cil.oc.client.KeyBindings
import li.cil.oc.common.entity
+import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.integration.util.NEI
import li.cil.oc.util.BlockPosition
-import li.cil.oc.util.ItemUtils
import li.cil.oc.util.Rarity
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
@@ -19,15 +19,15 @@ class Drone(val parent: Delegator) extends Delegate {
override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]): Unit = {
if (KeyBindings.showExtendedTooltips) {
- val info = new ItemUtils.MicrocontrollerData(stack)
- for (component <- info.components) {
+ val info = new MicrocontrollerData(stack)
+ for (component <- info.components if component != null) {
tooltip.add("- " + component.getDisplayName)
}
}
}
override def rarity(stack: ItemStack) = {
- val data = new ItemUtils.MicrocontrollerData(stack)
+ val data = new MicrocontrollerData(stack)
Rarity.byTier(data.tier)
}
diff --git a/src/main/scala/li/cil/oc/common/item/Tablet.scala b/src/main/scala/li/cil/oc/common/item/Tablet.scala
index d635508f7..66d808f38 100644
--- a/src/main/scala/li/cil/oc/common/item/Tablet.scala
+++ b/src/main/scala/li/cil/oc/common/item/Tablet.scala
@@ -24,10 +24,9 @@ import li.cil.oc.client.KeyBindings
import li.cil.oc.common.GuiType
import li.cil.oc.common.Slot
import li.cil.oc.common.inventory.ComponentInventory
+import li.cil.oc.common.item.data.TabletData
import li.cil.oc.server.component
import li.cil.oc.util.ExtendedNBT._
-import li.cil.oc.util.ItemUtils
-import li.cil.oc.util.ItemUtils.TabletData
import li.cil.oc.util.RotationHelper
import li.cil.oc.util.Tooltip
import net.minecraft.entity.Entity
@@ -54,7 +53,7 @@ class Tablet(val parent: Delegator) extends Delegate {
override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]): Unit = {
if (KeyBindings.showExtendedTooltips) {
- val info = new ItemUtils.TabletData(stack)
+ val info = new TabletData(stack)
// Ignore/hide the screen.
val components = info.items.drop(1)
if (components.length > 1) {
@@ -70,7 +69,7 @@ class Tablet(val parent: Delegator) extends Delegate {
override def durability(stack: ItemStack) = {
if (stack.hasTagCompound) {
- val data = new ItemUtils.TabletData()
+ val data = new TabletData()
data.load(stack.getTagCompound)
data.energy / data.maxEnergy
}
diff --git a/src/main/scala/li/cil/oc/common/item/data/DebugCardData.scala b/src/main/scala/li/cil/oc/common/item/data/DebugCardData.scala
new file mode 100644
index 000000000..f22ac7a6b
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/item/data/DebugCardData.scala
@@ -0,0 +1,34 @@
+package li.cil.oc.common.item.data
+
+import li.cil.oc.Settings
+import net.minecraft.item.ItemStack
+import net.minecraft.nbt.NBTTagCompound
+
+class DebugCardData extends ItemData {
+ def this(stack: ItemStack) {
+ this()
+ load(stack)
+ }
+
+ var player: Option[String] = None
+
+ override def load(nbt: NBTTagCompound) {
+ val tag = dataTag(nbt)
+ if (tag.hasKey(Settings.namespace + "player")) {
+ player = Option(tag.getString(Settings.namespace + "player"))
+ }
+ }
+
+ override def save(nbt: NBTTagCompound) {
+ val tag = dataTag(nbt)
+ tag.removeTag(Settings.namespace + "player")
+ player.foreach(tag.setString(Settings.namespace + "player", _))
+ }
+
+ private def dataTag(nbt: NBTTagCompound) = {
+ if (!nbt.hasKey(Settings.namespace + "data")) {
+ nbt.setTag(Settings.namespace + "data", new NBTTagCompound())
+ }
+ nbt.getCompoundTag(Settings.namespace + "data")
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/item/data/ItemData.scala b/src/main/scala/li/cil/oc/common/item/data/ItemData.scala
new file mode 100644
index 000000000..1df64ade7
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/item/data/ItemData.scala
@@ -0,0 +1,26 @@
+package li.cil.oc.common.item.data
+
+import li.cil.oc.api.Persistable
+import net.minecraft.item.ItemStack
+import net.minecraft.nbt.NBTTagCompound
+
+object ItemData {
+
+}
+
+abstract class ItemData extends Persistable {
+ def load(stack: ItemStack) {
+ if (stack.hasTagCompound) {
+ // Because ItemStack's load function doesn't copy the compound tag,
+ // but keeps it as is, leading to oh so fun bugs!
+ load(stack.getTagCompound.copy().asInstanceOf[NBTTagCompound])
+ }
+ }
+
+ def save(stack: ItemStack) {
+ if (!stack.hasTagCompound) {
+ stack.setTagCompound(new NBTTagCompound())
+ }
+ save(stack.getTagCompound)
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala b/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala
new file mode 100644
index 000000000..a8657920f
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/item/data/MicrocontrollerData.scala
@@ -0,0 +1,49 @@
+package li.cil.oc.common.item.data
+
+import li.cil.oc.Settings
+import li.cil.oc.api
+import li.cil.oc.common.Tier
+import li.cil.oc.util.ExtendedNBT._
+import li.cil.oc.util.ItemUtils
+import net.minecraft.item.ItemStack
+import net.minecraft.nbt.NBTTagCompound
+import net.minecraftforge.common.util.Constants.NBT
+
+class MicrocontrollerData extends ItemData {
+ def this(stack: ItemStack) {
+ this()
+ load(stack)
+ }
+
+ var tier = Tier.One
+
+ var components = Array.empty[ItemStack]
+
+ var storedEnergy = 0
+
+ override def load(nbt: NBTTagCompound) {
+ tier = nbt.getByte(Settings.namespace + "tier")
+ components = nbt.getTagList(Settings.namespace + "components", NBT.TAG_COMPOUND).
+ toArray[NBTTagCompound].map(ItemUtils.loadStack)
+ storedEnergy = nbt.getInteger(Settings.namespace + "storedEnergy")
+ }
+
+ override def save(nbt: NBTTagCompound) {
+ nbt.setByte(Settings.namespace + "tier", tier.toByte)
+ nbt.setNewTagList(Settings.namespace + "components", components.toIterable)
+ nbt.setInteger(Settings.namespace + "storedEnergy", storedEnergy)
+ }
+
+ def createItemStack() = {
+ val stack = api.Items.get("microcontroller").createItemStack(1)
+ save(stack)
+ stack
+ }
+
+ def copyItemStack() = {
+ val stack = createItemStack()
+ val newInfo = new MicrocontrollerData(stack)
+ newInfo.save(stack)
+ stack
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/item/data/NavigationUpgradeData.scala b/src/main/scala/li/cil/oc/common/item/data/NavigationUpgradeData.scala
new file mode 100644
index 000000000..0173c41de
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/item/data/NavigationUpgradeData.scala
@@ -0,0 +1,47 @@
+package li.cil.oc.common.item.data
+
+import li.cil.oc.Settings
+import li.cil.oc.util.ExtendedNBT._
+import li.cil.oc.util.ItemUtils
+import net.minecraft.item.ItemMap
+import net.minecraft.item.ItemStack
+import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.world.World
+
+class NavigationUpgradeData extends ItemData {
+ def this(stack: ItemStack) {
+ this()
+ load(stack)
+ }
+
+ var map = new ItemStack(net.minecraft.init.Items.filled_map)
+
+ def mapData(world: World) = try map.getItem.asInstanceOf[ItemMap].getMapData(map, world) catch {
+ case _: Throwable => throw new Exception("invalid map")
+ }
+
+ override def load(stack: ItemStack) {
+ if (stack.hasTagCompound) {
+ load(stack.getTagCompound.getCompoundTag(Settings.namespace + "data"))
+ }
+ }
+
+ override def save(stack: ItemStack) {
+ if (!stack.hasTagCompound) {
+ stack.setTagCompound(new NBTTagCompound())
+ }
+ save(stack.getCompoundTag(Settings.namespace + "data"))
+ }
+
+ override def load(nbt: NBTTagCompound) {
+ if (nbt.hasKey(Settings.namespace + "map")) {
+ map = ItemUtils.loadStack(nbt.getCompoundTag(Settings.namespace + "map"))
+ }
+ }
+
+ override def save(nbt: NBTTagCompound) {
+ if (map != null) {
+ nbt.setNewCompoundTag(Settings.namespace + "map", map.writeToNBT)
+ }
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/item/data/RaidData.scala b/src/main/scala/li/cil/oc/common/item/data/RaidData.scala
new file mode 100644
index 000000000..40e05bcec
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/item/data/RaidData.scala
@@ -0,0 +1,43 @@
+package li.cil.oc.common.item.data
+
+import li.cil.oc.Settings
+import li.cil.oc.api
+import li.cil.oc.util.ExtendedNBT._
+import li.cil.oc.util.ItemUtils
+import net.minecraft.item.ItemStack
+import net.minecraft.nbt.NBTTagCompound
+import net.minecraftforge.common.util.Constants.NBT
+
+class RaidData extends ItemData {
+ def this(stack: ItemStack) {
+ this()
+ load(stack)
+ }
+
+ var disks = Array.empty[ItemStack]
+
+ var filesystem = new NBTTagCompound()
+
+ var label: Option[String] = None
+
+ override def load(nbt: NBTTagCompound): Unit = {
+ disks = nbt.getTagList(Settings.namespace + "disks", NBT.TAG_COMPOUND).
+ toArray[NBTTagCompound].map(ItemUtils.loadStack)
+ filesystem = nbt.getCompoundTag(Settings.namespace + "filesystem")
+ if (nbt.hasKey(Settings.namespace + "label")) {
+ label = Option(nbt.getString(Settings.namespace + "label"))
+ }
+ }
+
+ override def save(nbt: NBTTagCompound): Unit = {
+ nbt.setNewTagList(Settings.namespace + "disks", disks.toIterable)
+ nbt.setTag(Settings.namespace + "filesystem", filesystem)
+ label.foreach(nbt.setString(Settings.namespace + "label", _))
+ }
+
+ def createItemStack() = {
+ val stack = api.Items.get("raid").createItemStack(1)
+ save(stack)
+ stack
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/item/data/RobotData.scala b/src/main/scala/li/cil/oc/common/item/data/RobotData.scala
new file mode 100644
index 000000000..c7c36a851
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/item/data/RobotData.scala
@@ -0,0 +1,114 @@
+package li.cil.oc.common.item.data
+
+import com.google.common.base.Charsets
+import com.google.common.base.Strings
+import li.cil.oc.OpenComputers
+import li.cil.oc.Settings
+import li.cil.oc.api
+import li.cil.oc.integration.opencomputers.DriverScreen
+import li.cil.oc.util.ExtendedNBT._
+import li.cil.oc.util.ItemUtils
+import net.minecraft.item.ItemStack
+import net.minecraft.nbt.NBTTagCompound
+import net.minecraftforge.common.util.Constants.NBT
+
+import scala.io.Source
+
+object RobotData {
+ val names = try {
+ Source.fromInputStream(getClass.getResourceAsStream(
+ "/assets/" + Settings.resourceDomain + "/robot.names"))(Charsets.UTF_8).
+ getLines().map(_.takeWhile(_ != '#').trim()).filter(_ != "").toArray
+ }
+ catch {
+ case t: Throwable =>
+ OpenComputers.log.warn("Failed loading robot name list.", t)
+ Array.empty[String]
+ }
+
+ def randomName = if (names.length > 0) names((math.random * names.length).toInt) else "Robot"
+}
+
+class RobotData extends ItemData {
+ def this(stack: ItemStack) {
+ this()
+ load(stack)
+ }
+
+ var name = ""
+
+ // Overall energy including components.
+ var totalEnergy = 0
+
+ // Energy purely stored in robot component - this is what we have to restore manually.
+ var robotEnergy = 0
+
+ var tier = 0
+
+ var components = Array.empty[ItemStack]
+
+ var containers = Array.empty[ItemStack]
+
+ var lightColor = 0xF23030
+
+ override def load(nbt: NBTTagCompound) {
+ if (nbt.hasKey("display") && nbt.getCompoundTag("display").hasKey("Name")) {
+ name = nbt.getCompoundTag("display").getString("Name")
+ }
+ if (Strings.isNullOrEmpty(name)) {
+ name = RobotData.randomName
+ }
+ totalEnergy = nbt.getInteger(Settings.namespace + "storedEnergy")
+ robotEnergy = nbt.getInteger(Settings.namespace + "robotEnergy")
+ tier = nbt.getInteger(Settings.namespace + "tier")
+ components = nbt.getTagList(Settings.namespace + "components", NBT.TAG_COMPOUND).
+ toArray[NBTTagCompound].map(ItemUtils.loadStack)
+ containers = nbt.getTagList(Settings.namespace + "containers", NBT.TAG_COMPOUND).
+ toArray[NBTTagCompound].map(ItemUtils.loadStack)
+ if (nbt.hasKey(Settings.namespace + "lightColor")) {
+ lightColor = nbt.getInteger(Settings.namespace + "lightColor")
+ }
+ }
+
+ override def save(nbt: NBTTagCompound) {
+ if (!Strings.isNullOrEmpty(name)) {
+ if (!nbt.hasKey("display")) {
+ nbt.setTag("display", new NBTTagCompound())
+ }
+ nbt.getCompoundTag("display").setString("Name", name)
+ }
+ nbt.setInteger(Settings.namespace + "storedEnergy", totalEnergy)
+ nbt.setInteger(Settings.namespace + "robotEnergy", robotEnergy)
+ nbt.setInteger(Settings.namespace + "tier", tier)
+ nbt.setNewTagList(Settings.namespace + "components", components.toIterable)
+ nbt.setNewTagList(Settings.namespace + "containers", containers.toIterable)
+ nbt.setInteger(Settings.namespace + "lightColor", lightColor)
+ }
+
+ def createItemStack() = {
+ val stack = api.Items.get("robot").createItemStack(1)
+ save(stack)
+ stack
+ }
+
+ def copyItemStack() = {
+ val stack = createItemStack()
+ // Forget all node addresses and so on. This is used when 'picking' a
+ // robot in creative mode.
+ val newInfo = new RobotData(stack)
+ newInfo.components.foreach(cs => Option(api.Driver.driverFor(cs)) match {
+ case Some(driver) if driver == DriverScreen =>
+ val nbt = driver.dataTag(cs)
+ for (tagName <- nbt.getKeySet.toArray) {
+ nbt.removeTag(tagName.asInstanceOf[String])
+ }
+ case _ =>
+ })
+ // Don't show energy info (because it's unreliable) but fill up the
+ // internal buffer. This is for creative use only, anyway.
+ newInfo.totalEnergy = 0
+ newInfo.robotEnergy = 50000
+ newInfo.save(stack)
+ stack
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/item/data/TabletData.scala b/src/main/scala/li/cil/oc/common/item/data/TabletData.scala
new file mode 100644
index 000000000..635030cd1
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/item/data/TabletData.scala
@@ -0,0 +1,47 @@
+package li.cil.oc.common.item.data
+
+import li.cil.oc.Settings
+import li.cil.oc.util.ExtendedNBT._
+import li.cil.oc.util.ItemUtils
+import net.minecraft.item.ItemStack
+import net.minecraft.nbt.NBTTagCompound
+import net.minecraftforge.common.util.Constants.NBT
+
+class TabletData extends ItemData {
+ def this(stack: ItemStack) {
+ this()
+ load(stack)
+ }
+
+ var items = Array.fill[Option[ItemStack]](32)(None)
+ var isRunning = false
+ var energy = 0.0
+ var maxEnergy = 0.0
+
+ override def load(nbt: NBTTagCompound) {
+ nbt.getTagList(Settings.namespace + "items", NBT.TAG_COMPOUND).foreach((slotNbt: NBTTagCompound) => {
+ val slot = slotNbt.getByte("slot")
+ if (slot >= 0 && slot < items.length) {
+ items(slot) = Option(ItemUtils.loadStack(slotNbt.getCompoundTag("item")))
+ }
+ })
+ isRunning = nbt.getBoolean(Settings.namespace + "isRunning")
+ energy = nbt.getDouble(Settings.namespace + "energy")
+ maxEnergy = nbt.getDouble(Settings.namespace + "maxEnergy")
+ }
+
+ override def save(nbt: NBTTagCompound) {
+ nbt.setNewTagList(Settings.namespace + "items",
+ items.zipWithIndex collect {
+ case (Some(stack), slot) => (stack, slot)
+ } map {
+ case (stack, slot) =>
+ val slotNbt = new NBTTagCompound()
+ slotNbt.setByte("slot", slot.toByte)
+ slotNbt.setNewCompoundTag("item", stack.writeToNBT)
+ })
+ nbt.setBoolean(Settings.namespace + "isRunning", isRunning)
+ nbt.setDouble(Settings.namespace + "energy", energy)
+ nbt.setDouble(Settings.namespace + "maxEnergy", maxEnergy)
+ }
+}
diff --git a/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala b/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala
index ca718e78b..f10e5abeb 100644
--- a/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala
+++ b/src/main/scala/li/cil/oc/common/recipe/ExtendedRecipe.scala
@@ -5,9 +5,10 @@ import java.util.UUID
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.detail.ItemInfo
+import li.cil.oc.common.init.Items
+import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.integration.Mods
import li.cil.oc.util.ExtendedNBT._
-import li.cil.oc.util.ItemUtils
import li.cil.oc.util.SideTracker
import net.minecraft.init.Blocks
import net.minecraft.inventory.InventoryCrafting
@@ -20,6 +21,7 @@ import scala.util.control.Breaks._
object ExtendedRecipe {
private lazy val drone = api.Items.get("drone")
private lazy val eeprom = api.Items.get("eeprom")
+ private lazy val luaBios = Items.createLuaBios()
private lazy val mcu = api.Items.get("microcontroller")
private lazy val navigationUpgrade = api.Items.get("navigationUpgrade")
private lazy val linkedCard = api.Items.get("linkedCard")
@@ -71,7 +73,7 @@ object ExtendedRecipe {
}
}
- if (api.Items.get(craftedStack) == eeprom) breakable {
+ if (api.Items.get(craftedStack) == eeprom && !ItemStack.areItemStackTagsEqual(craftedStack, luaBios)) breakable {
for (slot <- 0 until inventory.getSizeInventory) {
val stack = inventory.getStackInSlot(slot)
if (stack != null && api.Items.get(stack) == eeprom && stack.hasTagCompound) {
@@ -95,7 +97,7 @@ object ExtendedRecipe {
// Find old Microcontroller.
(0 until inventory.getSizeInventory).map(inventory.getStackInSlot).find(api.Items.get(_) == descriptor) match {
case Some(oldMcu) =>
- val data = new ItemUtils.MicrocontrollerData(oldMcu)
+ val data = new MicrocontrollerData(oldMcu)
// Remove old EEPROM.
val oldRom = data.components.filter(api.Items.get(_) == eeprom)
diff --git a/src/main/scala/li/cil/oc/common/template/DroneTemplate.scala b/src/main/scala/li/cil/oc/common/template/DroneTemplate.scala
index 6adde8ba7..552fd0f26 100644
--- a/src/main/scala/li/cil/oc/common/template/DroneTemplate.scala
+++ b/src/main/scala/li/cil/oc/common/template/DroneTemplate.scala
@@ -5,6 +5,7 @@ import li.cil.oc.api
import li.cil.oc.api.internal
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
+import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.inventory.IInventory
@@ -29,7 +30,7 @@ object DroneTemplate extends Template {
def assemble(inventory: IInventory) = {
val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot)
- val data = new ItemUtils.MicrocontrollerData()
+ val data = new MicrocontrollerData()
data.tier = caseTier(inventory)
data.components = items.drop(1).filter(_ != null).toArray
data.storedEnergy = Settings.get.bufferDrone.toInt
@@ -43,7 +44,7 @@ object DroneTemplate extends Template {
def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("drone")
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
- val info = new ItemUtils.MicrocontrollerData(stack)
+ val info = new MicrocontrollerData(stack)
val itemName = ItemUtils.caseNameWithTierSuffix("droneCase", info.tier)
Array(api.Items.get(itemName).createItemStack(1)) ++ info.components
diff --git a/src/main/scala/li/cil/oc/common/template/MicrocontrollerTemplate.scala b/src/main/scala/li/cil/oc/common/template/MicrocontrollerTemplate.scala
index ed737a022..3cbd70a28 100644
--- a/src/main/scala/li/cil/oc/common/template/MicrocontrollerTemplate.scala
+++ b/src/main/scala/li/cil/oc/common/template/MicrocontrollerTemplate.scala
@@ -5,6 +5,7 @@ import li.cil.oc.api
import li.cil.oc.api.internal
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
+import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.inventory.IInventory
@@ -29,7 +30,7 @@ object MicrocontrollerTemplate extends Template {
def assemble(inventory: IInventory) = {
val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot)
- val data = new ItemUtils.MicrocontrollerData()
+ val data = new MicrocontrollerData()
data.tier = caseTier(inventory)
data.components = items.drop(1).filter(_ != null).toArray
data.storedEnergy = Settings.get.bufferMicrocontroller.toInt
@@ -43,7 +44,7 @@ object MicrocontrollerTemplate extends Template {
def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("microcontroller")
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
- val info = new ItemUtils.MicrocontrollerData(stack)
+ val info = new MicrocontrollerData(stack)
val itemName = ItemUtils.caseNameWithTierSuffix("microcontrollerCase", info.tier)
Array(api.Items.get(itemName).createItemStack(1)) ++ info.components
diff --git a/src/main/scala/li/cil/oc/common/template/NavigationUpgradeTemplate.scala b/src/main/scala/li/cil/oc/common/template/NavigationUpgradeTemplate.scala
index 0360b6140..abbf512de 100644
--- a/src/main/scala/li/cil/oc/common/template/NavigationUpgradeTemplate.scala
+++ b/src/main/scala/li/cil/oc/common/template/NavigationUpgradeTemplate.scala
@@ -1,7 +1,7 @@
package li.cil.oc.common.template
import li.cil.oc.api
-import li.cil.oc.util.ItemUtils
+import li.cil.oc.common.item.data.NavigationUpgradeData
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.fml.common.event.FMLInterModComms
@@ -12,7 +12,7 @@ object NavigationUpgradeTemplate {
def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("navigationUpgrade")
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
- val info = new ItemUtils.NavigationUpgradeData(stack)
+ val info = new NavigationUpgradeData(stack)
ingredients.map {
case part if part.getItem == net.minecraft.init.Items.filled_map => info.map
case part => part
diff --git a/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala b/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala
index 973d91ebb..6c626a57e 100644
--- a/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala
+++ b/src/main/scala/li/cil/oc/common/template/RobotTemplate.scala
@@ -5,6 +5,7 @@ import li.cil.oc.api
import li.cil.oc.api.internal
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
+import li.cil.oc.common.item.data.RobotData
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ItemUtils
import net.minecraft.inventory.IInventory
@@ -16,21 +17,21 @@ import net.minecraftforge.fml.common.event.FMLInterModComms
object RobotTemplate extends Template {
override protected def hostClass = classOf[internal.Robot]
- def selectTier1(stack: ItemStack) = ItemUtils.caseTier(stack) == Tier.One
+ def selectTier1(stack: ItemStack) = api.Items.get(stack) == api.Items.get("case1")
- def selectTier2(stack: ItemStack) = ItemUtils.caseTier(stack) == Tier.Two
+ def selectTier2(stack: ItemStack) = api.Items.get(stack) == api.Items.get("case2")
- def selectTier3(stack: ItemStack) = ItemUtils.caseTier(stack) == Tier.Three
+ def selectTier3(stack: ItemStack) = api.Items.get(stack) == api.Items.get("case3")
- def selectCreative(stack: ItemStack) = ItemUtils.caseTier(stack) == Tier.Four
+ def selectCreative(stack: ItemStack) = api.Items.get(stack) == api.Items.get("caseCreative")
def validate(inventory: IInventory): Array[AnyRef] = validateComputer(inventory)
def assemble(inventory: IInventory) = {
val items = (0 until inventory.getSizeInventory).map(inventory.getStackInSlot)
- val data = new ItemUtils.RobotData()
+ val data = new RobotData()
data.tier = ItemUtils.caseTier(inventory.getStackInSlot(0))
- data.name = ItemUtils.RobotData.randomName
+ data.name = RobotData.randomName
data.robotEnergy = Settings.get.bufferRobot.toInt
data.totalEnergy = data.robotEnergy
data.containers = items.slice(1, 4).filter(_ != null).toArray
@@ -45,7 +46,7 @@ object RobotTemplate extends Template {
def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("robot")
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
- val info = new ItemUtils.RobotData(stack)
+ val info = new RobotData(stack)
val itemName = ItemUtils.caseNameWithTierSuffix("case", info.tier)
Array(api.Items.get(itemName).createItemStack(1)) ++ info.containers ++ info.components
diff --git a/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala b/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala
index 4c9eac43f..5973bf4e4 100644
--- a/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala
+++ b/src/main/scala/li/cil/oc/common/template/TabletTemplate.scala
@@ -5,8 +5,8 @@ import li.cil.oc.api
import li.cil.oc.api.internal
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
+import li.cil.oc.common.item.data.TabletData
import li.cil.oc.util.ExtendedNBT._
-import li.cil.oc.util.ItemUtils
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
@@ -32,7 +32,7 @@ object TabletTemplate extends Template {
val items = mutable.ArrayBuffer(
Option(api.Items.get("screen1").createItemStack(1))
) ++ (1 until inventory.getSizeInventory).map(slot => Option(inventory.getStackInSlot(slot)))
- val data = new ItemUtils.TabletData()
+ val data = new TabletData()
data.items = items.filter(_.isDefined).toArray
data.energy = Settings.get.bufferTablet
data.maxEnergy = data.energy
@@ -46,7 +46,7 @@ object TabletTemplate extends Template {
def selectDisassembler(stack: ItemStack) = api.Items.get(stack) == api.Items.get("tablet")
def disassemble(stack: ItemStack, ingredients: Array[ItemStack]) = {
- val info = new ItemUtils.TabletData(stack)
+ val info = new TabletData(stack)
Array(api.Items.get("tabletCase").createItemStack(1)) ++ info.items.collect {
case Some(item) => item
}.drop(1) // Screen.
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala
index 3ea9137de..9a53c0699 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala
@@ -10,10 +10,10 @@ import li.cil.oc.api.network._
import li.cil.oc.common.Slot
import li.cil.oc.common.entity.Drone
import li.cil.oc.common.item.Tablet
+import li.cil.oc.common.item.data.TabletData
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
-import li.cil.oc.util.ItemUtils
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
@@ -101,7 +101,7 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
handler(itemCharge)
}
}
- val data = new ItemUtils.TabletData(stack)
+ val data = new TabletData(stack)
tryCharge(data.energy, data.maxEnergy, (amount) => {
data.energy = math.min(data.maxEnergy, data.energy + amount)
data.save(stack)
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Disassembler.scala b/src/main/scala/li/cil/oc/common/tileentity/Disassembler.scala
index a91daeaa6..1de6cc188 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Disassembler.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Disassembler.scala
@@ -11,6 +11,7 @@ import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.InventoryUtils
import li.cil.oc.util.ItemUtils
+import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.EnumFacing
@@ -20,7 +21,7 @@ import net.minecraftforge.fml.relauncher.SideOnly
import scala.collection.mutable
-class Disassembler extends traits.Environment with traits.PowerAcceptor with traits.Inventory with traits.StateAware {
+class Disassembler extends traits.Environment with traits.PowerAcceptor with traits.Inventory with traits.StateAware with traits.PlayerInputAware {
val node = api.Network.newNode(this, Visibility.None).
withConnector(Settings.get.bufferConverter).
create()
@@ -33,6 +34,8 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
var buffer = 0.0
+ var disassembleNextInstantly = false
+
def progress = if (queue.isEmpty) 0 else (1 - (queue.size * Settings.get.disassemblerItemCost - buffer) / totalRequiredEnergy) * 100
private def setActive(value: Boolean) = if (value != isActive) {
@@ -64,7 +67,8 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
super.updateEntity()
if (world.getTotalWorldTime % Settings.get.tickFrequency == 0) {
if (queue.isEmpty) {
- disassemble(decrStackSize(0, 1))
+ val instant = disassembleNextInstantly // Is reset via decrStackSize
+ disassemble(decrStackSize(0, 1), instant)
setActive(queue.nonEmpty)
}
else {
@@ -76,10 +80,10 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
buffer += want
}
}
- if (buffer >= Settings.get.disassemblerItemCost) {
+ while (buffer >= Settings.get.disassemblerItemCost && queue.nonEmpty) {
buffer -= Settings.get.disassemblerItemCost
val stack = queue.remove(0)
- if (world.rand.nextDouble > Settings.get.disassemblerBreakChance) {
+ if (world.rand.nextDouble >= Settings.get.disassemblerBreakChance) {
drop(stack)
}
}
@@ -87,7 +91,7 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
}
}
- def disassemble(stack: ItemStack) {
+ def disassemble(stack: ItemStack, instant: Boolean = false) {
// Validate the item, never trust Minecraft / other Mods on anything!
if (stack != null && isItemValidForSlot(0, stack)) {
val ingredients = ItemUtils.getIngredients(stack)
@@ -99,6 +103,10 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
case _ => queue ++= ingredients
}
totalRequiredEnergy = queue.size * Settings.get.disassemblerItemCost
+ if (instant) {
+ buffer = totalRequiredEnergy
+ disassembleNextInstantly = false // Just to be sure...
+ }
}
}
@@ -152,4 +160,17 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
override def isItemValidForSlot(i: Int, stack: ItemStack) =
((Settings.get.disassembleAllTheThings || api.Items.get(stack) != null) && ItemUtils.getIngredients(stack).nonEmpty) ||
DisassemblerTemplates.select(stack) != None
+
+ override def setInventorySlotContents(slot: Int, stack: ItemStack): Unit = {
+ super.setInventorySlotContents(slot, stack)
+ if (!world.isRemote) {
+ disassembleNextInstantly = false
+ }
+ }
+
+ override def onSetInventorySlotContents(player: EntityPlayer, slot: Int, stack: ItemStack): Unit = {
+ if (!world.isRemote) {
+ disassembleNextInstantly = stack != null && slot == 0 && player.capabilities.isCreativeMode
+ }
+ }
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala b/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala
index 9ffdfe455..83fbd2c6f 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Microcontroller.scala
@@ -12,8 +12,8 @@ import li.cil.oc.api.machine.Context
import li.cil.oc.api.network._
import li.cil.oc.common.Slot
import li.cil.oc.common.Tier
+import li.cil.oc.common.item.data.MicrocontrollerData
import li.cil.oc.util.ExtendedNBT._
-import li.cil.oc.util.ItemUtils
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.EnumFacing
@@ -21,7 +21,7 @@ import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly
class Microcontroller extends traits.PowerAcceptor with traits.Computer with SidedEnvironment with internal.Microcontroller {
- val info = new ItemUtils.MicrocontrollerData()
+ val info = new MicrocontrollerData()
override val node = api.Network.newNode(this, Visibility.Network).
withComponent("microcontroller").
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Raid.scala b/src/main/scala/li/cil/oc/common/tileentity/Raid.scala
index 1072e3e77..8908d87cd 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Raid.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Raid.scala
@@ -77,7 +77,7 @@ class Raid extends traits.Environment with traits.Inventory with traits.Rotatabl
}
}
- private def tryCreateRaid(id: String) {
+ def tryCreateRaid(id: String) {
if (items.count(_.isDefined) == items.length) {
val fs = api.FileSystem.asManagedEnvironment(
api.FileSystem.fromSaveDirectory(id, wipeDisksAndComputeSpace, Settings.get.bufferChanges),
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Redstone.scala b/src/main/scala/li/cil/oc/common/tileentity/Redstone.scala
index c1c9aa7e9..a94b06c37 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Redstone.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Redstone.scala
@@ -1,6 +1,7 @@
package li.cil.oc.common.tileentity
import li.cil.oc.Settings
+import li.cil.oc.api
import li.cil.oc.api.network.Visibility
import li.cil.oc.common.tileentity.traits.BundledRedstoneAware
import li.cil.oc.common.tileentity.traits.Environment
@@ -11,12 +12,18 @@ import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.EnumFacing
class Redstone extends Environment with BundledRedstoneAware {
- val instance = if (BundledRedstone.isAvailable) new component.Redstone[BundledRedstoneAware](this) with component.RedstoneBundled else new component.Redstone(this)
+ val instance =
+ if (BundledRedstone.isAvailable)
+ new component.Redstone.Bundled(this)
+ else
+ new component.Redstone.Vanilla(this)
val node = instance.node
- if (node != null) {
+ val dummyNode = if (node != null) {
node.setVisibility(Visibility.Network)
_isOutputEnabled = true
+ api.Network.newNode(this, Visibility.None).create()
}
+ else null
override def canUpdate = isServer
@@ -34,8 +41,11 @@ class Redstone extends Environment with BundledRedstoneAware {
// ----------------------------------------------------------------------- //
- override protected def onRedstoneInputChanged(side: EnumFacing) {
- super.onRedstoneInputChanged(side)
- node.sendToReachable("computer.signal", "redstone_changed", Int.box(side.ordinal()))
+ override protected def onRedstoneInputChanged(side: EnumFacing, oldMaxValue: Int, newMaxValue: Int) {
+ super.onRedstoneInputChanged(side, oldMaxValue, newMaxValue)
+ if (node != null && node.network != null) {
+ node.connect(dummyNode)
+ dummyNode.sendToNeighbors("redstone.changed", side, int2Integer(oldMaxValue), int2Integer(newMaxValue))
+ }
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala
index 37b06c629..ef5807c20 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Robot.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Robot.scala
@@ -18,6 +18,7 @@ import li.cil.oc.common.Tier
import li.cil.oc.common.inventory.InventorySelection
import li.cil.oc.common.inventory.MultiTank
import li.cil.oc.common.inventory.TankSelection
+import li.cil.oc.common.item.data.RobotData
import li.cil.oc.integration.opencomputers.DriverKeyboard
import li.cil.oc.integration.opencomputers.DriverRedstoneCard
import li.cil.oc.integration.opencomputers.DriverScreen
@@ -28,7 +29,6 @@ import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.InventoryUtils
-import li.cil.oc.util.ItemUtils
import net.minecraft.block.Block
import net.minecraft.block.BlockLiquid
import net.minecraft.client.Minecraft
@@ -37,7 +37,6 @@ import net.minecraft.init.Blocks
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
-import net.minecraft.tileentity.TileEntity
import net.minecraft.util.BlockPos
import net.minecraft.util.EnumFacing
import net.minecraftforge.common.MinecraftForge
@@ -56,7 +55,7 @@ import scala.collection.mutable
class Robot extends traits.Computer with traits.PowerInformation with IFluidHandler with internal.Robot with MultiTank with InventorySelection with TankSelection {
var proxy: RobotProxy = _
- val info = new ItemUtils.RobotData()
+ val info = new RobotData()
val bot = if (isServer) new robot.Robot(this) else null
@@ -244,7 +243,7 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
// worked before the client is notified so that we can use the same trick on
// the client by sending a corresponding packet. This also saves us from
// having to send the complete state again (e.g. screen buffer) each move.
-// world.setBlockToAir(newPosition)
+ // world.setBlockToAir(newPosition)
// In some cases (though I couldn't quite figure out which one) setBlock
// will return true, even though the block was not created / adjusted.
val created = world.setBlockState(newPosition, blockRobotProxy.getDefaultState, 1)
@@ -751,8 +750,13 @@ class Robot extends traits.Computer with traits.PowerInformation with IFluidHand
override def dropSlot(slot: Int, count: Int, direction: Option[EnumFacing]) =
InventoryUtils.dropSlot(BlockPosition(x, y, z, world), dynamicInventory, slot, count, direction)
- override def dropAllSlots() =
+ override def dropAllSlots() = {
+ InventoryUtils.dropSlot(BlockPosition(x, y, z, world), this, 0, Int.MaxValue)
+ for (slot <- containerSlots) {
+ InventoryUtils.dropSlot(BlockPosition(x, y, z, world), this, slot, Int.MaxValue)
+ }
InventoryUtils.dropAllSlots(BlockPosition(x, y, z, world), dynamicInventory)
+ }
// ----------------------------------------------------------------------- //
diff --git a/src/main/scala/li/cil/oc/common/tileentity/Screen.scala b/src/main/scala/li/cil/oc/common/tileentity/Screen.scala
index 0d1c85b80..1db36b52f 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/Screen.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/Screen.scala
@@ -139,7 +139,7 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
}
// Convert to absolute coordinates and send the packet to the server.
- origin.buffer.mouseDown((brx * bw).toInt + 1, (bry * bh).toInt + 1, 0, null)
+ origin.buffer.mouseDown(brx * bw, bry * bh, 0, null)
true
}
@@ -319,8 +319,8 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
override def onAnalyze(player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float) = Array(origin.node)
- override protected def onRedstoneInputChanged(side: EnumFacing) {
- super.onRedstoneInputChanged(side)
+ override protected def onRedstoneInputChanged(side: EnumFacing, oldMaxValue: Int, newMaxValue: Int) {
+ super.onRedstoneInputChanged(side, oldMaxValue, newMaxValue)
val hasRedstoneInput = screens.map(_.maxInput).max > 0
if (hasRedstoneInput != hadRedstoneInput) {
hadRedstoneInput = hasRedstoneInput
diff --git a/src/main/scala/li/cil/oc/common/tileentity/ServerRack.scala b/src/main/scala/li/cil/oc/common/tileentity/ServerRack.scala
index c03f97335..6ece15ecb 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/ServerRack.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/ServerRack.scala
@@ -207,7 +207,7 @@ class ServerRack extends traits.PowerAcceptor with traits.Hub with traits.PowerB
val l = 2 / 16.0
val h = 14 / 16.0
val slot = (((1 - hitY) - l) / (h - l) * 4).toInt
- Some(math.max(0, math.min(servers.length, slot)))
+ Some(math.max(0, math.min(servers.length - 1, slot)))
}
else None
}
@@ -409,10 +409,10 @@ class ServerRack extends traits.PowerAcceptor with traits.Hub with traits.PowerB
checkRedstoneInputChanged()
}
- override protected def onRedstoneInputChanged(side: EnumFacing) {
- super.onRedstoneInputChanged(side)
+ override protected def onRedstoneInputChanged(side: EnumFacing, oldMaxValue: Int, newMaxValue: Int) {
+ super.onRedstoneInputChanged(side, oldMaxValue, newMaxValue)
servers collect {
- case Some(server) => server.machine.signal("redstone_changed", server.machine.node.address, Int.box(toLocal(side).ordinal()))
+ case Some(server) => server.machine.node.sendToNeighbors("redstone.changed", toLocal(side), int2Integer(oldMaxValue), int2Integer(newMaxValue))
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/BundledRedstoneAware.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/BundledRedstoneAware.scala
index 994359314..572334707 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/BundledRedstoneAware.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/BundledRedstoneAware.scala
@@ -55,13 +55,15 @@ trait BundledRedstoneAware extends RedstoneAware /* with IBundledEmitter with IB
def bundledInput(side: EnumFacing, color: Int) =
math.max(_bundledInput(side.ordinal())(color), _rednetInput(side.ordinal())(color))
- def rednetInput(side: EnumFacing, color: Int, value: Int) =
- if (_rednetInput(side.ordinal())(color) != value) {
- if (_rednetInput(side.ordinal())(color) != -1) {
- onRedstoneInputChanged(side)
+ def rednetInput(side: EnumFacing, color: Int, value: Int): Unit = {
+ val oldValue = _rednetInput(side.ordinal())(color)
+ if (oldValue != value) {
+ if (oldValue != -1) {
+ onRedstoneInputChanged(side, oldValue, value)
}
_rednetInput(side.ordinal())(color) = value
}
+ }
def bundledOutput(side: EnumFacing) = _bundledOutput(toLocal(side).ordinal())
@@ -87,19 +89,20 @@ trait BundledRedstoneAware extends RedstoneAware /* with IBundledEmitter with IB
override protected def updateRedstoneInput(side: EnumFacing) {
super.updateRedstoneInput(side)
- val oldBundledInput = _bundledInput(side.ordinal())
+ val ownBundledInput = _bundledInput(side.ordinal())
val newBundledInput = computeBundledInput(side)
+ val oldMaxValue = ownBundledInput.max
var changed = false
if (newBundledInput != null) for (color <- 0 until 16) {
- changed = changed || (oldBundledInput(color) >= 0 && oldBundledInput(color) != newBundledInput(color))
- oldBundledInput(color) = newBundledInput(color)
+ changed = changed || (ownBundledInput(color) >= 0 && ownBundledInput(color) != newBundledInput(color))
+ ownBundledInput(color) = newBundledInput(color)
}
else for (color <- 0 until 16) {
- changed = changed || oldBundledInput(color) > 0
- oldBundledInput(color) = 0
+ changed = changed || ownBundledInput(color) > 0
+ ownBundledInput(color) = 0
}
if (changed) {
- onRedstoneInputChanged(side)
+ onRedstoneInputChanged(side, oldMaxValue, ownBundledInput.max)
}
}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala
index 841a18971..7fe0892de 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/Computer.scala
@@ -180,9 +180,9 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
checkRedstoneInputChanged()
}
- override protected def onRedstoneInputChanged(side: EnumFacing) {
- super.onRedstoneInputChanged(side)
- machine.signal("redstone_changed", machine.node.address, Int.box(toLocal(side).ordinal()))
+ override protected def onRedstoneInputChanged(side: EnumFacing, oldMaxValue: Int, newMaxValue: Int) {
+ super.onRedstoneInputChanged(side, oldMaxValue, newMaxValue)
+ machine.node.sendToNeighbors("redstone.changed", toLocal(side), int2Integer(oldMaxValue), int2Integer(newMaxValue))
}
// ----------------------------------------------------------------------- //
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/PlayerInputAware.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/PlayerInputAware.scala
new file mode 100644
index 000000000..7701b48b0
--- /dev/null
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/PlayerInputAware.scala
@@ -0,0 +1,14 @@
+package li.cil.oc.common.tileentity.traits
+
+import net.minecraft.entity.player.EntityPlayer
+import net.minecraft.inventory.IInventory
+import net.minecraft.item.ItemStack
+
+// Used to get notifications from containers when a player changes a slot in
+// this inventory. Normally the player causing a setInventorySlotContents is
+// unavailable. Using this we gain access to the causing player, allowing for
+// some player-specific logic, such as the disassembler working instantaneously
+// when used by a player in creative mode.
+trait PlayerInputAware extends IInventory {
+ def onSetInventorySlotContents(player: EntityPlayer, slot: Int, stack: ItemStack): Unit
+}
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala
index 7ea456c60..8872f2f23 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/RedstoneAware.scala
@@ -84,8 +84,8 @@ trait RedstoneAware extends RotationAware /* with IConnectable with IRedstoneEmi
val oldInput = _input(side.ordinal())
val newInput = computeInput(side)
_input(side.ordinal()) = newInput
- if (oldInput >= 0 && input(side) != oldInput) {
- onRedstoneInputChanged(side)
+ if (oldInput >= 0 && newInput != oldInput) {
+ onRedstoneInputChanged(side, oldInput, newInput)
}
}
@@ -148,7 +148,7 @@ trait RedstoneAware extends RotationAware /* with IConnectable with IRedstoneEmi
}
}
- protected def onRedstoneInputChanged(side: EnumFacing) {}
+ protected def onRedstoneInputChanged(side: EnumFacing, oldMaxValue: Int, newMaxValue: Int) {}
protected def onRedstoneOutputEnabledChanged() {
world.notifyNeighborsOfStateChange(getPos, getBlockType)
diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/power/Mekanism.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/power/Mekanism.scala
index 396e0db5d..cda7a8daf 100644
--- a/src/main/scala/li/cil/oc/common/tileentity/traits/power/Mekanism.scala
+++ b/src/main/scala/li/cil/oc/common/tileentity/traits/power/Mekanism.scala
@@ -14,7 +14,7 @@
// @Optional.Method(modid = Mods.IDs.Mekanism)
// def transferEnergyToAcceptor(side: EnumFacing, amount: Double) =
// if (!Mods.Mekanism.isAvailable) 0
-// else amount - tryChangeBuffer(side, amount * Settings.get.ratioMekanism) / Settings.get.ratioMekanism
+// else tryChangeBuffer(side, amount * Settings.get.ratioMekanism) / Settings.get.ratioMekanism
//
// @Optional.Method(modid = Mods.IDs.Mekanism)
// def getMaxEnergy = EnumFacing.values.map(globalBufferSize).max / Settings.get.ratioMekanism
diff --git a/src/main/scala/li/cil/oc/integration/Mods.scala b/src/main/scala/li/cil/oc/integration/Mods.scala
index ffd160b6c..851946fa3 100644
--- a/src/main/scala/li/cil/oc/integration/Mods.scala
+++ b/src/main/scala/li/cil/oc/integration/Mods.scala
@@ -21,6 +21,7 @@ object Mods {
val AppliedEnergistics2 = new SimpleMod(IDs.AppliedEnergistics2, version = "@[rv1,)", providesPower = true)
val BattleGear2 = new SimpleMod(IDs.BattleGear2)
+ val BloodMagic = new SimpleMod(IDs.BloodMagic)
val BuildCraft = new SimpleMod(IDs.BuildCraft)
val BuildCraftTiles = new SimpleMod(IDs.BuildCraftTiles)
val BuildCraftTools = new SimpleMod(IDs.BuildCraftTools)
@@ -71,37 +72,38 @@ object Mods {
// ----------------------------------------------------------------------- //
val Proxies = Array(
-// integration.appeng.ModAppEng,
-// integration.buildcraft.tools.ModBuildCraftAPITools,
-// integration.buildcraft.tiles.ModBuildCraftAPITiles,
-// integration.buildcraft.transport.ModBuildCraftAPITransport,
-// integration.cofh.energy.ModCoFHEnergy,
-// integration.cofh.item.ModCoFHItem,
-// integration.cofh.tileentity.ModCoFHTileEntity,
-// integration.cofh.transport.ModCoFHTransport,
-// integration.enderstorage.ModEnderStorage,
-// integration.forestry.ModForestry,
-// integration.fmp.ModForgeMultipart,
-// integration.gc.ModGalacticraft,
-// integration.gregtech.ModGregtech,
-// integration.ic2.ModIndustrialCraft2,
-// integration.mfr.ModMineFactoryReloaded,
-// integration.mystcraft.ModMystcraft,
-// integration.railcraft.ModRailcraft,
-// integration.stargatetech2.ModStargateTech2,
-// integration.thaumcraft.ModThaumcraft,
-// integration.thermalexpansion.ModThermalExpansion,
-// integration.tcon.ModTinkersConstruct,
-// integration.tmechworks.ModTMechworks,
+ // integration.appeng.ModAppEng,
+ // integration.bloodmagic.ModBloodMagic,
+ // integration.buildcraft.tools.ModBuildCraftAPITools,
+ // integration.buildcraft.tiles.ModBuildCraftAPITiles,
+ // integration.buildcraft.transport.ModBuildCraftAPITransport,
+ // integration.cofh.energy.ModCoFHEnergy,
+ // integration.cofh.item.ModCoFHItem,
+ // integration.cofh.tileentity.ModCoFHTileEntity,
+ // integration.cofh.transport.ModCoFHTransport,
+ // integration.enderstorage.ModEnderStorage,
+ // integration.forestry.ModForestry,
+ // integration.fmp.ModForgeMultipart,
+ // integration.gc.ModGalacticraft,
+ // integration.gregtech.ModGregtech,
+ // integration.ic2.ModIndustrialCraft2,
+ // integration.mfr.ModMineFactoryReloaded,
+ // integration.mystcraft.ModMystcraft,
+ // integration.railcraft.ModRailcraft,
+ // integration.stargatetech2.ModStargateTech2,
+ // integration.thaumcraft.ModThaumcraft,
+ // integration.thermalexpansion.ModThermalExpansion,
+ // integration.tcon.ModTinkersConstruct,
+ // integration.tmechworks.ModTMechworks,
integration.vanilla.ModVanilla,
-// integration.versionchecker.ModVersionChecker,
-// integration.waila.ModWaila,
-// integration.wrcbe.ModWRCBE,
-// integration.wrsve.ModWRSVE,
+ // integration.versionchecker.ModVersionChecker,
+ // integration.waila.ModWaila,
+ // integration.wrcbe.ModWRCBE,
+ // integration.wrsve.ModWRSVE,
-// // Register the general IPeripheral driver last, if at all, to avoid it
-// // being used rather than other more concrete implementations.
-// integration.computercraft.ModComputerCraft,
+ // // Register the general IPeripheral driver last, if at all, to avoid it
+ // // being used rather than other more concrete implementations.
+ // integration.computercraft.ModComputerCraft,
// We go last to ensure all other mod integration is done, e.g. to
// allow properly checking if wireless redstone is present.
@@ -111,7 +113,7 @@ object Mods {
def init(): Unit = {
for (proxy <- Proxies) {
tryInit(proxy)
- }
+ }
}
private def tryInit(mod: ModProxy) {
@@ -131,6 +133,7 @@ object Mods {
object IDs {
final val AppliedEnergistics2 = "appliedenergistics2"
final val BattleGear2 = "battlegear2"
+ final val BloodMagic = "AWWayofTime"
final val BuildCraft = "BuildCraft|Core"
final val BuildCraftPower = "BuildCraftAPI|power"
final val BuildCraftTiles = "BuildCraftAPI|tiles"
diff --git a/src/main/scala/li/cil/oc/integration/appeng/DriverController.scala b/src/main/scala/li/cil/oc/integration/appeng/DriverController.scala
index abe2a6180..c7698aec7 100644
--- a/src/main/scala/li/cil/oc/integration/appeng/DriverController.scala
+++ b/src/main/scala/li/cil/oc/integration/appeng/DriverController.scala
@@ -1,11 +1,15 @@
package li.cil.oc.integration.appeng
+import appeng.api.AEApi
import appeng.api.config.Actionable
import appeng.api.networking.crafting.ICraftingLink
import appeng.api.networking.crafting.ICraftingRequester
+import appeng.api.networking.security.IActionHost
import appeng.api.networking.security.MachineSource
import appeng.api.storage.data.IAEItemStack
import appeng.core.Api
+import appeng.me.helpers.IGridProxyable
+import appeng.tile.misc.TileInterface
import appeng.tile.networking.TileController
import appeng.util.item.AEItemStack
import com.google.common.collect.ImmutableSet
@@ -25,6 +29,7 @@ import li.cil.oc.util.ResultWrapper._
import net.minecraft.block.Block
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
+import net.minecraft.tileentity.TileEntity
import net.minecraft.world.World
import net.minecraftforge.common.DimensionManager
import net.minecraftforge.common.util.Constants.NBT
@@ -37,19 +42,30 @@ import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
object DriverController extends DriverTileEntity with EnvironmentAware {
- def getTileEntityClass = classOf[TileController]
+ private type AETile = TileEntity with IGridProxyable with IActionHost
+
+ def getTileEntityClass = {
+ if (AEApi.instance != null && AEApi.instance.blocks != null) {
+ if (AEApi.instance.blocks.blockController != null && AEApi.instance.blocks.blockController.item != null)
+ classOf[TileController]
+ else
+ classOf[TileInterface]
+ }
+ else null
+ }
def createEnvironment(world: World, x: Int, y: Int, z: Int): ManagedEnvironment =
- new Environment(world.getTileEntity(x, y, z).asInstanceOf[TileController])
+ new Environment(world.getTileEntity(x, y, z).asInstanceOf[AETile])
override def providedEnvironment(stack: ItemStack) =
if (stack != null &&
- Api.instance != null &&
- Api.instance.blocks != null &&
- Api.instance.blocks.blockController != null &&
- Block.getBlockFromItem(stack.getItem) == Api.instance.blocks.blockController.block) classOf[Environment] else null
+ AEApi.instance != null &&
+ AEApi.instance.blocks != null &&
+ AEApi.instance.blocks.blockController != null &&
+ Block.getBlockFromItem(stack.getItem) == AEApi.instance.blocks.blockController.block) classOf[Environment]
+ else null
- class Environment(tileEntity: TileController) extends ManagedTileEntityEnvironment[TileController](tileEntity, "me_controller") with NamedBlock {
+ class Environment(tileEntity: AETile) extends ManagedTileEntityEnvironment[AETile](tileEntity, "me_controller") with NamedBlock {
override def preferredName = "me_controller"
override def priority = 0
@@ -63,9 +79,17 @@ object DriverController extends DriverTileEntity with EnvironmentAware {
"busy" -> cpu.isBusy)))
@Callback(doc = "function():table -- Get a list of known item recipes. These can be used to issue crafting requests.")
- def getCraftables(context: Context, args: Arguments): Array[AnyRef] =
+ def getCraftables(context: Context, args: Arguments): Array[AnyRef] = {
result(tileEntity.getProxy.getStorage.getItemInventory.getStorageList.
- filter(_.isCraftable).map(new Craftable(tileEntity, _)).toArray)
+ filter(_.isCraftable).map(stack => {
+ val patterns = tileEntity.getProxy.getCrafting.getCraftingFor(stack, null, 0, tileEntity.getWorldObj)
+ val result = patterns.find(pattern => pattern.getOutputs.exists(_.isSameType(stack))) match {
+ case Some(pattern) => pattern.getOutputs.find(_.isSameType(stack)).get
+ case _ => stack.copy.setStackSize(0) // Should not be possible, but hey...
+ }
+ new Craftable(tileEntity, result)
+ }).toArray)
+ }
@Callback(doc = "function():table -- Get a list of the stored items in the network.")
def getItemsInNetwork(context: Context, args: Arguments): Array[AnyRef] =
@@ -96,7 +120,7 @@ object DriverController extends DriverTileEntity with EnvironmentAware {
result(tileEntity.getProxy.getEnergy.getStoredPower)
}
- class Craftable(var controller: TileController, var stack: IAEItemStack) extends AbstractValue with ICraftingRequester {
+ class Craftable(var controller: AETile, var stack: IAEItemStack) extends AbstractValue with ICraftingRequester {
def this() = this(null, null)
private val links = mutable.Set.empty[ICraftingLink]
@@ -180,8 +204,8 @@ object DriverController extends DriverTileEntity with EnvironmentAware {
EventHandler.schedule(() => {
val world = DimensionManager.getWorld(dimension)
val tileEntity = world.getTileEntity(x, y, z)
- if (tileEntity != null && tileEntity.isInstanceOf[TileController]) {
- controller = tileEntity.asInstanceOf[TileController]
+ if (tileEntity != null && tileEntity.isInstanceOf[AETile]) {
+ controller = tileEntity.asInstanceOf[AETile]
}
})
}
diff --git a/src/main/scala/li/cil/oc/integration/bloodmagic/ConverterBloodOrb.java b/src/main/scala/li/cil/oc/integration/bloodmagic/ConverterBloodOrb.java
new file mode 100644
index 000000000..7d33b3dce
--- /dev/null
+++ b/src/main/scala/li/cil/oc/integration/bloodmagic/ConverterBloodOrb.java
@@ -0,0 +1,30 @@
+package li.cil.oc.integration.bloodmagic;
+
+import WayofTime.alchemicalWizardry.api.items.interfaces.IBloodOrb;
+import WayofTime.alchemicalWizardry.api.soulNetwork.SoulNetworkHandler;
+import li.cil.oc.api.driver.Converter;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+
+import java.util.Map;
+
+public class ConverterBloodOrb implements Converter {
+ @Override
+ public void convert(Object value, Map