mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-26 22:43:40 -04:00
Merge branch 'master' of https://github.com/MightyPirates/OpenComputers into MC1.7
Conflicts: src/main/scala/li/cil/oc/client/Proxy.scala src/main/scala/li/cil/oc/client/renderer/tileentity/RobotRenderer.scala src/main/scala/li/cil/oc/common/PacketBuilder.scala src/main/scala/li/cil/oc/common/block/Hologram.scala src/main/scala/li/cil/oc/common/tileentity/DiskDrive.scala src/main/scala/li/cil/oc/common/tileentity/Robot.scala src/main/scala/li/cil/oc/server/component/FileSystem.scala
This commit is contained in:
commit
2b5294821d
17
LICENSE
17
LICENSE
@ -21,6 +21,19 @@ THE SOFTWARE.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
All images / textures and localization strings (resources) are put in the
|
||||
public domain. More specicially, see CC0 1.0 Universal:
|
||||
public domain, unless explicitly excluded below. More specicially, see CC0 1.0
|
||||
Universal:
|
||||
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
Contributions:
|
||||
PixelToast - Capacitor textures.
|
||||
asie - Disk drive inject/eject and floppy disk access sound samples.
|
||||
|
||||
Thanks a lot!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Assets from other sources:
|
||||
HDD access samples based on this sample from freesound.org:
|
||||
https://www.freesound.org/people/artykris/sounds/117401/
|
||||
|
@ -12,7 +12,7 @@ If you'd like to contribute code, please have a look at the [code conventions](h
|
||||
|
||||
If you encounter any bugs, please report them [in the issue tracker](https://github.com/MightyPirates/OpenComputers/issues?state=open), if they have not already been reported. If you report a crash, always provide your log file.
|
||||
|
||||
If you wish to discuss or suggest a new feature, the [forums](http://oc.cil.li//index.php?/forum/22-feedback-and-suggestions/) are a good place for that.
|
||||
If you wish to discuss or suggest a new feature, the [forums](http://oc.cil.li/forums/viewforum.php?f=11) are a good place for that.
|
||||
|
||||
Extending
|
||||
---------
|
||||
|
@ -6,6 +6,7 @@ import dan200.computer.api.IWritableMount;
|
||||
import li.cil.oc.api.detail.FileSystemAPI;
|
||||
import li.cil.oc.api.fs.Label;
|
||||
import li.cil.oc.api.network.ManagedEnvironment;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
||||
/**
|
||||
* This class provides factory methods for creating file systems that are
|
||||
@ -46,7 +47,8 @@ public final class FileSystem {
|
||||
* @return a file system wrapping the specified folder.
|
||||
*/
|
||||
public static li.cil.oc.api.fs.FileSystem fromClass(final Class<?> clazz, final String domain, final String root) {
|
||||
if (instance != null) return instance.fromClass(clazz, domain, root);
|
||||
if (instance != null)
|
||||
return instance.fromClass(clazz, domain, root);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -74,7 +76,8 @@ public final class FileSystem {
|
||||
* @return a file system wrapping the specified folder.
|
||||
*/
|
||||
public static li.cil.oc.api.fs.FileSystem fromSaveDirectory(final String root, final long capacity, final boolean buffered) {
|
||||
if (instance != null) return instance.fromSaveDirectory(root, capacity, buffered);
|
||||
if (instance != null)
|
||||
return instance.fromSaveDirectory(root, capacity, buffered);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -103,7 +106,8 @@ public final class FileSystem {
|
||||
* @return a file system residing in memory.
|
||||
*/
|
||||
public static li.cil.oc.api.fs.FileSystem fromMemory(final long capacity) {
|
||||
if (instance != null) return instance.fromMemory(capacity);
|
||||
if (instance != null)
|
||||
return instance.fromMemory(capacity);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -115,7 +119,8 @@ public final class FileSystem {
|
||||
*/
|
||||
@Optional.Method(modid = "ComputerCraft")
|
||||
public static li.cil.oc.api.fs.FileSystem fromComputerCraft(final IMount mount) {
|
||||
if (instance != null) return instance.fromComputerCraft(mount);
|
||||
if (instance != null)
|
||||
return instance.fromComputerCraft(mount);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -127,7 +132,8 @@ public final class FileSystem {
|
||||
*/
|
||||
@Optional.Method(modid = "ComputerCraft")
|
||||
public static li.cil.oc.api.fs.FileSystem fromComputerCraft(final IWritableMount mount) {
|
||||
if (instance != null) return instance.fromComputerCraft(mount);
|
||||
if (instance != null)
|
||||
return instance.fromComputerCraft(mount);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -140,13 +146,36 @@ public final class FileSystem {
|
||||
* more control over the node, implement your own, and connect this one to
|
||||
* it. In that case you will have to forward any disk driver messages to the
|
||||
* node, though.
|
||||
* <p/>
|
||||
* The container parameter is used to give the file system some physical
|
||||
* relation to the world, for example this is used by hard drives to send
|
||||
* the disk event notifications to the client that are used to play disk
|
||||
* access sounds.
|
||||
* <p/>
|
||||
* The container may be <tt>null</tt>, if no such context can be provided.
|
||||
*
|
||||
* @param fileSystem the file system to wrap.
|
||||
* @param label the label of the file system.
|
||||
* @param container the tile entity containing the file system.
|
||||
* @return the network node wrapping the file system.
|
||||
*/
|
||||
public static ManagedEnvironment asManagedEnvironment(final li.cil.oc.api.fs.FileSystem fileSystem, final Label label, final TileEntity container) {
|
||||
if (instance != null)
|
||||
return instance.asManagedEnvironment(fileSystem, label, container);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #asManagedEnvironment(li.cil.oc.api.fs.FileSystem, Label, TileEntity)},
|
||||
* but does not provide a container.
|
||||
*
|
||||
* @param fileSystem the file system to wrap.
|
||||
* @param label the label of the file system.
|
||||
* @return the network node wrapping the file system.
|
||||
*/
|
||||
public static ManagedEnvironment asManagedEnvironment(final li.cil.oc.api.fs.FileSystem fileSystem, final Label label) {
|
||||
if (instance != null) return instance.asManagedEnvironment(fileSystem, label);
|
||||
if (instance != null)
|
||||
return instance.asManagedEnvironment(fileSystem, label);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -159,7 +188,8 @@ public final class FileSystem {
|
||||
* @return the network node wrapping the file system.
|
||||
*/
|
||||
public static ManagedEnvironment asManagedEnvironment(final li.cil.oc.api.fs.FileSystem fileSystem, final String label) {
|
||||
if (instance != null) return instance.asManagedEnvironment(fileSystem, label);
|
||||
if (instance != null)
|
||||
return instance.asManagedEnvironment(fileSystem, label);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -172,7 +202,8 @@ public final class FileSystem {
|
||||
* @return the network node wrapping the file system.
|
||||
*/
|
||||
public static ManagedEnvironment asManagedEnvironment(final li.cil.oc.api.fs.FileSystem fileSystem) {
|
||||
if (instance != null) return instance.asManagedEnvironment(fileSystem);
|
||||
if (instance != null)
|
||||
return instance.asManagedEnvironment(fileSystem);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import dan200.computer.api.IWritableMount;
|
||||
import li.cil.oc.api.fs.FileSystem;
|
||||
import li.cil.oc.api.fs.Label;
|
||||
import li.cil.oc.api.network.ManagedEnvironment;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
||||
public interface FileSystemAPI {
|
||||
/**
|
||||
@ -96,6 +97,24 @@ public interface FileSystemAPI {
|
||||
* more control over the node, implement your own, and connect this one to
|
||||
* it. In that case you will have to forward any disk driver messages to the
|
||||
* node, though.
|
||||
* <p/>
|
||||
* The container parameter is used to give the file system some physical
|
||||
* relation to the world, for example this is used by hard drives to send
|
||||
* the disk event notifications to the client that are used to play disk
|
||||
* access sounds.
|
||||
* <p/>
|
||||
* The container may be <tt>null</tt>, if no such context can be provided.
|
||||
*
|
||||
* @param fileSystem the file system to wrap.
|
||||
* @param label the label of the file system.
|
||||
* @param container the tile entity containing the file system.
|
||||
* @return the network node wrapping the file system.
|
||||
*/
|
||||
ManagedEnvironment asManagedEnvironment(FileSystem fileSystem, Label label, TileEntity container);
|
||||
|
||||
/**
|
||||
* Like {@link #asManagedEnvironment(li.cil.oc.api.fs.FileSystem, Label, TileEntity)},
|
||||
* but does not provide a container.
|
||||
*
|
||||
* @param fileSystem the file system to wrap.
|
||||
* @param label the label of the file system.
|
||||
|
@ -37,5 +37,5 @@
|
||||
@cpw.mods.fml.common.API(
|
||||
owner = "OpenComputers|Core",
|
||||
provides = "OpenComputersAPI",
|
||||
apiVersion = "1.4.4")
|
||||
apiVersion = "1.4.5")
|
||||
package li.cil.oc.api;
|
@ -173,4 +173,4 @@ oc:tooltip.UpgradeNavigation=Erlaubt es Robotern, ihre Position und Ausrichtung
|
||||
oc:tooltip.UpgradeSign=Erlaubt das Lesen und Schreiben von Text auf Schildern.
|
||||
oc:tooltip.UpgradeSolarGenerator=Kann verwendet werden, um unterwegs Energie aus Sonnenlicht zu generieren. Benötigt eine ungehinderte Sicht zum Himmel über dem Roboter. Generiert Energie mit %s%% der Geschwindigkeit eines Stirlingmotors.
|
||||
oc:tooltip.WirelessNetworkCard=Erlaubt das drahtlose Senden von Netzwerknachrichten, zusätzlich zu normalen. Drahtlose Nachrichten werden nur gesendet, wenn eine §fSignalstärke§7 festgelegt wurde!
|
||||
oc:tooltip.WirelessRouter=Verhält sich wie ein Switch, aber empfängt zusätzlich Drahtlosnachrichten, und leitet Pakete aus dem Festnetz drahtlos weiter.
|
||||
oc:tooltip.WirelessRouter=Verhält sich wie ein Switch, aber empfängt zusätzlich Drahtlosnachrichten und leitet Pakete aus dem Festnetz drahtlos weiter.
|
||||
|
@ -76,6 +76,7 @@ local ignore = {
|
||||
|
||||
-- command numbers to names.
|
||||
local commands = {
|
||||
--Replys
|
||||
RPL_WELCOME = "001",
|
||||
RPL_YOURHOST = "002",
|
||||
RPL_CREATED = "003",
|
||||
@ -102,7 +103,32 @@ local commands = {
|
||||
RPL_ENDOFNAMES = "366",
|
||||
RPL_MOTDSTART = "375",
|
||||
RPL_MOTD = "372",
|
||||
RPL_ENDOFMOTD = "376"
|
||||
RPL_ENDOFMOTD = "376",
|
||||
RPL_WHOISSECURE = "671",
|
||||
RPL_HELPSTART = "704",
|
||||
RPL_HELPTXT = "705",
|
||||
RPL_ENDOFHELP = "706",
|
||||
RPL_UMODEGMSG = "718",
|
||||
|
||||
--Errors
|
||||
ERR_BANLISTFULL = "478",
|
||||
ERR_CHANNELISFULL = "471",
|
||||
ERR_UNKNOWNMODE = "472",
|
||||
ERR_INVITEONLYCHAN = "473",
|
||||
ERR_BANNEDFROMCHAN = "474",
|
||||
ERR_CHANOPRIVSNEEDED = "482",
|
||||
ERR_UNIQOPRIVSNEEDED = "485",
|
||||
ERR_USERNOTINCHANNEL = "441",
|
||||
ERR_NOTONCHANNEL = "442",
|
||||
ERR_NICKCOLLISION = "436",
|
||||
ERR_NICKNAMEINUSE = "433",
|
||||
ERR_ERRONEUSNICKNAME = "432",
|
||||
ERR_WASNOSUCHNICK = "406",
|
||||
ERR_TOOMANYCHANNELS = "405",
|
||||
ERR_CANNOTSENDTOCHAN = "404",
|
||||
ERR_NOSUCHCHANNEL = "403",
|
||||
ERR_NOSUCHNICK = "401",
|
||||
ERR_MODELOCK = "742"
|
||||
}
|
||||
|
||||
-- main command handling callback.
|
||||
@ -116,7 +142,6 @@ local function handleCommand(prefix, command, args, message)
|
||||
|
||||
---------------------------------------------------
|
||||
-- General commands
|
||||
|
||||
elseif command == "NICK" then
|
||||
print(name(prefix) .. " is now known as " .. tostring(args[1] or message) .. ".")
|
||||
elseif command == "MODE" then
|
||||
@ -132,6 +157,16 @@ local function handleCommand(prefix, command, args, message)
|
||||
elseif command == "KICK" then
|
||||
print("[" .. args[1] .. "] " .. name(prefix) .. " kicked " .. args[2])
|
||||
elseif command == "PRIVMSG" then
|
||||
if string.find(message, "\001TIME\001") then
|
||||
sock:write("NOTICE " .. name(prefix) .. " :\001TIME " .. os.date() .. "\001\r\n")
|
||||
sock:flush()
|
||||
elseif string.find(message, "\001VERSION\001") then
|
||||
sock:write("NOTICE " .. name(prefix) .. " :\001VERSION Minecraft/OpenComputers Lua 5.2\001\r\n")
|
||||
sock:flush()
|
||||
elseif string.find(message, "\001PING") then
|
||||
sock:write("NOTICE " .. name(prefix) .. " :" .. message .. "\001\r\n")
|
||||
sock:flush()
|
||||
end
|
||||
print("[" .. args[1] .. "] " .. name(prefix) .. ": " .. message)
|
||||
elseif command == "NOTICE" then
|
||||
print("[NOTICE] " .. message)
|
||||
@ -182,6 +217,9 @@ local function handleCommand(prefix, command, args, message)
|
||||
elseif command == commands.RPL_WHOISIDLE then
|
||||
local nick = args[2]:lower()
|
||||
whois[nick].idle = tonumber(args[3])
|
||||
elseif command == commands.RPL_WHOISSECURE then
|
||||
local nick = args[2]:lower()
|
||||
whois[nick].secureconn = "Is using a secure connection"
|
||||
elseif command == commands.RPL_ENDOFWHOIS then
|
||||
local nick = args[2]:lower()
|
||||
local info = whois[nick]
|
||||
@ -190,6 +228,7 @@ local function handleCommand(prefix, command, args, message)
|
||||
if info.realName then print("Real name: " .. info.realName) end
|
||||
if info.host then print("Host: " .. info.host) end
|
||||
if info.server then print("Server: " .. info.server .. (info.serverInfo and (" (" .. info.serverInfo .. ")") or "")) end
|
||||
if info.secureconn then print(info.secureconn) end
|
||||
if info.channels then print("Channels: " .. info.channels) end
|
||||
if info.idle then print("Idle for: " .. info.idle) end
|
||||
whois[nick] = nil
|
||||
@ -218,6 +257,26 @@ local function handleCommand(prefix, command, args, message)
|
||||
print(message)
|
||||
end
|
||||
elseif command == commands.RPL_ENDOFMOTD then -- ignore
|
||||
elseif command == commands.RPL_HELPSTART or
|
||||
command == commands.RPL_HELPTXT or
|
||||
command == commands.RPL_ENDOFHELP then
|
||||
print(message)
|
||||
elseif command == commands.ERR_BANLISTFULL or
|
||||
command == commands.ERR_BANNEDFROMCHAN or
|
||||
command == commands.ERR_CANNOTSENDTOCHAN or
|
||||
command == commands.ERR_CHANNELISFULL or
|
||||
command == commands.ERR_CHANOPRIVSNEEDED or
|
||||
command == commands.ERR_ERRONEUSNICKNAME or
|
||||
command == commands.ERR_INVITEONLYCHAN or
|
||||
command == commands.ERR_NICKCOLLISION or
|
||||
command == commands.ERR_NOSUCHNICK or
|
||||
command == commands.ERR_NOTONCHANNEL or
|
||||
command == commands.ERR_UNIQOPRIVSNEEDED or
|
||||
command == commands.ERR_UNKNOWNMODE or
|
||||
command == commands.ERR_USERNOTINCHANNEL or
|
||||
command == commands.ERR_WASNOSUCHNICK or
|
||||
command == commands.ERR_MODELOCK then
|
||||
print("[ERROR]: " .. message)
|
||||
elseif tonumber(command) and (tonumber(command) >= 200 and tonumber(command) < 400) then
|
||||
print("[Response " .. command .. "] " .. table.concat(args, ", ") .. ": " .. message)
|
||||
|
||||
@ -232,7 +291,7 @@ local function handleCommand(prefix, command, args, message)
|
||||
-- Unhandled message.
|
||||
|
||||
else
|
||||
print("Unhandled command: " .. command)
|
||||
print("Unhandled command: " .. command .. ": " .. message)
|
||||
end
|
||||
end
|
||||
|
||||
@ -373,4 +432,4 @@ end
|
||||
if not result then
|
||||
error(reason, 0)
|
||||
end
|
||||
return reason
|
||||
return reason
|
||||
|
30
src/main/resources/assets/opencomputers/robot.names
Normal file
30
src/main/resources/assets/opencomputers/robot.names
Normal file
@ -0,0 +1,30 @@
|
||||
# This a list of names that robots are randomly named after, unless
|
||||
# explicitly named using an anvil.
|
||||
# If your name is on this list and you'd rather it not be, or you'd like a
|
||||
# different alias, sorry! Please make a pull request with the changed list.
|
||||
asie
|
||||
crafteverywhere
|
||||
LordFokas
|
||||
Michiyo
|
||||
mymagadsl
|
||||
PixelToast
|
||||
Pyrolusite
|
||||
SpiritedDusty
|
||||
Vexatos
|
||||
Wobbo
|
||||
YuRaNnNzZZ
|
||||
|
||||
# Names of more or less famous robots, as a bit of filler material. Feel free
|
||||
# to add more via pull requests. Let's hope this won't get us sued...
|
||||
Atlas
|
||||
Bender
|
||||
C-3PO
|
||||
Clank
|
||||
Claptrap
|
||||
Dog
|
||||
GLaDOS
|
||||
KITT
|
||||
Marvin
|
||||
P-Body
|
||||
R2-D2
|
||||
Wheatley
|
33
src/main/resources/assets/opencomputers/sounds.json
Normal file
33
src/main/resources/assets/opencomputers/sounds.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"floppy_access": {
|
||||
"category": "master",
|
||||
"sounds": [
|
||||
{"name": "floppy_access1", "stream": false},
|
||||
{"name": "floppy_access2", "stream": false},
|
||||
{"name": "floppy_access3", "stream": false},
|
||||
{"name": "floppy_access4", "stream": false},
|
||||
{"name": "floppy_access5", "stream": false},
|
||||
{"name": "floppy_access6", "stream": false}
|
||||
]
|
||||
},
|
||||
"floppy_eject": {
|
||||
"category": "master",
|
||||
"sounds": [{"name": "floppy_eject", "stream": false}]
|
||||
},
|
||||
"floppy_insert": {
|
||||
"category": "master",
|
||||
"sounds": [{"name": "floppy_insert", "stream": false}]
|
||||
},
|
||||
"hdd_access": {
|
||||
"category": "master",
|
||||
"sounds": [
|
||||
{"name": "hdd_access1", "stream": false},
|
||||
{"name": "hdd_access2", "stream": false},
|
||||
{"name": "hdd_access3", "stream": false},
|
||||
{"name": "hdd_access4", "stream": false},
|
||||
{"name": "hdd_access5", "stream": false},
|
||||
{"name": "hdd_access6", "stream": false},
|
||||
{"name": "hdd_access7", "stream": false}
|
||||
]
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/assets/opencomputers/sounds/floppy_eject.ogg
Normal file
BIN
src/main/resources/assets/opencomputers/sounds/floppy_eject.ogg
Normal file
Binary file not shown.
BIN
src/main/resources/assets/opencomputers/sounds/floppy_insert.ogg
Normal file
BIN
src/main/resources/assets/opencomputers/sounds/floppy_insert.ogg
Normal file
Binary file not shown.
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access1.ogg
Normal file
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access1.ogg
Normal file
Binary file not shown.
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access2.ogg
Normal file
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access2.ogg
Normal file
Binary file not shown.
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access3.ogg
Normal file
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access3.ogg
Normal file
Binary file not shown.
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access4.ogg
Normal file
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access4.ogg
Normal file
Binary file not shown.
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access5.ogg
Normal file
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access5.ogg
Normal file
Binary file not shown.
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access6.ogg
Normal file
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access6.ogg
Normal file
Binary file not shown.
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access7.ogg
Normal file
BIN
src/main/resources/assets/opencomputers/sounds/hdd_access7.ogg
Normal file
Binary file not shown.
@ -39,6 +39,9 @@ opencomputers {
|
||||
# attached to it). For valid key names, please see the following list:
|
||||
# https://github.com/LWJGL/lwjgl/blob/master/src/java/org/lwjgl/input/Keyboard.java#L73
|
||||
pasteShortcut: [LSHIFT, INSERT]
|
||||
|
||||
# Render robots' names as a label above them when near them
|
||||
robotLabels: true
|
||||
}
|
||||
|
||||
# Computer related settings, concerns server performance and security.
|
||||
|
@ -16,6 +16,7 @@ class Settings(config: Config) {
|
||||
val textLinearFiltering = config.getBoolean("client.textLinearFiltering")
|
||||
val textAntiAlias = config.getBoolean("client.textAntiAlias")
|
||||
val pasteShortcut = config.getStringList("client.pasteShortcut").toSet
|
||||
val robotLabels = config.getBoolean("client.robotLabels")
|
||||
val rTreeDebugRenderer = false // *Not* to be configurable via config file.
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
@ -9,8 +9,7 @@ import li.cil.oc.client.renderer.block.BlockRenderer
|
||||
import li.cil.oc.client.renderer.item.UpgradeRenderer
|
||||
import li.cil.oc.client.renderer.tileentity._
|
||||
import li.cil.oc.client.renderer.WirelessNetworkDebugRenderer
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.common.{Proxy => CommonProxy}
|
||||
import li.cil.oc.common.{Proxy => CommonProxy, Sound, tileentity}
|
||||
import li.cil.oc.{Items, Settings, OpenComputers}
|
||||
import net.minecraftforge.client.MinecraftForgeClient
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
@ -19,6 +18,7 @@ private[oc] class Proxy extends CommonProxy {
|
||||
override def preInit(e: FMLPreInitializationEvent) {
|
||||
super.preInit(e)
|
||||
|
||||
MinecraftForge.EVENT_BUS.register(Sound)
|
||||
MinecraftForge.EVENT_BUS.register(gui.Icons)
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
package li.cil.oc.client.renderer.tileentity
|
||||
|
||||
import java.util.logging.Level
|
||||
import li.cil.oc.OpenComputers
|
||||
import li.cil.oc.{Settings, OpenComputers}
|
||||
import li.cil.oc.client.Textures
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.util.RenderState
|
||||
import net.minecraft.client.renderer.entity.RenderManager
|
||||
import net.minecraft.client.renderer.entity.{RendererLivingEntity, RenderManager}
|
||||
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
|
||||
import net.minecraft.client.renderer.{Tessellator, GLAllocation}
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
@ -175,6 +175,51 @@ object RobotRenderer extends TileEntitySpecialRenderer {
|
||||
GL11.glPushMatrix()
|
||||
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
|
||||
|
||||
val name = robot.name
|
||||
if (Settings.get.robotLabels && name != null && x * x + y * y + z * z < RendererLivingEntity.NAME_TAG_RANGE) {
|
||||
GL11.glPushMatrix()
|
||||
|
||||
// This is pretty much copy-pasta from the entity's label renderer.
|
||||
val t = Tessellator.instance
|
||||
val f = func_147498_b
|
||||
val scale = 1.6f / 60f
|
||||
val width = f.getStringWidth(name)
|
||||
|
||||
GL11.glTranslated(0, 0.7, 0)
|
||||
GL11.glNormal3f(0, 1, 0)
|
||||
|
||||
GL11.glRotatef(-field_147501_a.field_147562_h, 0, 1, 0)
|
||||
GL11.glRotatef(field_147501_a.field_147563_i, 1, 0, 0)
|
||||
GL11.glScalef(-scale, -scale, scale)
|
||||
|
||||
GL11.glDisable(GL11.GL_LIGHTING)
|
||||
GL11.glDepthMask(false)
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST)
|
||||
GL11.glEnable(GL11.GL_BLEND)
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D)
|
||||
t.startDrawingQuads()
|
||||
val halfWidth = width / 2
|
||||
t.setColorRGBA_F(0, 0, 0, 0.25f)
|
||||
t.addVertex(-halfWidth - 1, -1, 0)
|
||||
t.addVertex(-halfWidth - 1, 8, 0)
|
||||
t.addVertex(halfWidth + 1, 8, 0)
|
||||
t.addVertex(halfWidth + 1, -1, 0)
|
||||
t.draw
|
||||
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D)
|
||||
f.drawString(name, -halfWidth, 0, 0x20FFFFFF)
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST)
|
||||
GL11.glDepthMask(true)
|
||||
f.drawString(name, -halfWidth, 0, -1)
|
||||
GL11.glEnable(GL11.GL_LIGHTING)
|
||||
GL11.glDisable(GL11.GL_BLEND)
|
||||
GL11.glColor4f(1, 1, 1, 1)
|
||||
|
||||
GL11.glPopMatrix()
|
||||
}
|
||||
|
||||
// If the move started while we were rendering and we have a reference to
|
||||
// the *old* proxy the robot would be rendered at the wrong position, so we
|
||||
// correct for the offset.
|
||||
|
@ -5,11 +5,11 @@ import cpw.mods.fml.common.network.internal.FMLProxyPacket
|
||||
import io.netty.buffer.Unpooled
|
||||
import java.io.{OutputStream, ByteArrayOutputStream, DataOutputStream}
|
||||
import java.util.zip.GZIPOutputStream
|
||||
import li.cil.oc.common.tileentity.TileEntity
|
||||
import li.cil.oc.OpenComputers
|
||||
import net.minecraft.entity.player.EntityPlayerMP
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.{CompressedStreamTools, NBTTagCompound}
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
@ -17,10 +17,10 @@ import scala.collection.convert.WrapAsScala._
|
||||
// Necessary to keep track of the GZIP stream.
|
||||
abstract class PacketBuilderBase[T <: OutputStream](protected val stream: T) extends DataOutputStream(stream) {
|
||||
def writeTileEntity(t: TileEntity) = {
|
||||
writeInt(t.world.provider.dimensionId)
|
||||
writeInt(t.x)
|
||||
writeInt(t.y)
|
||||
writeInt(t.z)
|
||||
writeInt(t.getWorldObj.provider.dimensionId)
|
||||
writeInt(t.xCoord)
|
||||
writeInt(t.yCoord)
|
||||
writeInt(t.zCoord)
|
||||
}
|
||||
|
||||
def writeDirection(d: ForgeDirection) = writeInt(d.ordinal)
|
||||
@ -37,7 +37,7 @@ abstract class PacketBuilderBase[T <: OutputStream](protected val stream: T) ext
|
||||
|
||||
def sendToAllPlayers() = OpenComputers.channel.sendToAll(packet)
|
||||
|
||||
def sendToNearbyPlayers(t: TileEntity, range: Double = 1024): Unit = sendToNearbyPlayers(t.world, t.x + 0.5, t.y + 0.5, t.z + 0.5, range)
|
||||
def sendToNearbyPlayers(t: TileEntity, range: Double = 1024): Unit = sendToNearbyPlayers(t.getWorldObj, t.xCoord + 0.5, t.yCoord + 0.5, t.zCoord + 0.5, range)
|
||||
|
||||
def sendToNearbyPlayers(world: World, x: Double, y: Double, z: Double, range: Double) {
|
||||
val dimension = world.provider.dimensionId
|
||||
|
39
src/main/scala/li/cil/oc/common/Sound.scala
Normal file
39
src/main/scala/li/cil/oc/common/Sound.scala
Normal file
@ -0,0 +1,39 @@
|
||||
package li.cil.oc.common
|
||||
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import li.cil.oc.Settings
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraftforge.client.event.sound.SoundLoadEvent
|
||||
import scala.collection.mutable
|
||||
|
||||
object Sound {
|
||||
val lastPlayed = mutable.WeakHashMap.empty[TileEntity, Long]
|
||||
|
||||
def play(t: tileentity.TileEntity, name: String) {
|
||||
t.world.playSoundEffect(t.x + 0.5, t.y + 0.5, t.z + 0.5, Settings.resourceDomain + ":" + name, 1, 1)
|
||||
}
|
||||
|
||||
def playDiskInsert(t: tileentity.DiskDrive) {
|
||||
play(t, "floppy_insert")
|
||||
}
|
||||
|
||||
def playDiskEject(t: tileentity.DiskDrive) {
|
||||
play(t, "floppy_eject")
|
||||
}
|
||||
|
||||
def playDiskActivity(t: TileEntity) = this.synchronized {
|
||||
lastPlayed.get(t) match {
|
||||
case Some(time) if time > System.currentTimeMillis() => // Cooldown.
|
||||
case _ =>
|
||||
t match {
|
||||
case computer: tileentity.Computer => play(computer, "hdd_access")
|
||||
case rack: tileentity.Rack => play(rack, "hdd_access")
|
||||
case drive: tileentity.DiskDrive => play(drive, "floppy_access")
|
||||
case _ => // Huh?
|
||||
}
|
||||
lastPlayed += t -> (System.currentTimeMillis() + 500)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -10,6 +10,7 @@ import net.minecraft.item.{ItemStack, EnumRarity}
|
||||
import net.minecraft.world.{World, IBlockAccess}
|
||||
import net.minecraft.util.{IIcon, AxisAlignedBB}
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
import cpw.mods.fml.relauncher.{SideOnly, Side}
|
||||
|
||||
class Hologram(val parent: SpecialDelegator) extends SpecialDelegate {
|
||||
val unlocalizedName = "Hologram"
|
||||
@ -28,6 +29,11 @@ class Hologram(val parent: SpecialDelegator) extends SpecialDelegate {
|
||||
|
||||
override def isSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = side == ForgeDirection.DOWN
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def shouldSideBeRendered(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = {
|
||||
super.shouldSideBeRendered(world, x, y, z, side) || side == ForgeDirection.UP
|
||||
}
|
||||
|
||||
override def bounds(world: IBlockAccess, x: Int, y: Int, z: Int) =
|
||||
AxisAlignedBB.getAABBPool.getAABB(0, 0, 0, 1, 3 / 16f, 1)
|
||||
|
||||
|
@ -3,6 +3,7 @@ package li.cil.oc.common.tileentity
|
||||
import li.cil.oc.api.driver.Slot
|
||||
import li.cil.oc.api.network.{Analyzable, Component, Visibility}
|
||||
import li.cil.oc.common.EventHandler
|
||||
import li.cil.oc.common.Sound
|
||||
import li.cil.oc.server.driver.Registry
|
||||
import li.cil.oc.{api, Settings}
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
@ -45,5 +46,11 @@ class DiskDrive extends Environment with ComponentInventory with Rotatable with
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
Sound.playDiskInsert(this)
|
||||
}
|
||||
|
||||
override protected def onItemRemoved(slot: Int, stack: ItemStack) {
|
||||
super.onItemRemoved(slot, stack)
|
||||
Sound.playDiskEject(this)
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import li.cil.oc.server.component.robot
|
||||
import li.cil.oc.server.driver.Registry
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender, driver, component}
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
import li.cil.oc.{Blocks, Settings, api, common}
|
||||
import li.cil.oc._
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
@ -18,6 +18,9 @@ import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.ChatComponentTranslation
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
import scala.io.Source
|
||||
import scala.Some
|
||||
import java.util.logging.Level
|
||||
|
||||
// Implementation note: this tile entity is never directly added to the world.
|
||||
// It is always wrapped by a `RobotProxy` tile entity, which forwards any
|
||||
@ -27,6 +30,7 @@ import net.minecraftforge.common.util.ForgeDirection
|
||||
// old proxy, which will be cleaned up by Minecraft like any other tile entity.
|
||||
class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory with Buffer with PowerInformation with api.machine.Robot {
|
||||
def this() = this(false)
|
||||
|
||||
if (isServer) {
|
||||
computer.setCostPerTick(Settings.get.robotCost)
|
||||
}
|
||||
@ -42,6 +46,16 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
|
||||
override def player() = player(facing, facing)
|
||||
|
||||
def name: String = {
|
||||
if (tag != null && tag.hasKey("display")) {
|
||||
val display = tag.getCompoundTag("display")
|
||||
if (display != null && display.hasKey("Name")) {
|
||||
return display.getString("Name")
|
||||
}
|
||||
}
|
||||
null
|
||||
}
|
||||
|
||||
override def saveUpgrade() = this.synchronized {
|
||||
components(3) match {
|
||||
case Some(environment) =>
|
||||
@ -76,6 +90,8 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
|
||||
var owner = "OpenComputers"
|
||||
|
||||
var tag: NBTTagCompound = _
|
||||
|
||||
var xp = 0.0
|
||||
|
||||
def xpForNextLevel = xpForLevel(level + 1)
|
||||
@ -198,24 +214,30 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
|
||||
def createItemStack() = {
|
||||
val stack = Blocks.robotProxy.createItemStack()
|
||||
if (globalBuffer > 1 || xp > 0) {
|
||||
stack.setTagCompound(new NBTTagCompound())
|
||||
}
|
||||
val tag = if (this.tag != null) this.tag.copy.asInstanceOf[NBTTagCompound] else new NBTTagCompound()
|
||||
stack.setTagCompound(tag)
|
||||
if (xp > 0) {
|
||||
stack.getTagCompound.setDouble(Settings.namespace + "xp", xp)
|
||||
tag.setDouble(Settings.namespace + "xp", xp)
|
||||
}
|
||||
if (globalBuffer > 1) {
|
||||
stack.getTagCompound.setInteger(Settings.namespace + "storedEnergy", globalBuffer.toInt)
|
||||
tag.setInteger(Settings.namespace + "storedEnergy", globalBuffer.toInt)
|
||||
}
|
||||
stack
|
||||
}
|
||||
|
||||
def parseItemStack(stack: ItemStack) {
|
||||
if (stack.hasTagCompound) {
|
||||
xp = stack.getTagCompound.getDouble(Settings.namespace + "xp")
|
||||
tag = stack.getTagCompound.copy.asInstanceOf[NBTTagCompound]
|
||||
xp = tag.getDouble(Settings.namespace + "xp")
|
||||
updateXpInfo()
|
||||
bot.node.changeBuffer(stack.getTagCompound.getInteger(Settings.namespace + "storedEnergy"))
|
||||
}
|
||||
else {
|
||||
tag = new NBTTagCompound()
|
||||
}
|
||||
if (name == null) {
|
||||
tag.setNewCompoundTag("display", tag => tag.setString("Name", Robot.randomName))
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
@ -332,6 +354,9 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
if (nbt.hasKey(Settings.namespace + "owner")) {
|
||||
owner = nbt.getString(Settings.namespace + "owner")
|
||||
}
|
||||
if (nbt.hasKey(Settings.namespace + "tag")) {
|
||||
tag = nbt.getCompoundTag(Settings.namespace + "tag")
|
||||
}
|
||||
xp = nbt.getDouble(Settings.namespace + "xp") max 0
|
||||
updateXpInfo()
|
||||
selectedSlot = nbt.getInteger(Settings.namespace + "selectedSlot") max actualSlot(0) min (getSizeInventory - 1)
|
||||
@ -355,6 +380,9 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
nbt.setNewCompoundTag(Settings.namespace + "keyboard", keyboard.save)
|
||||
nbt.setNewCompoundTag(Settings.namespace + "robot", bot.save)
|
||||
nbt.setString(Settings.namespace + "owner", owner)
|
||||
if (tag != null) {
|
||||
nbt.setTag(Settings.namespace + "tag", tag)
|
||||
}
|
||||
nbt.setDouble(Settings.namespace + "xp", xp)
|
||||
nbt.setInteger(Settings.namespace + "selectedSlot", selectedSlot)
|
||||
if (isAnimatingMove || isAnimatingSwing || isAnimatingTurn) {
|
||||
@ -371,6 +399,9 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def readFromNBTForClient(nbt: NBTTagCompound) {
|
||||
super.readFromNBTForClient(nbt)
|
||||
if (nbt.hasKey(Settings.namespace + "tag")) {
|
||||
tag = nbt.getCompoundTag(Settings.namespace + "tag")
|
||||
}
|
||||
selectedSlot = nbt.getInteger("selectedSlot")
|
||||
if (nbt.hasKey("equipped")) {
|
||||
equippedItem = Option(ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("equipped")))
|
||||
@ -393,6 +424,9 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
|
||||
override def writeToNBTForClient(nbt: NBTTagCompound) = this.synchronized {
|
||||
super.writeToNBTForClient(nbt)
|
||||
if (tag != null) {
|
||||
nbt.setTag(Settings.namespace + "tag", tag)
|
||||
}
|
||||
nbt.setInteger("selectedSlot", selectedSlot)
|
||||
if (getStackInSlot(0) != null) {
|
||||
nbt.setNewCompoundTag("equipped", getStackInSlot(0).writeToNBT)
|
||||
@ -566,3 +600,18 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
|
||||
case _ => (actualSlot(0) until getSizeInventory).toArray
|
||||
}
|
||||
}
|
||||
|
||||
object Robot {
|
||||
val names = try {
|
||||
Source.fromInputStream(getClass.getResourceAsStream(
|
||||
"/assets/" + Settings.resourceDomain + "/robot.names"))("UTF-8").
|
||||
getLines().map(_.trim).filter(!_.startsWith("#")).filter(_ != "").toArray
|
||||
}
|
||||
catch {
|
||||
case t: Throwable =>
|
||||
OpenComputers.log.log(Level.WARNING, "Failed loading robot name list.", t)
|
||||
Array.empty
|
||||
}
|
||||
|
||||
def randomName = names((math.random * names.length).toInt)
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package li.cil.oc.server
|
||||
|
||||
import li.cil.oc.common
|
||||
import li.cil.oc.common.tileentity._
|
||||
import li.cil.oc.common.tileentity
|
||||
import li.cil.oc.common.{CompressedPacketBuilder, PacketBuilder, PacketType}
|
||||
import li.cil.oc.util.PackedColor
|
||||
import net.minecraft.entity.player.EntityPlayerMP
|
||||
@ -9,7 +9,7 @@ import net.minecraft.item.ItemStack
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
object PacketSender {
|
||||
def sendAbstractBusState(t: AbstractBusAware) {
|
||||
def sendAbstractBusState(t: tileentity.AbstractBusAware) {
|
||||
val pb = new PacketBuilder(PacketType.AbstractBusState)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -26,7 +26,7 @@ object PacketSender {
|
||||
pb.sendToPlayer(player)
|
||||
}
|
||||
|
||||
def sendChargerState(t: Charger) {
|
||||
def sendChargerState(t: tileentity.Charger) {
|
||||
val pb = new PacketBuilder(PacketType.ChargerState)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -35,7 +35,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendComputerState(t: Computer) {
|
||||
def sendComputerState(t: tileentity.Computer) {
|
||||
val pb = new PacketBuilder(PacketType.ComputerState)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -44,7 +44,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendComputerUserList(t: Computer, list: Array[String]) {
|
||||
def sendComputerUserList(t: tileentity.Computer, list: Array[String]) {
|
||||
val pb = new PacketBuilder(PacketType.ComputerUserList)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -54,7 +54,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendHologramClear(t: Hologram) {
|
||||
def sendHologramClear(t: tileentity.Hologram) {
|
||||
val pb = new PacketBuilder(PacketType.HologramClear)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -62,7 +62,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendHologramPowerChange(t: Hologram) {
|
||||
def sendHologramPowerChange(t: tileentity.Hologram) {
|
||||
val pb = new PacketBuilder(PacketType.HologramPowerChange)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -71,7 +71,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendHologramScale(t: Hologram) {
|
||||
def sendHologramScale(t: tileentity.Hologram) {
|
||||
val pb = new PacketBuilder(PacketType.HologramScale)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -80,7 +80,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendHologramSet(t: Hologram) {
|
||||
def sendHologramSet(t: tileentity.Hologram) {
|
||||
val pb = new CompressedPacketBuilder(PacketType.HologramSet)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -97,7 +97,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendPowerState(t: PowerInformation) {
|
||||
def sendPowerState(t: tileentity.PowerInformation) {
|
||||
val pb = new PacketBuilder(PacketType.PowerState)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -107,7 +107,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendRedstoneState(t: RedstoneAware) {
|
||||
def sendRedstoneState(t: tileentity.RedstoneAware) {
|
||||
val pb = new PacketBuilder(PacketType.RedstoneState)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -119,7 +119,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendRobotMove(t: Robot, ox: Int, oy: Int, oz: Int, direction: ForgeDirection) {
|
||||
def sendRobotMove(t: tileentity.Robot, ox: Int, oy: Int, oz: Int, direction: ForgeDirection) {
|
||||
val pb = new PacketBuilder(PacketType.RobotMove)
|
||||
|
||||
// Custom pb.writeTileEntity() with fake coordinates (valid for the client).
|
||||
@ -132,7 +132,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendRobotAnimateSwing(t: Robot) {
|
||||
def sendRobotAnimateSwing(t: tileentity.Robot) {
|
||||
val pb = new PacketBuilder(PacketType.RobotAnimateSwing)
|
||||
|
||||
pb.writeTileEntity(t.proxy)
|
||||
@ -141,7 +141,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t, 64)
|
||||
}
|
||||
|
||||
def sendRobotAnimateTurn(t: Robot) {
|
||||
def sendRobotAnimateTurn(t: tileentity.Robot) {
|
||||
val pb = new PacketBuilder(PacketType.RobotAnimateTurn)
|
||||
|
||||
pb.writeTileEntity(t.proxy)
|
||||
@ -151,7 +151,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t, 64)
|
||||
}
|
||||
|
||||
def sendRobotEquippedItemChange(t: Robot, stack: ItemStack) {
|
||||
def sendRobotEquippedItemChange(t: tileentity.Robot, stack: ItemStack) {
|
||||
val pb = new PacketBuilder(PacketType.RobotEquippedItemChange)
|
||||
|
||||
pb.writeTileEntity(t.proxy)
|
||||
@ -160,7 +160,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendRobotEquippedUpgradeChange(t: Robot, stack: ItemStack) {
|
||||
def sendRobotEquippedUpgradeChange(t: tileentity.Robot, stack: ItemStack) {
|
||||
val pb = new PacketBuilder(PacketType.RobotEquippedUpgradeChange)
|
||||
|
||||
pb.writeTileEntity(t.proxy)
|
||||
@ -169,7 +169,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendRobotSelectedSlotChange(t: Robot) {
|
||||
def sendRobotSelectedSlotChange(t: tileentity.Robot) {
|
||||
val pb = new PacketBuilder(PacketType.RobotSelectedSlotChange)
|
||||
|
||||
pb.writeTileEntity(t.proxy)
|
||||
@ -178,7 +178,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t, 16)
|
||||
}
|
||||
|
||||
def sendRobotXp(t: Robot) {
|
||||
def sendRobotXp(t: tileentity.Robot) {
|
||||
val pb = new PacketBuilder(PacketType.RobotXp)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -187,7 +187,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendRotatableState(t: Rotatable) {
|
||||
def sendRotatableState(t: tileentity.Rotatable) {
|
||||
val pb = new PacketBuilder(PacketType.RotatableState)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -201,7 +201,7 @@ object PacketSender {
|
||||
val pb = new PacketBuilder(PacketType.ScreenColorChange)
|
||||
|
||||
val t = b.owner match {
|
||||
case t: Buffer =>
|
||||
case t: tileentity.Buffer =>
|
||||
pb.writeTileEntity(t)
|
||||
t
|
||||
case t: common.component.Terminal =>
|
||||
@ -220,7 +220,7 @@ object PacketSender {
|
||||
val pb = new PacketBuilder(PacketType.ScreenCopy)
|
||||
|
||||
val t = b.owner match {
|
||||
case t: Buffer =>
|
||||
case t: tileentity.Buffer =>
|
||||
pb.writeTileEntity(t)
|
||||
t
|
||||
case t: common.component.Terminal =>
|
||||
@ -243,7 +243,7 @@ object PacketSender {
|
||||
val pb = new PacketBuilder(PacketType.ScreenDepthChange)
|
||||
|
||||
val t = b.owner match {
|
||||
case t: Buffer =>
|
||||
case t: tileentity.Buffer =>
|
||||
pb.writeTileEntity(t)
|
||||
t
|
||||
case t: common.component.Terminal =>
|
||||
@ -261,7 +261,7 @@ object PacketSender {
|
||||
val pb = new PacketBuilder(PacketType.ScreenFill)
|
||||
|
||||
val t = b.owner match {
|
||||
case t: Buffer =>
|
||||
case t: tileentity.Buffer =>
|
||||
pb.writeTileEntity(t)
|
||||
t
|
||||
case t: common.component.Terminal =>
|
||||
@ -279,7 +279,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendScreenPowerChange(t: Buffer, hasPower: Boolean) {
|
||||
def sendScreenPowerChange(t: tileentity.Buffer, hasPower: Boolean) {
|
||||
val pb = new PacketBuilder(PacketType.ScreenPowerChange)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -292,7 +292,7 @@ object PacketSender {
|
||||
val pb = new PacketBuilder(PacketType.ScreenResolutionChange)
|
||||
|
||||
val t = b.owner match {
|
||||
case t: Buffer =>
|
||||
case t: tileentity.Buffer =>
|
||||
pb.writeTileEntity(t)
|
||||
t
|
||||
case t: common.component.Terminal =>
|
||||
@ -311,7 +311,7 @@ object PacketSender {
|
||||
val pb = new PacketBuilder(PacketType.ScreenSet)
|
||||
|
||||
val t = b.owner match {
|
||||
case t: Buffer =>
|
||||
case t: tileentity.Buffer =>
|
||||
pb.writeTileEntity(t)
|
||||
t
|
||||
case t: common.component.Terminal =>
|
||||
@ -327,7 +327,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendServerPresence(t: Rack) {
|
||||
def sendServerPresence(t: tileentity.Rack) {
|
||||
val pb = new PacketBuilder(PacketType.ServerPresence)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -342,7 +342,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendServerState(t: Rack) {
|
||||
def sendServerState(t: tileentity.Rack) {
|
||||
val pb = new PacketBuilder(PacketType.ComputerState)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
@ -352,7 +352,7 @@ object PacketSender {
|
||||
pb.sendToNearbyPlayers(t)
|
||||
}
|
||||
|
||||
def sendServerState(t: Rack, number: Int, player: Option[EntityPlayerMP] = None) {
|
||||
def sendServerState(t: tileentity.Rack, number: Int, player: Option[EntityPlayerMP] = None) {
|
||||
val pb = new PacketBuilder(PacketType.ComputerState)
|
||||
|
||||
pb.writeTileEntity(t)
|
||||
|
@ -1,16 +1,18 @@
|
||||
package li.cil.oc.server.component
|
||||
|
||||
import java.io.{FileNotFoundException, IOException}
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api.Network
|
||||
import li.cil.oc.api.fs.{Label, Mode, FileSystem => IFileSystem}
|
||||
import li.cil.oc.api.Network
|
||||
import li.cil.oc.api.network._
|
||||
import li.cil.oc.common.Sound
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
import net.minecraft.nbt.{NBTTagIntArray, NBTTagList, NBTTagCompound}
|
||||
import net.minecraftforge.common.util.Constants.NBT
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import scala.collection.mutable
|
||||
|
||||
class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedComponent {
|
||||
class FileSystem(val fileSystem: IFileSystem, var label: Label, val container: Option[TileEntity] = None) extends ManagedComponent {
|
||||
val node = Network.newNode(this, Visibility.Network).
|
||||
withComponent("filesystem", Visibility.Neighbors).
|
||||
withConnector().
|
||||
@ -75,7 +77,9 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
@Callback
|
||||
def list(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
Option(fileSystem.list(clean(args.checkString(0)))) match {
|
||||
case Some(list) => Array(list)
|
||||
case Some(list) =>
|
||||
container.foreach(Sound.playDiskActivity)
|
||||
Array(list)
|
||||
case _ => null
|
||||
}
|
||||
}
|
||||
@ -84,19 +88,25 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
def makeDirectory(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
def recurse(path: String): Boolean = !fileSystem.exists(path) && (fileSystem.makeDirectory(path) ||
|
||||
(recurse(path.split("/").dropRight(1).mkString("/")) && fileSystem.makeDirectory(path)))
|
||||
result(recurse(clean(args.checkString(0))))
|
||||
val success = recurse(clean(args.checkString(0)))
|
||||
if (success) container.foreach(Sound.playDiskActivity)
|
||||
result(success)
|
||||
}
|
||||
|
||||
@Callback
|
||||
def remove(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
def recurse(parent: String): Boolean = (!fileSystem.isDirectory(parent) ||
|
||||
fileSystem.list(parent).forall(child => recurse(parent + "/" + child))) && fileSystem.delete(parent)
|
||||
result(recurse(clean(args.checkString(0))))
|
||||
val success = recurse(clean(args.checkString(0)))
|
||||
if (success) container.foreach(Sound.playDiskActivity)
|
||||
result(success)
|
||||
}
|
||||
|
||||
@Callback
|
||||
def rename(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.rename(clean(args.checkString(0)), clean(args.checkString(1))))
|
||||
val success = fileSystem.rename(clean(args.checkString(0)), clean(args.checkString(1)))
|
||||
if (success) container.foreach(Sound.playDiskActivity)
|
||||
result(success)
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
@ -149,6 +159,7 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
if (!node.tryChangeBuffer(-Settings.get.hddReadCost * bytes.length)) {
|
||||
throw new IOException("not enough energy")
|
||||
}
|
||||
container.foreach(Sound.playDiskActivity)
|
||||
result(bytes)
|
||||
}
|
||||
else {
|
||||
@ -186,7 +197,10 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
checkOwner(context.node.address, handle)
|
||||
Option(fileSystem.getHandle(handle)) match {
|
||||
case Some(file) => file.write(value); result(true)
|
||||
case Some(file) =>
|
||||
file.write(value)
|
||||
container.foreach(Sound.playDiskActivity)
|
||||
result(true)
|
||||
case _ => throw new IOException("bad file descriptor")
|
||||
}
|
||||
}
|
||||
|
@ -9,24 +9,24 @@ import li.cil.oc.util.mods.ComputerCraft
|
||||
import li.cil.oc.{Settings, Items}
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.tileentity.{TileEntity => MCTileEntity}
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
|
||||
object FileSystem extends Item {
|
||||
override def worksWith(stack: ItemStack) = isOneOf(stack, Items.hdd1, Items.hdd2, Items.hdd3, Items.floppyDisk) || ComputerCraft.isDisk(stack)
|
||||
|
||||
override def createEnvironment(stack: ItemStack, container: MCTileEntity) =
|
||||
override def createEnvironment(stack: ItemStack, container: TileEntity) =
|
||||
if (ComputerCraft.isDisk(stack) && container != null) {
|
||||
val address = addressFromTag(dataTag(stack))
|
||||
val mount = ComputerCraft.createDiskMount(stack, container.getWorldObj)
|
||||
Option(oc.api.FileSystem.asManagedEnvironment(mount, new ComputerCraftLabel(stack))) match {
|
||||
Option(oc.api.FileSystem.asManagedEnvironment(mount, new ComputerCraftLabel(stack), container)) match {
|
||||
case Some(environment) =>
|
||||
environment.node.asInstanceOf[oc.server.network.Node].address = address
|
||||
environment
|
||||
case _ => null
|
||||
}
|
||||
} else Items.multi.subItem(stack) match {
|
||||
case Some(hdd: HardDiskDrive) => createEnvironment(stack, hdd.kiloBytes * 1024)
|
||||
case Some(disk: FloppyDisk) => createEnvironment(stack, Settings.get.floppySize * 1024)
|
||||
case Some(hdd: HardDiskDrive) => createEnvironment(stack, hdd.kiloBytes * 1024, container)
|
||||
case Some(disk: FloppyDisk) => createEnvironment(stack, Settings.get.floppySize * 1024, container)
|
||||
case _ => null
|
||||
}
|
||||
|
||||
@ -44,18 +44,17 @@ object FileSystem extends Item {
|
||||
case _ => 0
|
||||
}
|
||||
|
||||
private def createEnvironment(stack: ItemStack, capacity: Int) = {
|
||||
private def createEnvironment(stack: ItemStack, capacity: Int, container: TileEntity) = {
|
||||
// We have a bit of a chicken-egg problem here, because we want to use the
|
||||
// node's address as the folder name... so we generate the address here,
|
||||
// if necessary. No one will know, right? Right!?
|
||||
val address = addressFromTag(dataTag(stack))
|
||||
Option(oc.api.FileSystem.asManagedEnvironment(oc.api.FileSystem.
|
||||
fromSaveDirectory(address, capacity, Settings.get.bufferChanges), new ItemLabel(stack))) match {
|
||||
case Some(environment) =>
|
||||
environment.node.asInstanceOf[oc.server.network.Node].address = address
|
||||
environment
|
||||
case _ => null
|
||||
val fs = oc.api.FileSystem.fromSaveDirectory(address, capacity, Settings.get.bufferChanges)
|
||||
val environment = oc.api.FileSystem.asManagedEnvironment(fs, new ItemLabel(stack), container)
|
||||
if (environment != null) {
|
||||
environment.node.asInstanceOf[oc.server.network.Node].address = address
|
||||
}
|
||||
environment
|
||||
}
|
||||
|
||||
private def addressFromTag(tag: NBTTagCompound) =
|
||||
|
@ -72,6 +72,9 @@ object FileSystem extends api.detail.FileSystemAPI {
|
||||
@Optional.Method(modid = "ComputerCraft")
|
||||
def fromComputerCraft(mount: IWritableMount) = new ComputerCraftWritableFileSystem(mount)
|
||||
|
||||
def asManagedEnvironment(fileSystem: api.fs.FileSystem, label: Label, container: net.minecraft.tileentity.TileEntity) =
|
||||
Option(fileSystem).flatMap(fs => Some(new component.FileSystem(fs, label, Option(container)))).orNull
|
||||
|
||||
def asManagedEnvironment(fileSystem: api.fs.FileSystem, label: Label) =
|
||||
Option(fileSystem).flatMap(fs => Some(new component.FileSystem(fs, label))).orNull
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user