Merge branch '3d-printer' into master-MC1.7.10
Conflicts: src/main/resources/application.conf src/main/scala/li/cil/oc/Settings.scala
BIN
assets/items.psd
@ -509,6 +509,10 @@ opencomputers {
|
|||||||
# controls the speed at which items are disassembled, basically.
|
# controls the speed at which items are disassembled, basically.
|
||||||
disassemblerTickAmount: 25
|
disassemblerTickAmount: 25
|
||||||
|
|
||||||
|
# The amount of energy the printer can apply per tick. This controls
|
||||||
|
# the speed at which prints are completed, basically.
|
||||||
|
printerTickAmount: 1
|
||||||
|
|
||||||
# If you don't want OpenComputers to accept power from one or more of the
|
# If you don't want OpenComputers to accept power from one or more of the
|
||||||
# supported power mods, for example because it doesn't suit the vision
|
# supported power mods, for example because it doesn't suit the vision
|
||||||
# of your mod pack, you can disable support for them here. To stop
|
# of your mod pack, you can disable support for them here. To stop
|
||||||
@ -729,6 +733,9 @@ opencomputers {
|
|||||||
# Energy it costs to re-program an EEPROM. This is deliberately
|
# Energy it costs to re-program an EEPROM. This is deliberately
|
||||||
# expensive, to discourage frequent re-writing of EEPROMs.
|
# expensive, to discourage frequent re-writing of EEPROMs.
|
||||||
eepromWrite: 50
|
eepromWrite: 50
|
||||||
|
|
||||||
|
# How much energy is required for a single 3D print.
|
||||||
|
printerModel: 25
|
||||||
}
|
}
|
||||||
|
|
||||||
# The rate at which different blocks accept external power. All of these
|
# The rate at which different blocks accept external power. All of these
|
||||||
@ -1022,6 +1029,12 @@ opencomputers {
|
|||||||
# avoid issues with computers timing out, but can also lead to higher
|
# avoid issues with computers timing out, but can also lead to higher
|
||||||
# server load. AGAIN, USE WITH CARE!
|
# server load. AGAIN, USE WITH CARE!
|
||||||
threadPriority: -1
|
threadPriority: -1
|
||||||
|
|
||||||
|
# The maximum number of shape for a state of a 3D print allowed. This is
|
||||||
|
# for the individual states (off and on), so it is possible to have up to
|
||||||
|
# this many shapes *per state* (the reasoning being that only one state
|
||||||
|
# will ever be visible at a time).
|
||||||
|
maxPrinterShapes: 16
|
||||||
}
|
}
|
||||||
|
|
||||||
# Settings for mod integration (the mod previously known as OpenComponents).
|
# Settings for mod integration (the mod previously known as OpenComponents).
|
||||||
|
@ -23,6 +23,8 @@ tile.oc.microcontroller.name=Microcontroller
|
|||||||
tile.oc.motionSensor.name=Motion Sensor
|
tile.oc.motionSensor.name=Motion Sensor
|
||||||
tile.oc.powerConverter.name=Power Converter
|
tile.oc.powerConverter.name=Power Converter
|
||||||
tile.oc.powerDistributor.name=Power Distributor
|
tile.oc.powerDistributor.name=Power Distributor
|
||||||
|
tile.oc.print.name=3D Print
|
||||||
|
tile.oc.printer.name=3D Printer
|
||||||
tile.oc.raid.name=Raid
|
tile.oc.raid.name=Raid
|
||||||
tile.oc.redstone.name=Redstone I/O
|
tile.oc.redstone.name=Redstone I/O
|
||||||
tile.oc.robot.name=Robot
|
tile.oc.robot.name=Robot
|
||||||
@ -42,6 +44,7 @@ item.oc.appengTunnel.name=P2P Tunnel - OpenComputers
|
|||||||
item.oc.ArrowKeys.name=Arrow Keys
|
item.oc.ArrowKeys.name=Arrow Keys
|
||||||
item.oc.ButtonGroup.name=Button Group
|
item.oc.ButtonGroup.name=Button Group
|
||||||
item.oc.CardBase.name=Card Base
|
item.oc.CardBase.name=Card Base
|
||||||
|
item.oc.Chamelium.name=Chamelium
|
||||||
item.oc.CircuitBoard.name=Circuit Board
|
item.oc.CircuitBoard.name=Circuit Board
|
||||||
item.oc.ControlUnit.name=Control Unit (CU)
|
item.oc.ControlUnit.name=Control Unit (CU)
|
||||||
item.oc.ComponentBus0.name=Component Bus (Tier 1)
|
item.oc.ComponentBus0.name=Component Bus (Tier 1)
|
||||||
@ -66,6 +69,8 @@ item.oc.GraphicsCard2.name=Graphics Card (Tier 3)
|
|||||||
item.oc.HardDiskDrive0.name=Hard Disk Drive (Tier 1)
|
item.oc.HardDiskDrive0.name=Hard Disk Drive (Tier 1)
|
||||||
item.oc.HardDiskDrive1.name=Hard Disk Drive (Tier 2)
|
item.oc.HardDiskDrive1.name=Hard Disk Drive (Tier 2)
|
||||||
item.oc.HardDiskDrive2.name=Hard Disk Drive (Tier 3)
|
item.oc.HardDiskDrive2.name=Hard Disk Drive (Tier 3)
|
||||||
|
item.oc.InkCartridge.name=Ink Cartidge
|
||||||
|
item.oc.InkCartridgeEmpty.name=Ink Cartidge (Empty)
|
||||||
item.oc.InternetCard.name=Internet Card
|
item.oc.InternetCard.name=Internet Card
|
||||||
item.oc.Interweb.name=Interweb
|
item.oc.Interweb.name=Interweb
|
||||||
item.oc.IronNugget.name=Iron Nugget
|
item.oc.IronNugget.name=Iron Nugget
|
||||||
@ -98,6 +103,7 @@ item.oc.TabletCase0.name=Tablet Case (Tier 1)
|
|||||||
item.oc.TabletCase1.name=Tablet Case (Tier 2)
|
item.oc.TabletCase1.name=Tablet Case (Tier 2)
|
||||||
item.oc.TabletCase3.name=Tablet Case (Creative)
|
item.oc.TabletCase3.name=Tablet Case (Creative)
|
||||||
item.oc.Terminal.name=Remote Terminal
|
item.oc.Terminal.name=Remote Terminal
|
||||||
|
item.oc.TexturePicker.name=Texture Picker
|
||||||
item.oc.Transistor.name=Transistor
|
item.oc.Transistor.name=Transistor
|
||||||
item.oc.UpgradeAngel.name=Angel Upgrade
|
item.oc.UpgradeAngel.name=Angel Upgrade
|
||||||
item.oc.UpgradeBattery0.name=Battery Upgrade (Tier 1)
|
item.oc.UpgradeBattery0.name=Battery Upgrade (Tier 1)
|
||||||
@ -164,6 +170,7 @@ oc:gui.Chat.NewVersion=A new version is available: %s
|
|||||||
oc:gui.Chat.WarningFingerprint=§cWARNING§f - fingerprint mismatch! Expected '§a%s§f' but got '§e%s§f'. Unless you are a modder and are running the deobfuscated version of the mod, it is §lstrongly§f recommended to redownload OpenComputers, because the JAR you are using may have been tampered with.
|
oc:gui.Chat.WarningFingerprint=§cWARNING§f - fingerprint mismatch! Expected '§a%s§f' but got '§e%s§f'. Unless you are a modder and are running the deobfuscated version of the mod, it is §lstrongly§f recommended to redownload OpenComputers, because the JAR you are using may have been tampered with.
|
||||||
oc:gui.Chat.WarningLuaFallback=Native Lua libraries are not available, computers will not be able to persist their state. They will reboot on chunk reloads.
|
oc:gui.Chat.WarningLuaFallback=Native Lua libraries are not available, computers will not be able to persist their state. They will reboot on chunk reloads.
|
||||||
oc:gui.Chat.WarningPower=No supported power providing mod available. Computers, screens and all other components will §lnot§f require energy. Install one of the following mods to enable power: BuildCraft, Electrical Age, IndustrialCraft2, Mekanism or Thermal Expansion. Disable power in the config to suppress this warning.
|
oc:gui.Chat.WarningPower=No supported power providing mod available. Computers, screens and all other components will §lnot§f require energy. Install one of the following mods to enable power: BuildCraft, Electrical Age, IndustrialCraft2, Mekanism or Thermal Expansion. Disable power in the config to suppress this warning.
|
||||||
|
oc:gui.Chat.TextureName=§7Texture name is §a%s§f.
|
||||||
oc:gui.Chat.WarningProjectRed=You are using a version of Project: Red that is incompatible with OpenComputers. Try updating your version of Project: Red.
|
oc:gui.Chat.WarningProjectRed=You are using a version of Project: Red that is incompatible with OpenComputers. Try updating your version of Project: Red.
|
||||||
oc:gui.Error.ComponentOverflow=Too many components connected to the computer.
|
oc:gui.Error.ComponentOverflow=Too many components connected to the computer.
|
||||||
oc:gui.Error.InternalError=Internal error, please see the log file. This is probably a bug.
|
oc:gui.Error.InternalError=Internal error, please see the log file. This is probably a bug.
|
||||||
@ -197,6 +204,7 @@ oc:container.Charger=Charger
|
|||||||
oc:container.Case=Computer
|
oc:container.Case=Computer
|
||||||
oc:container.Disassembler=Disassembler
|
oc:container.Disassembler=Disassembler
|
||||||
oc:container.DiskDrive=Disk Drive
|
oc:container.DiskDrive=Disk Drive
|
||||||
|
oc:container.Printer=Printer
|
||||||
oc:container.Raid=Raid
|
oc:container.Raid=Raid
|
||||||
oc:container.Server=Server
|
oc:container.Server=Server
|
||||||
oc:container.ServerRack=Server Rack
|
oc:container.ServerRack=Server Rack
|
||||||
@ -219,6 +227,7 @@ oc:tooltip.Cable=A cheap way of connecting blocks.
|
|||||||
oc:tooltip.Capacitor=Stores energy for later use. Can be filled and emptied very quickly.
|
oc:tooltip.Capacitor=Stores energy for later use. Can be filled and emptied very quickly.
|
||||||
oc:tooltip.CardBase=As the name indicates, this is the basic building block for all expansion cards.
|
oc:tooltip.CardBase=As the name indicates, this is the basic building block for all expansion cards.
|
||||||
oc:tooltip.Case=The Computer Case is the basic building block for computers and houses the computer's §fextension cards§7, §fRAM§7 and §fhard disks§7.[nl] Slots: §f%s§7
|
oc:tooltip.Case=The Computer Case is the basic building block for computers and houses the computer's §fextension cards§7, §fRAM§7 and §fhard disks§7.[nl] Slots: §f%s§7
|
||||||
|
oc:tooltip.Chamelium=Raw material for 3D prints. Do not swallow. Not that you could even if you wanted to.
|
||||||
oc:tooltip.Charger=Transfers energy from capacitors into adjacent robots and drones. The transfer rate depends on the incoming §fredstone signal§7, where no signal means don't charge devices, and maximum strength means charge at full speed. Can also be used to charge tablets and access hard drives in tablets.
|
oc:tooltip.Charger=Transfers energy from capacitors into adjacent robots and drones. The transfer rate depends on the incoming §fredstone signal§7, where no signal means don't charge devices, and maximum strength means charge at full speed. Can also be used to charge tablets and access hard drives in tablets.
|
||||||
oc:tooltip.CircuitBoard=Now we're getting somewhere. Can be etched to obtain a printed circuit board.
|
oc:tooltip.CircuitBoard=Now we're getting somewhere. Can be etched to obtain a printed circuit board.
|
||||||
oc:tooltip.ControlUnit=This is the unit that... controls... stuff. You need it to build a CPU. So yeah, totally important.
|
oc:tooltip.ControlUnit=This is the unit that... controls... stuff. You need it to build a CPU. So yeah, totally important.
|
||||||
@ -237,6 +246,8 @@ oc:tooltip.DroneCase=This casing is used to build Drones in the assembler. It ha
|
|||||||
oc:tooltip.EEPROM=Small, programmable storage that contains the BIOS computers use to boot.
|
oc:tooltip.EEPROM=Small, programmable storage that contains the BIOS computers use to boot.
|
||||||
oc:tooltip.Geolyzer=Allows scanning the surrounding area's blocks' hardness. This information can be useful for generating holograms of the area or for detecting ores.
|
oc:tooltip.Geolyzer=Allows scanning the surrounding area's blocks' hardness. This information can be useful for generating holograms of the area or for detecting ores.
|
||||||
oc:tooltip.GraphicsCard=Used to change what's displayed on screens.[nl] Maximum resolution: §f%sx%s§7[nl] Maximum color depth: §f%s§7[nl] Operations/tick: §f%s§7
|
oc:tooltip.GraphicsCard=Used to change what's displayed on screens.[nl] Maximum resolution: §f%sx%s§7[nl] Maximum color depth: §f%s§7[nl] Operations/tick: §f%s§7
|
||||||
|
oc:tooltip.InkCartridge=Used to refill ink in 3D printers. For mysterious reasons it does not have to remain in the printer.
|
||||||
|
oc:tooltip.InkCartridgeEmpty=This ink cartridge has been sucked dry. Refill it using dyes. Or throw it away. See if I care.
|
||||||
oc:tooltip.InternetCard=This card allows making HTTP requests and using real TCP sockets.
|
oc:tooltip.InternetCard=This card allows making HTTP requests and using real TCP sockets.
|
||||||
oc:tooltip.Interweb=Congratulations, you win one (1) interweb. You can connect to it using an Internet Card. Beware: don't feed the trolls.
|
oc:tooltip.Interweb=Congratulations, you win one (1) interweb. You can connect to it using an Internet Card. Beware: don't feed the trolls.
|
||||||
oc:tooltip.IronNugget=A nugget made of iron, that's why it's called an Iron Nugget, duh...
|
oc:tooltip.IronNugget=A nugget made of iron, that's why it's called an Iron Nugget, duh...
|
||||||
@ -262,6 +273,7 @@ oc:tooltip.PowerConverter.ThermalExpansion=§fThermal Expansion RF§7: §a%s:%s
|
|||||||
oc:tooltip.PowerConverter.ResonantEngine=§fResonant Engine Coulombs§7: §a%s:%s§7
|
oc:tooltip.PowerConverter.ResonantEngine=§fResonant Engine Coulombs§7: §a%s:%s§7
|
||||||
oc:tooltip.PowerConverter=Converts power from other mods to the internal energy type. Conversion rates:
|
oc:tooltip.PowerConverter=Converts power from other mods to the internal energy type. Conversion rates:
|
||||||
oc:tooltip.PowerDistributor=Distributes energy among different networks. This is useful for sharing power fed into your system from one converter among different sub-networks that should remain separate.
|
oc:tooltip.PowerDistributor=Distributes energy among different networks. This is useful for sharing power fed into your system from one converter among different sub-networks that should remain separate.
|
||||||
|
oc:tooltip.Printer=Allows printing blocks of user-defined shapes using Chamelium and Ink Cartridges. Must be configured using a computer. Keep away from small children. Because reasons.
|
||||||
oc:tooltip.PrintedCircuitBoard=The basic building block for expansion cards and memory and such.
|
oc:tooltip.PrintedCircuitBoard=The basic building block for expansion cards and memory and such.
|
||||||
oc:tooltip.Present=... for your troubles. Open this present for a chance to receive some §kphat lewt§7![nl]§8Craft OpenComputers items when the time is right for a chance to receive a present.§7
|
oc:tooltip.Present=... for your troubles. Open this present for a chance to receive some §kphat lewt§7![nl]§8Craft OpenComputers items when the time is right for a chance to receive a present.§7
|
||||||
oc:tooltip.Raid=Allows combining three hard drives into one larger file system that can be used by all connected computers.
|
oc:tooltip.Raid=Allows combining three hard drives into one larger file system that can be used by all connected computers.
|
||||||
@ -285,6 +297,7 @@ oc:tooltip.Switch=Allows connecting different networks to each other. Only netwo
|
|||||||
oc:tooltip.Tablet=A tablet computer, for fresh Lua on the go. Can be forced to shut down by sneak-activating it.
|
oc:tooltip.Tablet=A tablet computer, for fresh Lua on the go. Can be forced to shut down by sneak-activating it.
|
||||||
oc:tooltip.TabletCase=Basic case for tablets. Place it into the assembler to add in components and create a tablet computer.
|
oc:tooltip.TabletCase=Basic case for tablets. Place it into the assembler to add in components and create a tablet computer.
|
||||||
oc:tooltip.Terminal=Allows controlling a server remotely, as long as you are in range of it. Acts like a portable screen and keyboard. Shift-right-click a server in a server rack to bind the terminal to it.
|
oc:tooltip.Terminal=Allows controlling a server remotely, as long as you are in range of it. Acts like a portable screen and keyboard. Shift-right-click a server in a server rack to bind the terminal to it.
|
||||||
|
oc:tooltip.TexturePicker=This tool allows showing a string describing a block's surface, for use in 3D printer shape definitions. Totally not texture names, nope. No sir.
|
||||||
oc:tooltip.Tier=§8Tier %s
|
oc:tooltip.Tier=§8Tier %s
|
||||||
oc:tooltip.TooLong=Hold [§f%s§7] for a detailed tooltip.
|
oc:tooltip.TooLong=Hold [§f%s§7] for a detailed tooltip.
|
||||||
oc:tooltip.Transistor=A basic element in most other computer parts. It's a bit twisted, but it does the job.
|
oc:tooltip.Transistor=A basic element in most other computer parts. It's a bit twisted, but it does the job.
|
||||||
|
@ -6,6 +6,11 @@ analyzer {
|
|||||||
["oc:materialTransistor", nuggetGold, ""]
|
["oc:materialTransistor", nuggetGold, ""]
|
||||||
["oc:materialCircuitBoardPrinted", nuggetGold, ""]]
|
["oc:materialCircuitBoardPrinted", nuggetGold, ""]]
|
||||||
}
|
}
|
||||||
|
texturePicker {
|
||||||
|
input: [[dyeBlack, dyeRed, dyeGreen]
|
||||||
|
[dyeBlue, "oc:analyzer", dyePurple]
|
||||||
|
[dyeYellow, dyeMagenta, dyeWhite]]
|
||||||
|
}
|
||||||
droneCase1 {
|
droneCase1 {
|
||||||
input: [[{block="minecraft:end_stone"}, compass, {block="minecraft:end_stone"}]
|
input: [[{block="minecraft:end_stone"}, compass, {block="minecraft:end_stone"}]
|
||||||
["oc:circuitChip1", "oc:microcontrollerCase1", "oc:circuitChip1"]
|
["oc:circuitChip1", "oc:microcontrollerCase1", "oc:circuitChip1"]
|
||||||
@ -318,6 +323,21 @@ disk {
|
|||||||
[nuggetIron, "", nuggetIron]
|
[nuggetIron, "", nuggetIron]
|
||||||
["", nuggetIron, ""]]
|
["", nuggetIron, ""]]
|
||||||
}
|
}
|
||||||
|
chamelium {
|
||||||
|
input: [[gravel, redstone, gravel],
|
||||||
|
[redstone, {item=coal, subID=1}, redstone],
|
||||||
|
[gravel, water_bucket, gravel]]
|
||||||
|
output: 16
|
||||||
|
}
|
||||||
|
inkCartridgeEmpty {
|
||||||
|
input: [[nuggetIron, dispenser, nuggetIron],
|
||||||
|
["oc:materialTransistor", bucket, "oc:materialTransistor"],
|
||||||
|
[nuggetIron, "oc:materialCircuitBoardPrinted", nuggetIron]]
|
||||||
|
}
|
||||||
|
inkCartridge {
|
||||||
|
type: shapeless
|
||||||
|
input: [dyeCyan, dyeMagenta, dyeYellow, dyeBlack, "oc:inkCartridgeEmpty"]
|
||||||
|
}
|
||||||
|
|
||||||
buttonGroup {
|
buttonGroup {
|
||||||
input: [[button, button, button]
|
input: [[button, button, button]
|
||||||
|
After Width: | Height: | Size: 509 B |
After Width: | Height: | Size: 365 B |
BIN
src/main/resources/assets/opencomputers/textures/gui/printer.png
Normal file
After Width: | Height: | Size: 634 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 189 B |
After Width: | Height: | Size: 313 B |
After Width: | Height: | Size: 645 B |
After Width: | Height: | Size: 636 B |
After Width: | Height: | Size: 346 B |
@ -84,6 +84,8 @@ object Localization {
|
|||||||
def WarningFingerprint(event: FMLFingerprintViolationEvent) = new ChatComponentText("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.WarningFingerprint", event.expectedFingerprint, event.fingerprints.toArray.mkString(", ")))
|
def WarningFingerprint(event: FMLFingerprintViolationEvent) = new ChatComponentText("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.WarningFingerprint", event.expectedFingerprint, event.fingerprints.toArray.mkString(", ")))
|
||||||
|
|
||||||
def InfoNewVersion(version: String) = new ChatComponentText("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.NewVersion", version))
|
def InfoNewVersion(version: String) = new ChatComponentText("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.NewVersion", version))
|
||||||
|
|
||||||
|
def TextureName(name: String) = new ChatComponentText("§aOpenComputers§f: ").appendSibling(localizeLater("gui.Chat.TextureName", name))
|
||||||
}
|
}
|
||||||
|
|
||||||
object Computer {
|
object Computer {
|
||||||
|
@ -139,6 +139,7 @@ class Settings(val config: Config) {
|
|||||||
val solarGeneratorEfficiency = config.getDouble("power.solarGeneratorEfficiency")
|
val solarGeneratorEfficiency = config.getDouble("power.solarGeneratorEfficiency")
|
||||||
val assemblerTickAmount = config.getDouble("power.assemblerTickAmount") max 1
|
val assemblerTickAmount = config.getDouble("power.assemblerTickAmount") max 1
|
||||||
val disassemblerTickAmount = config.getDouble("power.disassemblerTickAmount") max 1
|
val disassemblerTickAmount = config.getDouble("power.disassemblerTickAmount") max 1
|
||||||
|
val printerTickAmount = config.getDouble("power.printerTickAmount") max 1
|
||||||
val powerModBlacklist = config.getStringList("power.modBlacklist")
|
val powerModBlacklist = config.getStringList("power.modBlacklist")
|
||||||
|
|
||||||
// power.buffer
|
// power.buffer
|
||||||
@ -192,6 +193,7 @@ class Settings(val config: Config) {
|
|||||||
val chunkloaderCost = config.getDouble("power.cost.chunkloaderCost") max 0
|
val chunkloaderCost = config.getDouble("power.cost.chunkloaderCost") max 0
|
||||||
val pistonCost = config.getDouble("power.cost.pistonPush") max 0
|
val pistonCost = config.getDouble("power.cost.pistonPush") max 0
|
||||||
val eepromWriteCost = config.getDouble("power.cost.eepromWrite") max 0
|
val eepromWriteCost = config.getDouble("power.cost.eepromWrite") max 0
|
||||||
|
val printCost = config.getDouble("power.cost.printerModel") max 0
|
||||||
|
|
||||||
// power.rate
|
// power.rate
|
||||||
val accessPointRate = config.getDouble("power.rate.accessPoint") max 0
|
val accessPointRate = config.getDouble("power.rate.accessPoint") max 0
|
||||||
@ -291,6 +293,7 @@ class Settings(val config: Config) {
|
|||||||
val presentChance = config.getDouble("misc.presentChance") max 0 min 1
|
val presentChance = config.getDouble("misc.presentChance") max 0 min 1
|
||||||
val assemblerBlacklist = config.getStringList("misc.assemblerBlacklist")
|
val assemblerBlacklist = config.getStringList("misc.assemblerBlacklist")
|
||||||
val threadPriority = config.getInt("misc.threadPriority")
|
val threadPriority = config.getInt("misc.threadPriority")
|
||||||
|
val maxPrintComplexity = config.getInt("misc.maxPrinterShapes")
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
// integration
|
// integration
|
||||||
|
@ -32,6 +32,8 @@ object GuiHandler extends CommonGuiHandler {
|
|||||||
new gui.Disassembler(player.inventory, t)
|
new gui.Disassembler(player.inventory, t)
|
||||||
case t: tileentity.DiskDrive if id == GuiType.DiskDrive.id =>
|
case t: tileentity.DiskDrive if id == GuiType.DiskDrive.id =>
|
||||||
new gui.DiskDrive(player.inventory, t)
|
new gui.DiskDrive(player.inventory, t)
|
||||||
|
case t: tileentity.Printer if id == GuiType.Printer.id =>
|
||||||
|
new gui.Printer(player.inventory, t)
|
||||||
case t: tileentity.Raid if id == GuiType.Raid.id =>
|
case t: tileentity.Raid if id == GuiType.Raid.id =>
|
||||||
new gui.Raid(player.inventory, t)
|
new gui.Raid(player.inventory, t)
|
||||||
case t: tileentity.RobotProxy if id == GuiType.Robot.id =>
|
case t: tileentity.RobotProxy if id == GuiType.Robot.id =>
|
||||||
|
@ -9,6 +9,7 @@ import li.cil.oc.api.component
|
|||||||
import li.cil.oc.api.event.FileSystemAccessEvent
|
import li.cil.oc.api.event.FileSystemAccessEvent
|
||||||
import li.cil.oc.client.renderer.PetRenderer
|
import li.cil.oc.client.renderer.PetRenderer
|
||||||
import li.cil.oc.common.PacketType
|
import li.cil.oc.common.PacketType
|
||||||
|
import li.cil.oc.common.container
|
||||||
import li.cil.oc.common.tileentity._
|
import li.cil.oc.common.tileentity._
|
||||||
import li.cil.oc.common.tileentity.traits._
|
import li.cil.oc.common.tileentity.traits._
|
||||||
import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
|
import li.cil.oc.common.{PacketHandler => CommonPacketHandler}
|
||||||
@ -41,6 +42,7 @@ object PacketHandler extends CommonPacketHandler {
|
|||||||
case PacketType.ColorChange => onColorChange(p)
|
case PacketType.ColorChange => onColorChange(p)
|
||||||
case PacketType.ComputerState => onComputerState(p)
|
case PacketType.ComputerState => onComputerState(p)
|
||||||
case PacketType.ComputerUserList => onComputerUserList(p)
|
case PacketType.ComputerUserList => onComputerUserList(p)
|
||||||
|
case PacketType.ContainerUpdate => onContainerUpdate(p)
|
||||||
case PacketType.DisassemblerActiveChange => onDisassemblerActiveChange(p)
|
case PacketType.DisassemblerActiveChange => onDisassemblerActiveChange(p)
|
||||||
case PacketType.FileSystemActivity => onFileSystemActivity(p)
|
case PacketType.FileSystemActivity => onFileSystemActivity(p)
|
||||||
case PacketType.FloppyChange => onFloppyChange(p)
|
case PacketType.FloppyChange => onFloppyChange(p)
|
||||||
@ -52,6 +54,7 @@ object PacketHandler extends CommonPacketHandler {
|
|||||||
case PacketType.HologramTranslation => onHologramPositionOffsetY(p)
|
case PacketType.HologramTranslation => onHologramPositionOffsetY(p)
|
||||||
case PacketType.PetVisibility => onPetVisibility(p)
|
case PacketType.PetVisibility => onPetVisibility(p)
|
||||||
case PacketType.PowerState => onPowerState(p)
|
case PacketType.PowerState => onPowerState(p)
|
||||||
|
case PacketType.PrinterState => onPrinterState(p)
|
||||||
case PacketType.RaidStateChange => onRaidStateChange(p)
|
case PacketType.RaidStateChange => onRaidStateChange(p)
|
||||||
case PacketType.RedstoneState => onRedstoneState(p)
|
case PacketType.RedstoneState => onRedstoneState(p)
|
||||||
case PacketType.RobotAnimateSwing => onRobotAnimateSwing(p)
|
case PacketType.RobotAnimateSwing => onRobotAnimateSwing(p)
|
||||||
@ -134,6 +137,16 @@ object PacketHandler extends CommonPacketHandler {
|
|||||||
case _ => // Invalid packet.
|
case _ => // Invalid packet.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def onContainerUpdate(p: PacketParser) = {
|
||||||
|
val windowId = p.readUnsignedByte()
|
||||||
|
if (p.player.openContainer != null && p.player.openContainer.windowId == windowId) {
|
||||||
|
p.player.openContainer match {
|
||||||
|
case container: container.Player => container.updateCustomData(p.readNBT())
|
||||||
|
case _ => // Invalid packet.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def onDisassemblerActiveChange(p: PacketParser) =
|
def onDisassemblerActiveChange(p: PacketParser) =
|
||||||
p.readTileEntity[Disassembler]() match {
|
p.readTileEntity[Disassembler]() match {
|
||||||
case Some(t) => t.isActive = p.readBoolean()
|
case Some(t) => t.isActive = p.readBoolean()
|
||||||
@ -242,6 +255,14 @@ object PacketHandler extends CommonPacketHandler {
|
|||||||
case _ => // Invalid packet.
|
case _ => // Invalid packet.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def onPrinterState(p: PacketParser) =
|
||||||
|
p.readTileEntity[Printer]() match {
|
||||||
|
case Some(t) =>
|
||||||
|
if (p.readBoolean()) t.requiredEnergy = 9001
|
||||||
|
else t.requiredEnergy = 0
|
||||||
|
case _ => // Invalid packet.
|
||||||
|
}
|
||||||
|
|
||||||
def onRaidStateChange(p: PacketParser) =
|
def onRaidStateChange(p: PacketParser) =
|
||||||
p.readTileEntity[Raid]() match {
|
p.readTileEntity[Raid]() match {
|
||||||
case Some(t) =>
|
case Some(t) =>
|
||||||
|
@ -58,6 +58,7 @@ private[oc] class Proxy extends CommonProxy {
|
|||||||
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Hologram], HologramRendererFallback)
|
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Hologram], HologramRendererFallback)
|
||||||
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Microcontroller], MicrocontrollerRenderer)
|
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Microcontroller], MicrocontrollerRenderer)
|
||||||
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.PowerDistributor], PowerDistributorRenderer)
|
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.PowerDistributor], PowerDistributorRenderer)
|
||||||
|
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Printer], PrinterRenderer)
|
||||||
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Raid], RaidRenderer)
|
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Raid], RaidRenderer)
|
||||||
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.ServerRack], ServerRackRenderer)
|
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.ServerRack], ServerRackRenderer)
|
||||||
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Switch], SwitchRenderer)
|
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Switch], SwitchRenderer)
|
||||||
@ -66,6 +67,7 @@ private[oc] class Proxy extends CommonProxy {
|
|||||||
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Screen], ScreenRenderer)
|
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Screen], ScreenRenderer)
|
||||||
|
|
||||||
MinecraftForgeClient.registerItemRenderer(Items.multi, ItemRenderer)
|
MinecraftForgeClient.registerItemRenderer(Items.multi, ItemRenderer)
|
||||||
|
MinecraftForgeClient.registerItemRenderer(Items.get("print").createItemStack(1).getItem, ItemRenderer)
|
||||||
|
|
||||||
ClientRegistry.registerKeyBinding(KeyBindings.materialCosts)
|
ClientRegistry.registerKeyBinding(KeyBindings.materialCosts)
|
||||||
ClientRegistry.registerKeyBinding(KeyBindings.clipboardPaste)
|
ClientRegistry.registerKeyBinding(KeyBindings.clipboardPaste)
|
||||||
|
@ -25,6 +25,10 @@ object Textures {
|
|||||||
val guiDisassembler = new ResourceLocation(Settings.resourceDomain, "textures/gui/disassembler.png")
|
val guiDisassembler = new ResourceLocation(Settings.resourceDomain, "textures/gui/disassembler.png")
|
||||||
val guiDrone = new ResourceLocation(Settings.resourceDomain, "textures/gui/drone.png")
|
val guiDrone = new ResourceLocation(Settings.resourceDomain, "textures/gui/drone.png")
|
||||||
val guiKeyboardMissing = new ResourceLocation(Settings.resourceDomain, "textures/gui/keyboard_missing.png")
|
val guiKeyboardMissing = new ResourceLocation(Settings.resourceDomain, "textures/gui/keyboard_missing.png")
|
||||||
|
val guiPrinter = new ResourceLocation(Settings.resourceDomain, "textures/gui/printer.png")
|
||||||
|
val guiPrinterInk = new ResourceLocation(Settings.resourceDomain, "textures/gui/printer_ink.png")
|
||||||
|
val guiPrinterMaterial = new ResourceLocation(Settings.resourceDomain, "textures/gui/printer_material.png")
|
||||||
|
val guiPrinterProgress = new ResourceLocation(Settings.resourceDomain, "textures/gui/printer_progress.png")
|
||||||
val guiRaid = new ResourceLocation(Settings.resourceDomain, "textures/gui/raid.png")
|
val guiRaid = new ResourceLocation(Settings.resourceDomain, "textures/gui/raid.png")
|
||||||
val guiRange = new ResourceLocation(Settings.resourceDomain, "textures/gui/range.png")
|
val guiRange = new ResourceLocation(Settings.resourceDomain, "textures/gui/range.png")
|
||||||
val guiRobot = new ResourceLocation(Settings.resourceDomain, "textures/gui/robot.png")
|
val guiRobot = new ResourceLocation(Settings.resourceDomain, "textures/gui/robot.png")
|
||||||
|
78
src/main/scala/li/cil/oc/client/gui/Printer.scala
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package li.cil.oc.client.gui
|
||||||
|
|
||||||
|
import li.cil.oc.Localization
|
||||||
|
import li.cil.oc.client.Textures
|
||||||
|
import li.cil.oc.client.gui.widget.ProgressBar
|
||||||
|
import li.cil.oc.common.container
|
||||||
|
import li.cil.oc.common.container.ComponentSlot
|
||||||
|
import li.cil.oc.common.tileentity
|
||||||
|
import net.minecraft.entity.player.InventoryPlayer
|
||||||
|
import org.lwjgl.opengl.GL11
|
||||||
|
|
||||||
|
class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) extends DynamicGuiContainer(new container.Printer(playerInventory, printer)) {
|
||||||
|
xSize = 176
|
||||||
|
ySize = 166
|
||||||
|
|
||||||
|
private val materialBar = addWidget(new ProgressBar(40, 21) {
|
||||||
|
override def width = 62
|
||||||
|
|
||||||
|
override def height = 12
|
||||||
|
|
||||||
|
override def barTexture = Textures.guiPrinterMaterial
|
||||||
|
})
|
||||||
|
private val inkBar = addWidget(new ProgressBar(40, 53) {
|
||||||
|
override def width = 62
|
||||||
|
|
||||||
|
override def height = 12
|
||||||
|
|
||||||
|
override def barTexture = Textures.guiPrinterInk
|
||||||
|
})
|
||||||
|
private val progressBar = addWidget(new ProgressBar(105, 20) {
|
||||||
|
override def width = 46
|
||||||
|
|
||||||
|
override def height = 46
|
||||||
|
|
||||||
|
override def barTexture = Textures.guiPrinterProgress
|
||||||
|
})
|
||||||
|
|
||||||
|
private def printerContainer = inventorySlots.asInstanceOf[container.Printer]
|
||||||
|
|
||||||
|
override def initGui() {
|
||||||
|
super.initGui()
|
||||||
|
}
|
||||||
|
|
||||||
|
override def drawSecondaryForegroundLayer(mouseX: Int, mouseY: Int) = {
|
||||||
|
super.drawSecondaryForegroundLayer(mouseX, mouseY)
|
||||||
|
fontRendererObj.drawString(
|
||||||
|
Localization.localizeImmediately(printer.getInventoryName),
|
||||||
|
8, 6, 0x404040)
|
||||||
|
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS) // Me lazy... prevents NEI render glitch.
|
||||||
|
if (func_146978_c(materialBar.x, materialBar.y, materialBar.width, materialBar.height, mouseX, mouseY)) {
|
||||||
|
val tooltip = new java.util.ArrayList[String]
|
||||||
|
tooltip.add(printerContainer.amountMaterial + "/" + printer.maxAmountMaterial)
|
||||||
|
copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj)
|
||||||
|
}
|
||||||
|
if (func_146978_c(inkBar.x, inkBar.y, inkBar.width, inkBar.height, mouseX, mouseY)) {
|
||||||
|
val tooltip = new java.util.ArrayList[String]
|
||||||
|
tooltip.add(printerContainer.amountInk + "/" + printer.maxAmountInk)
|
||||||
|
copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj)
|
||||||
|
}
|
||||||
|
GL11.glPopAttrib()
|
||||||
|
}
|
||||||
|
|
||||||
|
override def drawGuiContainerBackgroundLayer(dt: Float, mouseX: Int, mouseY: Int) {
|
||||||
|
GL11.glColor3f(1, 1, 1) // Required under Linux.
|
||||||
|
mc.renderEngine.bindTexture(Textures.guiPrinter)
|
||||||
|
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize)
|
||||||
|
materialBar.level = printerContainer.amountMaterial / printer.maxAmountMaterial.toDouble
|
||||||
|
inkBar.level = printerContainer.amountInk / printer.maxAmountInk.toDouble
|
||||||
|
if (printerContainer.isPrinting) progressBar.level = (System.currentTimeMillis() % 3000) / 3000.0
|
||||||
|
else progressBar.level = 0
|
||||||
|
drawWidgets()
|
||||||
|
drawInventorySlots()
|
||||||
|
}
|
||||||
|
|
||||||
|
override protected def drawDisabledSlot(slot: ComponentSlot) {}
|
||||||
|
|
||||||
|
override def doesGuiPauseGame = false
|
||||||
|
}
|
@ -9,19 +9,21 @@ class ProgressBar(val x: Int, val y: Int) extends Widget {
|
|||||||
|
|
||||||
override def height = 12
|
override def height = 12
|
||||||
|
|
||||||
|
def barTexture = Textures.guiBar
|
||||||
|
|
||||||
var level = 0.0
|
var level = 0.0
|
||||||
|
|
||||||
def draw() {
|
def draw() {
|
||||||
if (level > 0) {
|
if (level > 0) {
|
||||||
val u0 = 0
|
val u0 = 0
|
||||||
val u1 = width / 256.0 * level
|
val u1 = level
|
||||||
val v0 = 1 - height / 256.0
|
val v0 = 0
|
||||||
val v1 = 1
|
val v1 = 1
|
||||||
val tx = owner.windowX + x
|
val tx = owner.windowX + x
|
||||||
val ty = owner.windowY + y
|
val ty = owner.windowY + y
|
||||||
val w = width * level
|
val w = width * level
|
||||||
|
|
||||||
Minecraft.getMinecraft.renderEngine.bindTexture(Textures.guiBar)
|
Minecraft.getMinecraft.renderEngine.bindTexture(barTexture)
|
||||||
val t = Tessellator.instance
|
val t = Tessellator.instance
|
||||||
t.startDrawingQuads()
|
t.startDrawingQuads()
|
||||||
t.addVertexWithUV(tx, ty, owner.windowZ, u0, v0)
|
t.addVertexWithUV(tx, ty, owner.windowZ, u0, v0)
|
||||||
|
@ -11,5 +11,5 @@ abstract class Widget {
|
|||||||
|
|
||||||
def height: Int
|
def height: Int
|
||||||
|
|
||||||
def draw()
|
def draw(): Unit
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,15 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent
|
|||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
import li.cil.oc.api
|
import li.cil.oc.api
|
||||||
import li.cil.oc.client.Textures
|
import li.cil.oc.client.Textures
|
||||||
|
import li.cil.oc.common
|
||||||
import li.cil.oc.util.BlockPosition
|
import li.cil.oc.util.BlockPosition
|
||||||
|
import li.cil.oc.util.ExtendedAABB._
|
||||||
import li.cil.oc.util.ExtendedBlock._
|
import li.cil.oc.util.ExtendedBlock._
|
||||||
import li.cil.oc.util.ExtendedWorld._
|
import li.cil.oc.util.ExtendedWorld._
|
||||||
import li.cil.oc.util.RenderState
|
import li.cil.oc.util.RenderState
|
||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
import net.minecraft.client.renderer.OpenGlHelper
|
import net.minecraft.client.renderer.OpenGlHelper
|
||||||
|
import net.minecraft.client.renderer.RenderGlobal
|
||||||
import net.minecraft.client.renderer.Tessellator
|
import net.minecraft.client.renderer.Tessellator
|
||||||
import net.minecraft.util.MovingObjectPosition.MovingObjectType
|
import net.minecraft.util.MovingObjectPosition.MovingObjectType
|
||||||
import net.minecraftforge.client.event.DrawBlockHighlightEvent
|
import net.minecraftforge.client.event.DrawBlockHighlightEvent
|
||||||
@ -95,5 +98,33 @@ object HighlightRenderer {
|
|||||||
GL11.glPopMatrix()
|
GL11.glPopMatrix()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hitInfo.typeOfHit == MovingObjectType.BLOCK) e.player.getEntityWorld.getTileEntity(hitInfo.blockX, hitInfo.blockY, hitInfo.blockZ) match {
|
||||||
|
case print: common.tileentity.Print =>
|
||||||
|
val pos = e.player.getPosition(e.partialTicks)
|
||||||
|
val expansion = 0.002f
|
||||||
|
|
||||||
|
// See RenderGlobal.drawSelectionBox.
|
||||||
|
GL11.glEnable(GL11.GL_BLEND)
|
||||||
|
OpenGlHelper.glBlendFunc(770, 771, 1, 0)
|
||||||
|
GL11.glColor4f(0, 0, 0, 0.4f)
|
||||||
|
GL11.glLineWidth(2)
|
||||||
|
GL11.glDisable(GL11.GL_TEXTURE_2D)
|
||||||
|
GL11.glDepthMask(false)
|
||||||
|
|
||||||
|
for (shape <- if (print.state) print.data.stateOn else print.data.stateOff) {
|
||||||
|
val bounds = shape.bounds.rotateTowards(print.facing)
|
||||||
|
RenderGlobal.drawOutlinedBoundingBox(bounds.copy().expand(expansion, expansion, expansion)
|
||||||
|
.offset(e.target.blockX, e.target.blockY, e.target.blockZ)
|
||||||
|
.offset(-pos.xCoord, -pos.yCoord, -pos.zCoord), -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
GL11.glDepthMask(true)
|
||||||
|
GL11.glEnable(GL11.GL_TEXTURE_2D)
|
||||||
|
GL11.glDisable(GL11.GL_BLEND)
|
||||||
|
|
||||||
|
e.setCanceled(true)
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package li.cil.oc.client.renderer.block
|
package li.cil.oc.client.renderer.block
|
||||||
|
|
||||||
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler
|
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler
|
||||||
import cpw.mods.fml.common.Loader
|
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
import li.cil.oc.client.Textures
|
|
||||||
import li.cil.oc.client.renderer.tileentity.RobotRenderer
|
import li.cil.oc.client.renderer.tileentity.RobotRenderer
|
||||||
import li.cil.oc.common.block._
|
import li.cil.oc.common.block._
|
||||||
import li.cil.oc.common.tileentity
|
import li.cil.oc.common.tileentity
|
||||||
@ -54,6 +52,13 @@ object BlockRenderer extends ISimpleBlockRenderingHandler {
|
|||||||
Tessellator.instance.draw()
|
Tessellator.instance.draw()
|
||||||
|
|
||||||
RenderState.checkError(getClass.getName + ".renderInventoryBlock: hologram")
|
RenderState.checkError(getClass.getName + ".renderInventoryBlock: hologram")
|
||||||
|
case printer: Printer =>
|
||||||
|
GL11.glTranslatef(-0.5f, -0.5f, -0.5f)
|
||||||
|
Tessellator.instance.startDrawingQuads()
|
||||||
|
Printer.render(block, metadata, renderer)
|
||||||
|
Tessellator.instance.draw()
|
||||||
|
|
||||||
|
RenderState.checkError(getClass.getName + ".renderInventoryBlock: printer")
|
||||||
case _ =>
|
case _ =>
|
||||||
block match {
|
block match {
|
||||||
case simple: SimpleBlock =>
|
case simple: SimpleBlock =>
|
||||||
@ -82,7 +87,7 @@ object BlockRenderer extends ISimpleBlockRenderingHandler {
|
|||||||
override def renderWorldBlock(world: IBlockAccess, x: Int, y: Int, z: Int, block: Block, modelId: Int, realRenderer: RenderBlocks) = {
|
override def renderWorldBlock(world: IBlockAccess, x: Int, y: Int, z: Int, block: Block, modelId: Int, realRenderer: RenderBlocks) = {
|
||||||
RenderState.checkError(getClass.getName + ".renderWorldBlock: entering (aka: wasntme)")
|
RenderState.checkError(getClass.getName + ".renderWorldBlock: entering (aka: wasntme)")
|
||||||
|
|
||||||
val renderer = patchedRenderer(realRenderer)
|
val renderer = patchedRenderer(realRenderer, block)
|
||||||
world.getTileEntity(x, y, z) match {
|
world.getTileEntity(x, y, z) match {
|
||||||
case cable: tileentity.Cable =>
|
case cable: tileentity.Cable =>
|
||||||
Cable.render(world, x, y, z, block, renderer)
|
Cable.render(world, x, y, z, block, renderer)
|
||||||
@ -91,85 +96,25 @@ object BlockRenderer extends ISimpleBlockRenderingHandler {
|
|||||||
|
|
||||||
true
|
true
|
||||||
case keyboard: tileentity.Keyboard =>
|
case keyboard: tileentity.Keyboard =>
|
||||||
if (keyboard.facing == ForgeDirection.UP || keyboard.facing == ForgeDirection.DOWN) {
|
val result = Keyboard.render(keyboard, x, y, z, block, renderer)
|
||||||
keyboard.yaw match {
|
|
||||||
case ForgeDirection.NORTH =>
|
|
||||||
renderer.uvRotateTop = 0
|
|
||||||
renderer.uvRotateBottom = 0
|
|
||||||
case ForgeDirection.SOUTH =>
|
|
||||||
renderer.uvRotateTop = 3
|
|
||||||
renderer.uvRotateBottom = 3
|
|
||||||
case ForgeDirection.WEST =>
|
|
||||||
renderer.uvRotateTop = 2
|
|
||||||
renderer.uvRotateBottom = 1
|
|
||||||
case ForgeDirection.EAST =>
|
|
||||||
renderer.uvRotateTop = 1
|
|
||||||
renderer.uvRotateBottom = 2
|
|
||||||
case _ => throw new AssertionError("Impossible yaw value on keyboard.")
|
|
||||||
}
|
|
||||||
if (keyboard.facing == ForgeDirection.DOWN) {
|
|
||||||
renderer.flipTexture = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val result = renderer.renderStandardBlock(block, x, y, z)
|
|
||||||
renderer.uvRotateTop = 0
|
|
||||||
renderer.uvRotateBottom = 0
|
|
||||||
renderer.flipTexture = false
|
|
||||||
|
|
||||||
RenderState.checkError(getClass.getName + ".renderWorldBlock: keyboard")
|
RenderState.checkError(getClass.getName + ".renderWorldBlock: keyboard")
|
||||||
|
|
||||||
result
|
result
|
||||||
|
case print: tileentity.Print =>
|
||||||
|
Print.render(print, x, y, z, block, renderer)
|
||||||
|
|
||||||
|
RenderState.checkError(getClass.getName + ".renderWorldBlock: print")
|
||||||
|
|
||||||
|
true
|
||||||
|
case printer: tileentity.Printer =>
|
||||||
|
Printer.render(block, x, y, z, renderer)
|
||||||
|
|
||||||
|
RenderState.checkError(getClass.getName + ".renderWorldBlock: printer")
|
||||||
|
|
||||||
|
true
|
||||||
case rack: tileentity.ServerRack =>
|
case rack: tileentity.ServerRack =>
|
||||||
val previousRenderAllFaces = renderer.renderAllFaces
|
ServerRack.render(rack, x, y, z, block, renderer)
|
||||||
val u1 = 1 / 16f
|
|
||||||
val u2 = 15 / 16f
|
|
||||||
val v1 = 2 / 16f
|
|
||||||
val v2 = 14 / 16f
|
|
||||||
val fs = 3 / 16f
|
|
||||||
|
|
||||||
// Top and bottom.
|
|
||||||
renderer.renderAllFaces = true
|
|
||||||
renderer.setRenderBounds(0, 0, 0, 1, v1, 1)
|
|
||||||
renderer.renderStandardBlock(block, x, y, z)
|
|
||||||
renderer.setRenderBounds(0, v2, 0, 1, 1, 1)
|
|
||||||
renderer.renderStandardBlock(block, x, y, z)
|
|
||||||
|
|
||||||
// Sides.
|
|
||||||
val front = rack.facing
|
|
||||||
def renderSide(side: ForgeDirection, lx: Double, lz: Double, hx: Double, hz: Double) {
|
|
||||||
if (side == front) {
|
|
||||||
for (i <- 0 until 4 if rack.isPresent(i).isDefined) {
|
|
||||||
side match {
|
|
||||||
case ForgeDirection.WEST =>
|
|
||||||
renderer.setRenderBounds(lx, v2 - (i + 1) * fs, lz + u1, u2, v2 - i * fs, hz - u1)
|
|
||||||
case ForgeDirection.EAST =>
|
|
||||||
renderer.setRenderBounds(u1, v2 - (i + 1) * fs, lz + u1, hx, v2 - i * fs, hz - u1)
|
|
||||||
case ForgeDirection.NORTH =>
|
|
||||||
renderer.setRenderBounds(lx + u1, v2 - (i + 1) * fs, lz, hx - u1, v2 - i * fs, u2)
|
|
||||||
case ForgeDirection.SOUTH =>
|
|
||||||
renderer.setRenderBounds(lx + u1, v2 - (i + 1) * fs, u1, hx - u1, v2 - i * fs, hz)
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
renderer.renderStandardBlock(block, x, y, z)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
val isBack = front == side.getOpposite
|
|
||||||
if (isBack) {
|
|
||||||
renderer.setOverrideBlockTexture(Textures.ServerRack.icons(ForgeDirection.NORTH.ordinal))
|
|
||||||
}
|
|
||||||
renderer.setRenderBounds(lx, v1, lz, hx, v2, hz)
|
|
||||||
renderer.renderStandardBlock(block, x, y, z)
|
|
||||||
renderer.clearOverrideBlockTexture()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderSide(ForgeDirection.WEST, 0, 0, u1, 1)
|
|
||||||
renderSide(ForgeDirection.EAST, u2, 0, 1, 1)
|
|
||||||
renderSide(ForgeDirection.NORTH, 0, 0, 1, u1)
|
|
||||||
renderSide(ForgeDirection.SOUTH, 0, u2, 1, 1)
|
|
||||||
|
|
||||||
renderer.renderAllFaces = previousRenderAllFaces
|
|
||||||
|
|
||||||
RenderState.checkError(getClass.getName + ".renderWorldBlock: rack")
|
RenderState.checkError(getClass.getName + ".renderWorldBlock: rack")
|
||||||
|
|
||||||
@ -195,9 +140,8 @@ object BlockRenderer extends ISimpleBlockRenderingHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val isOneSevenTwo = Loader.instance.getMinecraftModContainer.getVersion == "1.7.2"
|
// The texture flip this works around only seems to occur for blocks with custom block renderers?
|
||||||
|
def patchedRenderer(renderer: RenderBlocks, block: Block) = if (block.isInstanceOf[Hologram] || block.isInstanceOf[Printer]) {
|
||||||
def patchedRenderer(renderer: RenderBlocks) = if (isOneSevenTwo) {
|
|
||||||
PatchedRenderBlocks.blockAccess = renderer.blockAccess
|
PatchedRenderBlocks.blockAccess = renderer.blockAccess
|
||||||
PatchedRenderBlocks.overrideBlockTexture = renderer.overrideBlockTexture
|
PatchedRenderBlocks.overrideBlockTexture = renderer.overrideBlockTexture
|
||||||
PatchedRenderBlocks.flipTexture = renderer.flipTexture
|
PatchedRenderBlocks.flipTexture = renderer.flipTexture
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package li.cil.oc.client.renderer.block
|
||||||
|
|
||||||
|
import li.cil.oc.common.tileentity
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
import net.minecraft.client.renderer.RenderBlocks
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection
|
||||||
|
|
||||||
|
object Keyboard {
|
||||||
|
def render(keyboard: tileentity.Keyboard, x: Int, y: Int, z: Int, block: Block, renderer: RenderBlocks): Boolean = {
|
||||||
|
if (keyboard.facing == ForgeDirection.UP || keyboard.facing == ForgeDirection.DOWN) {
|
||||||
|
keyboard.yaw match {
|
||||||
|
case ForgeDirection.NORTH =>
|
||||||
|
renderer.uvRotateTop = 0
|
||||||
|
renderer.uvRotateBottom = 0
|
||||||
|
case ForgeDirection.SOUTH =>
|
||||||
|
renderer.uvRotateTop = 3
|
||||||
|
renderer.uvRotateBottom = 3
|
||||||
|
case ForgeDirection.WEST =>
|
||||||
|
renderer.uvRotateTop = 2
|
||||||
|
renderer.uvRotateBottom = 1
|
||||||
|
case ForgeDirection.EAST =>
|
||||||
|
renderer.uvRotateTop = 1
|
||||||
|
renderer.uvRotateBottom = 2
|
||||||
|
case _ => throw new AssertionError("Impossible yaw value on keyboard.")
|
||||||
|
}
|
||||||
|
if (keyboard.facing == ForgeDirection.DOWN) {
|
||||||
|
renderer.flipTexture = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val result = renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
renderer.uvRotateTop = 0
|
||||||
|
renderer.uvRotateBottom = 0
|
||||||
|
renderer.flipTexture = false
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
29
src/main/scala/li/cil/oc/client/renderer/block/Print.scala
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package li.cil.oc.client.renderer.block
|
||||||
|
|
||||||
|
import li.cil.oc.common.tileentity
|
||||||
|
import li.cil.oc.util.ExtendedAABB._
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
import net.minecraft.client.Minecraft
|
||||||
|
import net.minecraft.client.renderer.RenderBlocks
|
||||||
|
import net.minecraft.client.renderer.texture.TextureMap
|
||||||
|
import net.minecraft.util.IIcon
|
||||||
|
|
||||||
|
object Print {
|
||||||
|
def render(print: tileentity.Print, x: Int, y: Int, z: Int, block: Block, renderer: RenderBlocks): Unit = {
|
||||||
|
for (shape <- if (print.state) print.data.stateOn else print.data.stateOff) {
|
||||||
|
val bounds = shape.bounds.rotateTowards(print.facing)
|
||||||
|
renderer.setOverrideBlockTexture(resolveTexture(shape.texture))
|
||||||
|
renderer.setRenderBounds(
|
||||||
|
bounds.minX, bounds.minY, bounds.minZ,
|
||||||
|
bounds.maxX, bounds.maxY, bounds.maxZ)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
}
|
||||||
|
renderer.clearOverrideBlockTexture()
|
||||||
|
}
|
||||||
|
|
||||||
|
def resolveTexture(name: String): IIcon = {
|
||||||
|
val icon = Minecraft.getMinecraft.getTextureMapBlocks.getTextureExtry(name)
|
||||||
|
if (icon == null) Minecraft.getMinecraft.getTextureManager.getTexture(TextureMap.locationBlocksTexture).asInstanceOf[TextureMap].getAtlasSprite("missingno")
|
||||||
|
else icon
|
||||||
|
}
|
||||||
|
}
|
68
src/main/scala/li/cil/oc/client/renderer/block/Printer.scala
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package li.cil.oc.client.renderer.block
|
||||||
|
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
import net.minecraft.client.renderer.RenderBlocks
|
||||||
|
|
||||||
|
object Printer {
|
||||||
|
def render(block: Block, x: Int, y: Int, z: Int, renderer: RenderBlocks) {
|
||||||
|
val previousRenderAllFaces = renderer.renderAllFaces
|
||||||
|
renderer.renderAllFaces = true
|
||||||
|
|
||||||
|
// Bottom.
|
||||||
|
renderer.setRenderBounds(0, 0, 0, 1, 8 / 16f, 1)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
// Corners.
|
||||||
|
renderer.setRenderBounds(0 / 16f, 8 / 16f, 0 / 16f, 3 / 16f, 16 / 16f, 3 / 16f)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
renderer.setRenderBounds(13 / 16f, 8 / 16f, 0 / 16f, 16 / 16f, 16 / 16f, 3 / 16f)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
renderer.setRenderBounds(0 / 16f, 8 / 16f, 13 / 16f, 3 / 16f, 16 / 16f, 16 / 16f)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
renderer.setRenderBounds(13 / 16f, 8 / 16f, 13 / 16f, 16 / 16f, 16 / 16f, 16 / 16f)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
// Top.
|
||||||
|
renderer.setRenderBounds(3 / 16f, 13 / 16f, 0 / 16f, 13 / 16f, 16 / 16f, 3 / 16f)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
renderer.setRenderBounds(3 / 16f, 13 / 16f, 13 / 16f, 13 / 16f, 16 / 16f, 16 / 16f)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
renderer.setRenderBounds(0 / 16f, 13 / 16f, 3 / 16f, 3 / 16f, 16 / 16f, 13 / 16f)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
renderer.setRenderBounds(13 / 16f, 13 / 16f, 3 / 16f, 16 / 16f, 16 / 16f, 13 / 16f)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
|
||||||
|
renderer.renderAllFaces = previousRenderAllFaces
|
||||||
|
}
|
||||||
|
|
||||||
|
def render(block: Block, metadata: Int, renderer: RenderBlocks) {
|
||||||
|
// Bottom.
|
||||||
|
renderer.setRenderBounds(0, 0, 0, 1, 8 / 16f, 1)
|
||||||
|
renderAllFaces(block, metadata, renderer)
|
||||||
|
// Corners.
|
||||||
|
renderer.setRenderBounds(0 / 16f, 8 / 16f, 0 / 16f, 3 / 16f, 16 / 16f, 3 / 16f)
|
||||||
|
renderAllFaces(block, metadata, renderer)
|
||||||
|
renderer.setRenderBounds(13 / 16f, 8 / 16f, 0 / 16f, 16 / 16f, 16 / 16f, 3 / 16f)
|
||||||
|
renderAllFaces(block, metadata, renderer)
|
||||||
|
renderer.setRenderBounds(0 / 16f, 8 / 16f, 13 / 16f, 3 / 16f, 16 / 16f, 16 / 16f)
|
||||||
|
renderAllFaces(block, metadata, renderer)
|
||||||
|
renderer.setRenderBounds(13 / 16f, 8 / 16f, 13 / 16f, 16 / 16f, 16 / 16f, 16 / 16f)
|
||||||
|
renderAllFaces(block, metadata, renderer)
|
||||||
|
// Top.
|
||||||
|
renderer.setRenderBounds(3 / 16f, 13 / 16f, 0 / 16f, 13 / 16f, 16 / 16f, 3 / 16f)
|
||||||
|
renderAllFaces(block, metadata, renderer)
|
||||||
|
renderer.setRenderBounds(3 / 16f, 13 / 16f, 13 / 16f, 13 / 16f, 16 / 16f, 16 / 16f)
|
||||||
|
renderAllFaces(block, metadata, renderer)
|
||||||
|
renderer.setRenderBounds(0 / 16f, 13 / 16f, 3 / 16f, 3 / 16f, 16 / 16f, 13 / 16f)
|
||||||
|
renderAllFaces(block, metadata, renderer)
|
||||||
|
renderer.setRenderBounds(13 / 16f, 13 / 16f, 3 / 16f, 16 / 16f, 16 / 16f, 13 / 16f)
|
||||||
|
renderAllFaces(block, metadata, renderer)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def renderAllFaces(block: Block, metadata: Int, renderer: RenderBlocks): Unit = {
|
||||||
|
BlockRenderer.renderFaceYPos(block, metadata, renderer)
|
||||||
|
BlockRenderer.renderFaceYNeg(block, metadata, renderer)
|
||||||
|
BlockRenderer.renderFaceXPos(block, metadata, renderer)
|
||||||
|
BlockRenderer.renderFaceXNeg(block, metadata, renderer)
|
||||||
|
BlockRenderer.renderFaceZPos(block, metadata, renderer)
|
||||||
|
BlockRenderer.renderFaceZNeg(block, metadata, renderer)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package li.cil.oc.client.renderer.block
|
||||||
|
|
||||||
|
import li.cil.oc.client.Textures
|
||||||
|
import li.cil.oc.common.tileentity
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
import net.minecraft.client.renderer.RenderBlocks
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection
|
||||||
|
|
||||||
|
object ServerRack {
|
||||||
|
def render(rack: tileentity.ServerRack, x: Int, y: Int, z: Int, block: Block, renderer: RenderBlocks): Unit = {
|
||||||
|
val previousRenderAllFaces = renderer.renderAllFaces
|
||||||
|
val u1 = 1 / 16f
|
||||||
|
val u2 = 15 / 16f
|
||||||
|
val v1 = 2 / 16f
|
||||||
|
val v2 = 14 / 16f
|
||||||
|
val fs = 3 / 16f
|
||||||
|
|
||||||
|
// Top and bottom.
|
||||||
|
renderer.renderAllFaces = true
|
||||||
|
renderer.setRenderBounds(0, 0, 0, 1, v1, 1)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
renderer.setRenderBounds(0, v2, 0, 1, 1, 1)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
|
||||||
|
// Sides.
|
||||||
|
val front = rack.facing
|
||||||
|
def renderSide(side: ForgeDirection, lx: Double, lz: Double, hx: Double, hz: Double) {
|
||||||
|
if (side == front) {
|
||||||
|
for (i <- 0 until 4 if rack.isPresent(i).isDefined) {
|
||||||
|
side match {
|
||||||
|
case ForgeDirection.WEST =>
|
||||||
|
renderer.setRenderBounds(lx, v2 - (i + 1) * fs, lz + u1, u2, v2 - i * fs, hz - u1)
|
||||||
|
case ForgeDirection.EAST =>
|
||||||
|
renderer.setRenderBounds(u1, v2 - (i + 1) * fs, lz + u1, hx, v2 - i * fs, hz - u1)
|
||||||
|
case ForgeDirection.NORTH =>
|
||||||
|
renderer.setRenderBounds(lx + u1, v2 - (i + 1) * fs, lz, hx - u1, v2 - i * fs, u2)
|
||||||
|
case ForgeDirection.SOUTH =>
|
||||||
|
renderer.setRenderBounds(lx + u1, v2 - (i + 1) * fs, u1, hx - u1, v2 - i * fs, hz)
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val isBack = front == side.getOpposite
|
||||||
|
if (isBack) {
|
||||||
|
renderer.setOverrideBlockTexture(Textures.ServerRack.icons(ForgeDirection.NORTH.ordinal))
|
||||||
|
}
|
||||||
|
renderer.setRenderBounds(lx, v1, lz, hx, v2, hz)
|
||||||
|
renderer.renderStandardBlock(block, x, y, z)
|
||||||
|
renderer.clearOverrideBlockTexture()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSide(ForgeDirection.WEST, 0, 0, u1, 1)
|
||||||
|
renderSide(ForgeDirection.EAST, u2, 0, 1, 1)
|
||||||
|
renderSide(ForgeDirection.NORTH, 0, 0, 1, u1)
|
||||||
|
renderSide(ForgeDirection.SOUTH, 0, u2, 1, 1)
|
||||||
|
|
||||||
|
renderer.renderAllFaces = previousRenderAllFaces
|
||||||
|
}
|
||||||
|
}
|
@ -4,13 +4,16 @@ import li.cil.oc.Settings
|
|||||||
import li.cil.oc.api
|
import li.cil.oc.api
|
||||||
import li.cil.oc.api.detail.ItemInfo
|
import li.cil.oc.api.detail.ItemInfo
|
||||||
import li.cil.oc.client.Textures
|
import li.cil.oc.client.Textures
|
||||||
|
import li.cil.oc.client.renderer.block.Print
|
||||||
import li.cil.oc.client.renderer.entity.DroneRenderer
|
import li.cil.oc.client.renderer.entity.DroneRenderer
|
||||||
|
import li.cil.oc.common.item.data.PrintData
|
||||||
import li.cil.oc.integration.opencomputers.Item
|
import li.cil.oc.integration.opencomputers.Item
|
||||||
import li.cil.oc.util.RenderState
|
import li.cil.oc.util.RenderState
|
||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
import net.minecraft.client.gui.ScaledResolution
|
import net.minecraft.client.gui.ScaledResolution
|
||||||
import net.minecraft.client.renderer.entity.RenderItem
|
import net.minecraft.client.renderer.entity.RenderItem
|
||||||
import net.minecraft.client.renderer.entity.RenderManager
|
import net.minecraft.client.renderer.entity.RenderManager
|
||||||
|
import net.minecraft.client.renderer.texture.TextureMap
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.util.AxisAlignedBB
|
import net.minecraft.util.AxisAlignedBB
|
||||||
import net.minecraft.util.EnumChatFormatting
|
import net.minecraft.util.EnumChatFormatting
|
||||||
@ -32,6 +35,7 @@ object ItemRenderer extends IItemRenderer {
|
|||||||
|
|
||||||
lazy val floppy = api.Items.get("floppy")
|
lazy val floppy = api.Items.get("floppy")
|
||||||
lazy val lootDisk = api.Items.get("lootDisk")
|
lazy val lootDisk = api.Items.get("lootDisk")
|
||||||
|
lazy val print = api.Items.get("print")
|
||||||
|
|
||||||
def bounds = AxisAlignedBB.getBoundingBox(-0.1, -0.1, -0.1, 0.1, 0.1, 0.1)
|
def bounds = AxisAlignedBB.getBoundingBox(-0.1, -0.1, -0.1, 0.1, 0.1, 0.1)
|
||||||
|
|
||||||
@ -48,11 +52,13 @@ object ItemRenderer extends IItemRenderer {
|
|||||||
val descriptor = api.Items.get(stack)
|
val descriptor = api.Items.get(stack)
|
||||||
(renderType == ItemRenderType.EQUIPPED && isUpgrade(api.Items.get(stack))) ||
|
(renderType == ItemRenderType.EQUIPPED && isUpgrade(api.Items.get(stack))) ||
|
||||||
(renderType == ItemRenderType.INVENTORY && isFloppy(api.Items.get(stack))) ||
|
(renderType == ItemRenderType.INVENTORY && isFloppy(api.Items.get(stack))) ||
|
||||||
((renderType == ItemRenderType.INVENTORY || renderType == ItemRenderType.ENTITY || renderType == ItemRenderType.EQUIPPED || renderType == ItemRenderType.EQUIPPED_FIRST_PERSON) && descriptor == drone)
|
((renderType == ItemRenderType.INVENTORY || renderType == ItemRenderType.ENTITY || renderType == ItemRenderType.EQUIPPED || renderType == ItemRenderType.EQUIPPED_FIRST_PERSON) && descriptor == drone) ||
|
||||||
|
((renderType == ItemRenderType.INVENTORY || renderType == ItemRenderType.ENTITY || renderType == ItemRenderType.EQUIPPED || renderType == ItemRenderType.EQUIPPED_FIRST_PERSON) && api.Items.get(stack) == print)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def shouldUseRenderHelper(renderType: ItemRenderType, stack: ItemStack, helper: ItemRendererHelper) =
|
override def shouldUseRenderHelper(renderType: ItemRenderType, stack: ItemStack, helper: ItemRendererHelper) =
|
||||||
if (renderType == ItemRenderType.ENTITY) true
|
if (renderType == ItemRenderType.ENTITY) true
|
||||||
|
else if (renderType == ItemRenderType.INVENTORY && api.Items.get(stack) == print) helper == ItemRendererHelper.INVENTORY_BLOCK
|
||||||
// Note: it's easier to revert changes introduced by this "helper" than by
|
// Note: it's easier to revert changes introduced by this "helper" than by
|
||||||
// the code that applies if no helper is used...
|
// the code that applies if no helper is used...
|
||||||
else helper == ItemRendererHelper.EQUIPPED_BLOCK
|
else helper == ItemRendererHelper.EQUIPPED_BLOCK
|
||||||
@ -116,6 +122,7 @@ object ItemRenderer extends IItemRenderer {
|
|||||||
|
|
||||||
RenderState.checkError("ItemRenderer.renderItem: floppy")
|
RenderState.checkError("ItemRenderer.renderItem: floppy")
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (descriptor == drone) {
|
else if (descriptor == drone) {
|
||||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
|
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
|
||||||
GL11.glPushMatrix()
|
GL11.glPushMatrix()
|
||||||
@ -144,6 +151,26 @@ object ItemRenderer extends IItemRenderer {
|
|||||||
RenderState.checkError("ItemRenderer.renderItem: drone")
|
RenderState.checkError("ItemRenderer.renderItem: drone")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (descriptor == print) {
|
||||||
|
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
|
||||||
|
GL11.glPushMatrix()
|
||||||
|
|
||||||
|
if (renderType == ItemRenderType.ENTITY) {
|
||||||
|
GL11.glTranslatef(-0.5f, 0, -0.5f)
|
||||||
|
}
|
||||||
|
|
||||||
|
val data = new PrintData(stack)
|
||||||
|
Minecraft.getMinecraft.renderEngine.bindTexture(TextureMap.locationBlocksTexture)
|
||||||
|
for (shape <- data.stateOff) {
|
||||||
|
drawShape(shape)
|
||||||
|
}
|
||||||
|
|
||||||
|
GL11.glPopMatrix()
|
||||||
|
GL11.glPopAttrib()
|
||||||
|
|
||||||
|
RenderState.checkError("ItemRenderer.renderItem: print")
|
||||||
|
}
|
||||||
|
|
||||||
RenderState.checkError("ItemRenderer.renderItem: leaving")
|
RenderState.checkError("ItemRenderer.renderItem: leaving")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,4 +234,79 @@ object ItemRenderer extends IItemRenderer {
|
|||||||
|
|
||||||
GL11.glEnd()
|
GL11.glEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def drawShape(shape: PrintData.Shape) {
|
||||||
|
val bounds = shape.bounds
|
||||||
|
val texture = Print.resolveTexture(shape.texture)
|
||||||
|
|
||||||
|
GL11.glBegin(GL11.GL_QUADS)
|
||||||
|
|
||||||
|
// Front.
|
||||||
|
GL11.glNormal3f(0, 0, 1)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.minY * 16))
|
||||||
|
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.minY * 16))
|
||||||
|
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.maxY * 16))
|
||||||
|
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.maxY * 16))
|
||||||
|
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ)
|
||||||
|
|
||||||
|
// Back.
|
||||||
|
GL11.glNormal3f(0, 0, -1)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.minY * 16))
|
||||||
|
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.minZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.minY * 16))
|
||||||
|
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.minZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.maxY * 16))
|
||||||
|
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.minZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.maxY * 16))
|
||||||
|
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.minZ)
|
||||||
|
|
||||||
|
// Top.
|
||||||
|
GL11.glNormal3f(0, 1, 0)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.maxZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.minZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.minZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.minZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.minZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.maxZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ)
|
||||||
|
|
||||||
|
// Bottom.
|
||||||
|
GL11.glNormal3f(0, -1, 0)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.maxZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minX * 16), texture.getInterpolatedV(bounds.minZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.minZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.minZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.minZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxX * 16), texture.getInterpolatedV(bounds.maxZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ)
|
||||||
|
|
||||||
|
// Left.
|
||||||
|
GL11.glNormal3f(1, 0, 0)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxY * 16), texture.getInterpolatedV(bounds.maxZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.maxZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minY * 16), texture.getInterpolatedV(bounds.maxZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.maxZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minY * 16), texture.getInterpolatedV(bounds.minZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.maxX, bounds.minY, bounds.minZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxY * 16), texture.getInterpolatedV(bounds.minZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.maxX, bounds.maxY, bounds.minZ)
|
||||||
|
|
||||||
|
// Right.
|
||||||
|
GL11.glNormal3f(-1, 0, 0)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minY * 16), texture.getInterpolatedV(bounds.maxZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.maxZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxY * 16), texture.getInterpolatedV(bounds.maxZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.maxZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.maxY * 16), texture.getInterpolatedV(bounds.minZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.minX, bounds.maxY, bounds.minZ)
|
||||||
|
GL11.glTexCoord2f(texture.getInterpolatedU(bounds.minY * 16), texture.getInterpolatedV(bounds.minZ * 16))
|
||||||
|
GL11.glVertex3d(bounds.minX, bounds.minY, bounds.minZ)
|
||||||
|
|
||||||
|
GL11.glEnd()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package li.cil.oc.client.renderer.tileentity
|
||||||
|
|
||||||
|
import li.cil.oc.common.tileentity.Printer
|
||||||
|
import li.cil.oc.util.RenderState
|
||||||
|
import net.minecraft.client.renderer.OpenGlHelper
|
||||||
|
import net.minecraft.client.renderer.entity.RenderItem
|
||||||
|
import net.minecraft.client.renderer.entity.RenderManager
|
||||||
|
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
|
||||||
|
import net.minecraft.entity.item.EntityItem
|
||||||
|
import net.minecraft.tileentity.TileEntity
|
||||||
|
import org.lwjgl.opengl.GL11
|
||||||
|
|
||||||
|
object PrinterRenderer extends TileEntitySpecialRenderer {
|
||||||
|
override def renderTileEntityAt(tileEntity: TileEntity, x: Double, y: Double, z: Double, f: Float) {
|
||||||
|
RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)")
|
||||||
|
|
||||||
|
val printer = tileEntity.asInstanceOf[Printer]
|
||||||
|
if (printer.data.stateOff.size > 0) {
|
||||||
|
val stack = printer.data.createItemStack()
|
||||||
|
|
||||||
|
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS)
|
||||||
|
GL11.glPushMatrix()
|
||||||
|
|
||||||
|
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
|
||||||
|
|
||||||
|
// GL11.glTranslated(-0.5, -0.5, -0.5)
|
||||||
|
GL11.glRotated((System.currentTimeMillis() % 20000) / 20000.0 * 360, 0, 1, 0)
|
||||||
|
// GL11.glTranslated(0.5, 0.5, 0.5)
|
||||||
|
|
||||||
|
val brightness = printer.world.getLightBrightnessForSkyBlocks(printer.x, printer.y, printer.z, 0)
|
||||||
|
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightness % 65536, brightness / 65536)
|
||||||
|
|
||||||
|
// This is very 'meh', but item frames do it like this, too!
|
||||||
|
val entity = new EntityItem(printer.world, 0, 0, 0, stack)
|
||||||
|
entity.hoverStart = 0
|
||||||
|
RenderItem.renderInFrame = true
|
||||||
|
RenderManager.instance.renderEntityWithPosYaw(entity, 0, -0.1, 0, 0, 0)
|
||||||
|
RenderItem.renderInFrame = false
|
||||||
|
|
||||||
|
GL11.glPopMatrix()
|
||||||
|
GL11.glPopAttrib()
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving")
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,8 @@ abstract class GuiHandler extends IGuiHandler {
|
|||||||
new container.Disassembler(player.inventory, t)
|
new container.Disassembler(player.inventory, t)
|
||||||
case t: tileentity.DiskDrive if id == GuiType.DiskDrive.id =>
|
case t: tileentity.DiskDrive if id == GuiType.DiskDrive.id =>
|
||||||
new container.DiskDrive(player.inventory, t)
|
new container.DiskDrive(player.inventory, t)
|
||||||
|
case t: tileentity.Printer if id == GuiType.Printer.id =>
|
||||||
|
new container.Printer(player.inventory, t)
|
||||||
case t: tileentity.Raid if id == GuiType.Raid.id =>
|
case t: tileentity.Raid if id == GuiType.Raid.id =>
|
||||||
new container.Raid(player.inventory, t)
|
new container.Raid(player.inventory, t)
|
||||||
case t: tileentity.RobotProxy if id == GuiType.Robot.id =>
|
case t: tileentity.RobotProxy if id == GuiType.Robot.id =>
|
||||||
|
@ -21,6 +21,7 @@ object GuiType extends ScalaEnum {
|
|||||||
val Disassembler = new EnumVal { def name = "Disassembler"; def subType = GuiType.Category.Block }
|
val Disassembler = new EnumVal { def name = "Disassembler"; def subType = GuiType.Category.Block }
|
||||||
val DiskDrive = new EnumVal { def name = "DiskDrive"; def subType = GuiType.Category.Block }
|
val DiskDrive = new EnumVal { def name = "DiskDrive"; def subType = GuiType.Category.Block }
|
||||||
val Drone = new EnumVal { def name = "Drone"; def subType = GuiType.Category.Entity }
|
val Drone = new EnumVal { def name = "Drone"; def subType = GuiType.Category.Entity }
|
||||||
|
val Printer = new EnumVal { def name = "Printer"; def subType = GuiType.Category.Block }
|
||||||
val Rack = new EnumVal { def name = "Rack"; def subType = GuiType.Category.Block }
|
val Rack = new EnumVal { def name = "Rack"; def subType = GuiType.Category.Block }
|
||||||
val Raid = new EnumVal { def name = "Raid"; def subType = GuiType.Category.Block }
|
val Raid = new EnumVal { def name = "Raid"; def subType = GuiType.Category.Block }
|
||||||
val Robot = new EnumVal { def name = "Robot"; def subType = GuiType.Category.Block }
|
val Robot = new EnumVal { def name = "Robot"; def subType = GuiType.Category.Block }
|
||||||
|
@ -9,6 +9,7 @@ object PacketType extends Enumeration {
|
|||||||
ColorChange,
|
ColorChange,
|
||||||
ComputerState,
|
ComputerState,
|
||||||
ComputerUserList,
|
ComputerUserList,
|
||||||
|
ContainerUpdate,
|
||||||
DisassemblerActiveChange,
|
DisassemblerActiveChange,
|
||||||
FileSystemActivity,
|
FileSystemActivity,
|
||||||
FloppyChange,
|
FloppyChange,
|
||||||
@ -20,6 +21,7 @@ object PacketType extends Enumeration {
|
|||||||
HologramTranslation,
|
HologramTranslation,
|
||||||
PetVisibility, // Goes both ways.
|
PetVisibility, // Goes both ways.
|
||||||
PowerState,
|
PowerState,
|
||||||
|
PrinterState,
|
||||||
RaidStateChange,
|
RaidStateChange,
|
||||||
RedstoneState,
|
RedstoneState,
|
||||||
RobotAnimateSwing,
|
RobotAnimateSwing,
|
||||||
|
@ -5,6 +5,7 @@ import li.cil.oc.api.driver
|
|||||||
object Slot {
|
object Slot {
|
||||||
val None = driver.item.Slot.None
|
val None = driver.item.Slot.None
|
||||||
val Any = driver.item.Slot.Any
|
val Any = driver.item.Slot.Any
|
||||||
|
val Filtered = "filtered"
|
||||||
|
|
||||||
val Card = driver.item.Slot.Card
|
val Card = driver.item.Slot.Card
|
||||||
val ComponentBus = driver.item.Slot.ComponentBus
|
val ComponentBus = driver.item.Slot.ComponentBus
|
||||||
|
@ -5,6 +5,7 @@ import java.util
|
|||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
import li.cil.oc.api
|
import li.cil.oc.api
|
||||||
import li.cil.oc.client.KeyBindings
|
import li.cil.oc.client.KeyBindings
|
||||||
|
import li.cil.oc.common.item.data.PrintData
|
||||||
import li.cil.oc.common.item.data.RobotData
|
import li.cil.oc.common.item.data.RobotData
|
||||||
import li.cil.oc.common.tileentity
|
import li.cil.oc.common.tileentity
|
||||||
import li.cil.oc.util.ItemCosts
|
import li.cil.oc.util.ItemCosts
|
||||||
@ -47,6 +48,14 @@ class Item(value: Block) extends ItemBlock(value) {
|
|||||||
|
|
||||||
override def getMetadata(itemDamage: Int) = itemDamage
|
override def getMetadata(itemDamage: Int) = itemDamage
|
||||||
|
|
||||||
|
override def getItemStackDisplayName(stack: ItemStack): String = {
|
||||||
|
if (api.Items.get(stack) == api.Items.get("print")) {
|
||||||
|
val data = new PrintData(stack)
|
||||||
|
data.label.getOrElse(super.getItemStackDisplayName(stack))
|
||||||
|
}
|
||||||
|
else super.getItemStackDisplayName(stack)
|
||||||
|
}
|
||||||
|
|
||||||
override def getUnlocalizedName = block match {
|
override def getUnlocalizedName = block match {
|
||||||
case simple: SimpleBlock => simple.getUnlocalizedName
|
case simple: SimpleBlock => simple.getUnlocalizedName
|
||||||
case _ => Settings.namespace + "tile"
|
case _ => Settings.namespace + "tile"
|
||||||
|
@ -102,8 +102,10 @@ class Microcontroller(protected implicit val tileTag: ClassTag[tileentity.Microc
|
|||||||
|
|
||||||
override protected def doCustomInit(tileEntity: tileentity.Microcontroller, player: EntityLivingBase, stack: ItemStack): Unit = {
|
override protected def doCustomInit(tileEntity: tileentity.Microcontroller, player: EntityLivingBase, stack: ItemStack): Unit = {
|
||||||
super.doCustomInit(tileEntity, player, stack)
|
super.doCustomInit(tileEntity, player, stack)
|
||||||
tileEntity.info.load(stack)
|
if (!tileEntity.world.isRemote) {
|
||||||
tileEntity.snooperNode.changeBuffer(tileEntity.info.storedEnergy - tileEntity.snooperNode.localBuffer)
|
tileEntity.info.load(stack)
|
||||||
|
tileEntity.snooperNode.changeBuffer(tileEntity.info.storedEnergy - tileEntity.snooperNode.localBuffer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected def doCustomDrops(tileEntity: tileentity.Microcontroller, player: EntityPlayer, willHarvest: Boolean): Unit = {
|
override protected def doCustomDrops(tileEntity: tileentity.Microcontroller, player: EntityPlayer, willHarvest: Boolean): Unit = {
|
||||||
|
160
src/main/scala/li/cil/oc/common/block/Print.scala
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
package li.cil.oc.common.block
|
||||||
|
|
||||||
|
import java.util
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
|
import li.cil.oc.Settings
|
||||||
|
import li.cil.oc.common.item.data.PrintData
|
||||||
|
import li.cil.oc.common.tileentity
|
||||||
|
import li.cil.oc.integration.util.NEI
|
||||||
|
import li.cil.oc.util.ExtendedAABB
|
||||||
|
import li.cil.oc.util.ExtendedAABB._
|
||||||
|
import net.minecraft.entity.Entity
|
||||||
|
import net.minecraft.entity.EntityLivingBase
|
||||||
|
import net.minecraft.entity.EnumCreatureType
|
||||||
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.util.AxisAlignedBB
|
||||||
|
import net.minecraft.util.MovingObjectPosition
|
||||||
|
import net.minecraft.util.Vec3
|
||||||
|
import net.minecraft.world.IBlockAccess
|
||||||
|
import net.minecraft.world.World
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection
|
||||||
|
|
||||||
|
import scala.collection.convert.WrapAsJava._
|
||||||
|
import scala.reflect.ClassTag
|
||||||
|
|
||||||
|
class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends RedstoneAware with traits.SpecialBlock with traits.CustomDrops[tileentity.Print] {
|
||||||
|
setLightOpacity(0)
|
||||||
|
setHardness(1)
|
||||||
|
setCreativeTab(null)
|
||||||
|
NEI.hide(this)
|
||||||
|
setBlockTextureName(Settings.resourceDomain + "GenericTop")
|
||||||
|
|
||||||
|
override protected def tooltipBody(metadata: Int, stack: ItemStack, player: EntityPlayer, tooltip: util.List[String], advanced: Boolean): Unit = {
|
||||||
|
super.tooltipBody(metadata, stack, player, tooltip, advanced)
|
||||||
|
val data = new PrintData(stack)
|
||||||
|
data.tooltip.foreach(s => tooltip.addAll(s.lines.toIterable))
|
||||||
|
}
|
||||||
|
|
||||||
|
override def shouldSideBeRendered(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true
|
||||||
|
|
||||||
|
override def isBlockSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = isSideSolid(world, x, y, z, side)
|
||||||
|
|
||||||
|
override def isSideSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection): Boolean = {
|
||||||
|
world.getTileEntity(x, y, z) match {
|
||||||
|
case print: tileentity.Print =>
|
||||||
|
val shapes = if (print.state) print.data.stateOn else print.data.stateOff
|
||||||
|
for (shape <- shapes) {
|
||||||
|
val bounds = shape.bounds
|
||||||
|
val fullX = bounds.minX == 0 && bounds.maxX == 1
|
||||||
|
val fullY = bounds.minY == 0 && bounds.maxY == 1
|
||||||
|
val fullZ = bounds.minZ == 0 && bounds.maxZ == 1
|
||||||
|
if (side match {
|
||||||
|
case ForgeDirection.DOWN => bounds.minY == 0 && fullX && fullZ
|
||||||
|
case ForgeDirection.UP => bounds.maxY == 1 && fullX && fullZ
|
||||||
|
case ForgeDirection.NORTH => bounds.minZ == 0 && fullX && fullY
|
||||||
|
case ForgeDirection.SOUTH => bounds.maxZ == 1 && fullX && fullY
|
||||||
|
case ForgeDirection.WEST => bounds.minX == 0 && fullY && fullZ
|
||||||
|
case ForgeDirection.EAST => bounds.maxX == 1 && fullY && fullZ
|
||||||
|
case _ => false
|
||||||
|
}) return true
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
override def getPickBlock(target: MovingObjectPosition, world: World, x: Int, y: Int, z: Int, player: EntityPlayer): ItemStack = {
|
||||||
|
world.getTileEntity(x, y, z) match {
|
||||||
|
case print: tileentity.Print => print.data.createItemStack()
|
||||||
|
case _ => null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def addCollisionBoxesToList(world: World, x: Int, y: Int, z: Int, mask: AxisAlignedBB, list: util.List[_], entity: Entity): Unit = {
|
||||||
|
world.getTileEntity(x, y, z) match {
|
||||||
|
case print: tileentity.Print =>
|
||||||
|
def add[T](list: util.List[T], value: Any) = list.add(value.asInstanceOf[T])
|
||||||
|
val shapes = if (print.state) print.data.stateOn else print.data.stateOff
|
||||||
|
for (shape <- shapes) {
|
||||||
|
val bounds = shape.bounds.rotateTowards(print.facing).offset(x, y, z)
|
||||||
|
if (bounds.intersectsWith(mask)) {
|
||||||
|
add(list, bounds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case _ => super.addCollisionBoxesToList(world, x, y, z, mask, list, entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override protected def intersect(world: World, x: Int, y: Int, z: Int, origin: Vec3, direction: Vec3): MovingObjectPosition = {
|
||||||
|
world.getTileEntity(x, y, z) match {
|
||||||
|
case print: tileentity.Print =>
|
||||||
|
var closestDistance = Double.PositiveInfinity
|
||||||
|
var closest: Option[MovingObjectPosition] = None
|
||||||
|
for (shape <- if (print.state) print.data.stateOn else print.data.stateOff) {
|
||||||
|
val bounds = shape.bounds.rotateTowards(print.facing).offset(x, y, z)
|
||||||
|
val hit = bounds.calculateIntercept(origin, direction)
|
||||||
|
if (hit != null) {
|
||||||
|
val distance = hit.hitVec.distanceTo(origin)
|
||||||
|
if (distance < closestDistance) {
|
||||||
|
closestDistance = distance
|
||||||
|
closest = Option(hit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closest.map(hit => new MovingObjectPosition(x, y, z, hit.sideHit, hit.hitVec)).orNull
|
||||||
|
case _ => super.intersect(world, x, y, z, origin, direction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override protected def doSetBlockBoundsBasedOnState(world: IBlockAccess, x: Int, y: Int, z: Int): Unit = {
|
||||||
|
world.getTileEntity(x, y, z) match {
|
||||||
|
case print: tileentity.Print => setBlockBounds(if (print.state) print.boundsOn else print.boundsOff)
|
||||||
|
case _ => super.doSetBlockBoundsBasedOnState(world, x, y, z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setBlockBoundsForItemRender(metadata: Int): Unit = {
|
||||||
|
setBlockBounds(ExtendedAABB.unitBounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def canCreatureSpawn(creature: EnumCreatureType, world: IBlockAccess, x: Int, y: Int, z: Int): Boolean = true
|
||||||
|
|
||||||
|
override def tickRate(world: World) = 20
|
||||||
|
|
||||||
|
override def updateTick(world: World, x: Int, y: Int, z: Int, rng: Random): Unit = {
|
||||||
|
if (!world.isRemote) world.getTileEntity(x, y, z) match {
|
||||||
|
case print: tileentity.Print => if (print.state) print.toggleState()
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
override def hasTileEntity(metadata: Int) = true
|
||||||
|
|
||||||
|
override def createTileEntity(world: World, metadata: Int) = new tileentity.Print()
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
override def onBlockActivated(world: World, x: Int, y: Int, z: Int, player: EntityPlayer, side: ForgeDirection, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
|
||||||
|
world.getTileEntity(x, y, z) match {
|
||||||
|
case print: tileentity.Print => print.activate()
|
||||||
|
case _ => super.onBlockActivated(world, x, y, z, player, side, hitX, hitY, hitZ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override protected def doCustomInit(tileEntity: tileentity.Print, player: EntityLivingBase, stack: ItemStack): Unit = {
|
||||||
|
super.doCustomInit(tileEntity, player, stack)
|
||||||
|
tileEntity.data.load(stack)
|
||||||
|
tileEntity.updateBounds()
|
||||||
|
}
|
||||||
|
|
||||||
|
override protected def doCustomDrops(tileEntity: tileentity.Print, player: EntityPlayer, willHarvest: Boolean): Unit = {
|
||||||
|
super.doCustomDrops(tileEntity, player, willHarvest)
|
||||||
|
if (!player.capabilities.isCreativeMode) {
|
||||||
|
dropBlockAsItem(tileEntity.world, tileEntity.x, tileEntity.y, tileEntity.z, tileEntity.data.createItemStack())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
src/main/scala/li/cil/oc/common/block/Printer.scala
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package li.cil.oc.common.block
|
||||||
|
|
||||||
|
import li.cil.oc.Settings
|
||||||
|
import li.cil.oc.client.Textures
|
||||||
|
import li.cil.oc.common.GuiType
|
||||||
|
import li.cil.oc.common.tileentity
|
||||||
|
import net.minecraft.client.renderer.texture.IIconRegister
|
||||||
|
import net.minecraft.world.IBlockAccess
|
||||||
|
import net.minecraft.world.World
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection
|
||||||
|
|
||||||
|
class Printer extends SimpleBlock with traits.SpecialBlock with traits.StateAware with traits.GUI {
|
||||||
|
override protected def customTextures = Array(
|
||||||
|
None,
|
||||||
|
Some("PrinterTop"),
|
||||||
|
Some("PrinterSide"),
|
||||||
|
Some("PrinterSide"),
|
||||||
|
Some("PrinterSide"),
|
||||||
|
Some("PrinterSide")
|
||||||
|
)
|
||||||
|
|
||||||
|
override def registerBlockIcons(iconRegister: IIconRegister) = {
|
||||||
|
super.registerBlockIcons(iconRegister)
|
||||||
|
Textures.Assembler.iconSideAssembling = iconRegister.registerIcon(Settings.resourceDomain + ":AssemblerSideAssembling")
|
||||||
|
Textures.Assembler.iconSideOn = iconRegister.registerIcon(Settings.resourceDomain + ":AssemblerSideOn")
|
||||||
|
Textures.Assembler.iconTopOn = iconRegister.registerIcon(Settings.resourceDomain + ":AssemblerTopOn")
|
||||||
|
}
|
||||||
|
|
||||||
|
override def isBlockSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = side == ForgeDirection.DOWN
|
||||||
|
|
||||||
|
override def isSideSolid(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = side == ForgeDirection.DOWN
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
override def guiType = GuiType.Printer
|
||||||
|
|
||||||
|
override def hasTileEntity(metadata: Int) = true
|
||||||
|
|
||||||
|
override def createTileEntity(world: World, metadata: Int) = new tileentity.Printer()
|
||||||
|
}
|
@ -55,14 +55,16 @@ class Raid(protected implicit val tileTag: ClassTag[tileentity.Raid]) extends Si
|
|||||||
|
|
||||||
override protected def doCustomInit(tileEntity: tileentity.Raid, player: EntityLivingBase, stack: ItemStack): Unit = {
|
override protected def doCustomInit(tileEntity: tileentity.Raid, player: EntityLivingBase, stack: ItemStack): Unit = {
|
||||||
super.doCustomInit(tileEntity, player, stack)
|
super.doCustomInit(tileEntity, player, stack)
|
||||||
val data = new RaidData(stack)
|
if (!tileEntity.world.isRemote) {
|
||||||
for (i <- 0 until math.min(data.disks.length, tileEntity.getSizeInventory)) {
|
val data = new RaidData(stack)
|
||||||
tileEntity.setInventorySlotContents(i, data.disks(i))
|
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) {
|
data.label.foreach(tileEntity.label.setLabel)
|
||||||
tileEntity.tryCreateRaid(data.filesystem.getCompoundTag("node").getString("address"))
|
if (!data.filesystem.hasNoTags) {
|
||||||
tileEntity.filesystem.foreach(_.load(data.filesystem))
|
tileEntity.tryCreateRaid(data.filesystem.getCompoundTag("node").getString("address"))
|
||||||
|
tileEntity.filesystem.foreach(_.load(data.filesystem))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,11 @@ abstract class RedstoneAware extends SimpleBlock with IRedNetOmniNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
world.getTileEntity(x, y, z) match {
|
world.getTileEntity(x, y, z) match {
|
||||||
case redstone: tileentity.traits.RedstoneAware => redstone.checkRedstoneInputChanged()
|
case redstone: tileentity.traits.RedstoneAware =>
|
||||||
|
if (redstone.canUpdate)
|
||||||
|
redstone.checkRedstoneInputChanged()
|
||||||
|
else
|
||||||
|
ForgeDirection.VALID_DIRECTIONS.foreach(redstone.updateRedstoneInput)
|
||||||
case _ => // Ignore.
|
case _ => // Ignore.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import net.minecraftforge.common.util.ForgeDirection
|
|||||||
|
|
||||||
class SimpleBlock(material: Material = Material.iron) extends Block(material) {
|
class SimpleBlock(material: Material = Material.iron) extends Block(material) {
|
||||||
setHardness(2f)
|
setHardness(2f)
|
||||||
|
setResistance(5)
|
||||||
setCreativeTab(CreativeTab)
|
setCreativeTab(CreativeTab)
|
||||||
|
|
||||||
var showInItemList = true
|
var showInItemList = true
|
||||||
|
@ -31,12 +31,10 @@ trait CustomDrops[Tile <: TileEntity] extends SimpleBlock {
|
|||||||
|
|
||||||
override def onBlockPlacedBy(world: World, x: Int, y: Int, z: Int, player: EntityLivingBase, stack: ItemStack): Unit = {
|
override def onBlockPlacedBy(world: World, x: Int, y: Int, z: Int, player: EntityLivingBase, stack: ItemStack): Unit = {
|
||||||
super.onBlockPlacedBy(world, x, y, z, player, stack)
|
super.onBlockPlacedBy(world, x, y, z, player, stack)
|
||||||
if (!world.isRemote) {
|
val matcher = tileTag
|
||||||
val matcher = tileTag
|
world.getTileEntity(x, y, z) match {
|
||||||
world.getTileEntity(x, y, z) match {
|
case matcher(tileEntity) => doCustomInit(tileEntity, player, stack)
|
||||||
case matcher(tileEntity) => doCustomInit(tileEntity, player, stack)
|
case _ =>
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ import li.cil.oc.common
|
|||||||
import li.cil.oc.common.InventorySlots.InventorySlot
|
import li.cil.oc.common.InventorySlots.InventorySlot
|
||||||
import li.cil.oc.common.template.AssemblerTemplates
|
import li.cil.oc.common.template.AssemblerTemplates
|
||||||
import li.cil.oc.common.tileentity
|
import li.cil.oc.common.tileentity
|
||||||
import li.cil.oc.util.SideTracker
|
|
||||||
import net.minecraft.entity.player.InventoryPlayer
|
import net.minecraft.entity.player.InventoryPlayer
|
||||||
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
|
||||||
class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Assembler) extends Player(playerInventory, assembler) {
|
class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Assembler) extends Player(playerInventory, assembler) {
|
||||||
// Computer case.
|
// Computer case.
|
||||||
@ -67,40 +67,16 @@ class Assembler(playerInventory: InventoryPlayer, val assembler: tileentity.Asse
|
|||||||
// Show the player's inventory.
|
// Show the player's inventory.
|
||||||
addPlayerInventorySlots(8, 110)
|
addPlayerInventorySlots(8, 110)
|
||||||
|
|
||||||
var isAssembling = false
|
def isAssembling = synchronizedData.getBoolean("isAssembling")
|
||||||
var assemblyProgress = 0.0
|
|
||||||
var assemblyRemainingTime = 0
|
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
def assemblyProgress = synchronizedData.getDouble("assemblyProgress")
|
||||||
override def updateProgressBar(id: Int, value: Int) {
|
|
||||||
super.updateProgressBar(id, value)
|
|
||||||
if (id == 0) {
|
|
||||||
isAssembling = value == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id == 1) {
|
def assemblyRemainingTime = synchronizedData.getInteger("assemblyRemainingTime")
|
||||||
assemblyProgress = value / 5.0
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id == 2) {
|
override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
|
||||||
assemblyRemainingTime = value
|
synchronizedData.setBoolean("isAssembling", assembler.isAssembling)
|
||||||
}
|
synchronizedData.setDouble("assemblyProgress", assembler.progress)
|
||||||
|
synchronizedData.setInteger("assemblyRemainingTime", assembler.timeRemaining)
|
||||||
|
super.detectCustomDataChanges(nbt)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
override def detectAndSendChanges() {
|
|
||||||
super.detectAndSendChanges()
|
|
||||||
if (SideTracker.isServer) {
|
|
||||||
if (isAssembling != assembler.isAssembling) {
|
|
||||||
isAssembling = assembler.isAssembling
|
|
||||||
sendProgressBarUpdate(0, if (isAssembling) 1 else 0)
|
|
||||||
}
|
|
||||||
val timeRemaining = assembler.timeRemaining
|
|
||||||
if (math.abs(assembler.progress - assemblyProgress) > 0.2 || assemblyRemainingTime != timeRemaining) {
|
|
||||||
assemblyProgress = assembler.progress
|
|
||||||
assemblyRemainingTime = timeRemaining
|
|
||||||
sendProgressBarUpdate(1, (assemblyProgress * 5).toInt)
|
|
||||||
sendProgressBarUpdate(2, timeRemaining)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,32 +1,17 @@
|
|||||||
package li.cil.oc.common.container
|
package li.cil.oc.common.container
|
||||||
|
|
||||||
import cpw.mods.fml.relauncher.Side
|
|
||||||
import cpw.mods.fml.relauncher.SideOnly
|
|
||||||
import li.cil.oc.common.tileentity
|
import li.cil.oc.common.tileentity
|
||||||
import li.cil.oc.util.SideTracker
|
|
||||||
import net.minecraft.entity.player.InventoryPlayer
|
import net.minecraft.entity.player.InventoryPlayer
|
||||||
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
|
||||||
class Disassembler(playerInventory: InventoryPlayer, val disassembler: tileentity.Disassembler) extends Player(playerInventory, disassembler) {
|
class Disassembler(playerInventory: InventoryPlayer, val disassembler: tileentity.Disassembler) extends Player(playerInventory, disassembler) {
|
||||||
addSlotToContainer(80, 35, "ocitem")
|
addSlotToContainer(80, 35, "ocitem")
|
||||||
addPlayerInventorySlots(8, 84)
|
addPlayerInventorySlots(8, 84)
|
||||||
|
|
||||||
var disassemblyProgress = 0.0
|
def disassemblyProgress = synchronizedData.getDouble("disassemblyProgress")
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
|
||||||
override def updateProgressBar(id: Int, value: Int) {
|
synchronizedData.setDouble("disassemblyProgress", disassembler.progress)
|
||||||
super.updateProgressBar(id, value)
|
super.detectCustomDataChanges(nbt)
|
||||||
if (id == 0) {
|
|
||||||
disassemblyProgress = value / 5.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def detectAndSendChanges() {
|
|
||||||
super.detectAndSendChanges()
|
|
||||||
if (SideTracker.isServer) {
|
|
||||||
if (math.abs(disassembler.progress - disassemblyProgress) > 0.2) {
|
|
||||||
disassemblyProgress = disassembler.progress
|
|
||||||
sendProgressBarUpdate(0, (disassemblyProgress * 5).toInt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ class DynamicComponentSlot(val container: Player, inventory: IInventory, index:
|
|||||||
|
|
||||||
override def getSlotStackLimit =
|
override def getSlotStackLimit =
|
||||||
slot match {
|
slot match {
|
||||||
case common.Slot.Tool | common.Slot.Any => super.getSlotStackLimit
|
case common.Slot.Tool | common.Slot.Any | common.Slot.Filtered => super.getSlotStackLimit
|
||||||
case common.Slot.None => 0
|
case common.Slot.None => 0
|
||||||
case _ => 1
|
case _ => 1
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,18 @@ package li.cil.oc.common.container
|
|||||||
import li.cil.oc.common
|
import li.cil.oc.common
|
||||||
import li.cil.oc.common.InventorySlots.InventorySlot
|
import li.cil.oc.common.InventorySlots.InventorySlot
|
||||||
import li.cil.oc.common.Tier
|
import li.cil.oc.common.Tier
|
||||||
|
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||||
import li.cil.oc.util.SideTracker
|
import li.cil.oc.util.SideTracker
|
||||||
import net.minecraft.entity.player.EntityPlayer
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP
|
||||||
import net.minecraft.entity.player.InventoryPlayer
|
import net.minecraft.entity.player.InventoryPlayer
|
||||||
import net.minecraft.inventory.Container
|
import net.minecraft.inventory.Container
|
||||||
import net.minecraft.inventory.ICrafting
|
import net.minecraft.inventory.ICrafting
|
||||||
import net.minecraft.inventory.IInventory
|
import net.minecraft.inventory.IInventory
|
||||||
import net.minecraft.inventory.Slot
|
import net.minecraft.inventory.Slot
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.nbt.NBTBase
|
||||||
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
|
||||||
import scala.collection.convert.WrapAsScala._
|
import scala.collection.convert.WrapAsScala._
|
||||||
|
|
||||||
@ -133,4 +137,104 @@ abstract class Player(val playerInventory: InventoryPlayer, val otherInventory:
|
|||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def detectAndSendChanges(): Unit = {
|
||||||
|
super.detectAndSendChanges()
|
||||||
|
if (SideTracker.isServer) {
|
||||||
|
val nbt = new NBTTagCompound()
|
||||||
|
detectCustomDataChanges(nbt)
|
||||||
|
for (entry <- crafters) entry match {
|
||||||
|
case player: EntityPlayerMP => ServerPacketSender.sendContainerUpdate(this, nbt, player)
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for custom value synchronization, because shorts simply don't cut it most of the time.
|
||||||
|
protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
|
||||||
|
val delta = synchronizedData.getDelta
|
||||||
|
if (delta != null && !delta.hasNoTags) {
|
||||||
|
nbt.setTag("delta", delta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def updateCustomData(nbt: NBTTagCompound): Unit = {
|
||||||
|
if (nbt.hasKey("delta")) {
|
||||||
|
val delta = nbt.getCompoundTag("delta")
|
||||||
|
delta.func_150296_c().foreach {
|
||||||
|
case key: String => synchronizedData.setTag(key, delta.getTag(key))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class SynchronizedData extends NBTTagCompound {
|
||||||
|
private var delta = new NBTTagCompound()
|
||||||
|
|
||||||
|
def getDelta: NBTTagCompound = this.synchronized {
|
||||||
|
if (delta.hasNoTags) null
|
||||||
|
else {
|
||||||
|
val result = delta
|
||||||
|
delta = new NBTTagCompound()
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setTag(key: String, value: NBTBase): Unit = this.synchronized {
|
||||||
|
if (!value.equals(getTag(key))) delta.setTag(key, value)
|
||||||
|
super.setTag(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setByte(key: String, value: Byte): Unit = this.synchronized {
|
||||||
|
if (value != getByte(key)) delta.setByte(key, value)
|
||||||
|
super.setByte(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setShort(key: String, value: Short): Unit = this.synchronized {
|
||||||
|
if (value != getShort(key)) delta.setShort(key, value)
|
||||||
|
super.setShort(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setInteger(key: String, value: Int): Unit = this.synchronized {
|
||||||
|
if (value != getInteger(key)) delta.setInteger(key, value)
|
||||||
|
super.setInteger(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setLong(key: String, value: Long): Unit = this.synchronized {
|
||||||
|
if (value != getLong(key)) delta.setLong(key, value)
|
||||||
|
super.setLong(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setFloat(key: String, value: Float): Unit = this.synchronized {
|
||||||
|
if (value != getFloat(key)) delta.setFloat(key, value)
|
||||||
|
super.setFloat(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setDouble(key: String, value: Double): Unit = this.synchronized {
|
||||||
|
if (value != getDouble(key)) delta.setDouble(key, value)
|
||||||
|
super.setDouble(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setString(key: String, value: String): Unit = this.synchronized {
|
||||||
|
if (value != getString(key)) delta.setString(key, value)
|
||||||
|
super.setString(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setByteArray(key: String, value: Array[Byte]): Unit = this.synchronized {
|
||||||
|
if (value.deep != getByteArray(key).deep) delta.setByteArray(key, value)
|
||||||
|
super.setByteArray(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setIntArray(key: String, value: Array[Int]): Unit = this.synchronized {
|
||||||
|
if (value.deep != getIntArray(key).deep) delta.setIntArray(key, value)
|
||||||
|
super.setIntArray(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def setBoolean(key: String, value: Boolean): Unit = this.synchronized {
|
||||||
|
if (value != getBoolean(key)) delta.setBoolean(key, value)
|
||||||
|
super.setBoolean(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected val synchronizedData = new SynchronizedData()
|
||||||
|
|
||||||
}
|
}
|
28
src/main/scala/li/cil/oc/common/container/Printer.scala
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package li.cil.oc.common.container
|
||||||
|
|
||||||
|
import li.cil.oc.common.Slot
|
||||||
|
import li.cil.oc.common.tileentity
|
||||||
|
import net.minecraft.entity.player.InventoryPlayer
|
||||||
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
|
||||||
|
class Printer(playerInventory: InventoryPlayer, val printer: tileentity.Printer) extends Player(playerInventory, printer) {
|
||||||
|
addSlotToContainer(18, 19, Slot.Filtered)
|
||||||
|
addSlotToContainer(18, 51, Slot.Filtered)
|
||||||
|
addSlotToContainer(152, 35)
|
||||||
|
|
||||||
|
// Show the player's inventory.
|
||||||
|
addPlayerInventorySlots(8, 84)
|
||||||
|
|
||||||
|
def isPrinting = synchronizedData.getBoolean("isPrinting")
|
||||||
|
|
||||||
|
def amountMaterial = synchronizedData.getInteger("amountMaterial")
|
||||||
|
|
||||||
|
def amountInk = synchronizedData.getInteger("amountInk")
|
||||||
|
|
||||||
|
override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
|
||||||
|
synchronizedData.setBoolean("isPrinting", printer.isPrinting)
|
||||||
|
synchronizedData.setInteger("amountMaterial", printer.amountMaterial)
|
||||||
|
synchronizedData.setInteger("amountInk", printer.amountInk)
|
||||||
|
super.detectCustomDataChanges(nbt)
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@ class StaticComponentSlot(val container: Player, inventory: IInventory, index: I
|
|||||||
|
|
||||||
override def getSlotStackLimit =
|
override def getSlotStackLimit =
|
||||||
slot match {
|
slot match {
|
||||||
case common.Slot.Tool | common.Slot.Any => super.getSlotStackLimit
|
case common.Slot.Tool | common.Slot.Any | common.Slot.Filtered => super.getSlotStackLimit
|
||||||
case common.Slot.None => 0
|
case common.Slot.None => 0
|
||||||
case _ => 1
|
case _ => 1
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package li.cil.oc.common.container
|
package li.cil.oc.common.container
|
||||||
|
|
||||||
import cpw.mods.fml.common.FMLCommonHandler
|
|
||||||
import li.cil.oc.common.Slot
|
import li.cil.oc.common.Slot
|
||||||
import li.cil.oc.common.tileentity
|
import li.cil.oc.common.tileentity
|
||||||
import net.minecraft.entity.player.InventoryPlayer
|
import net.minecraft.entity.player.InventoryPlayer
|
||||||
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
|
||||||
class Switch(playerInventory: InventoryPlayer, switch: tileentity.Switch) extends Player(playerInventory, switch) {
|
class Switch(playerInventory: InventoryPlayer, switch: tileentity.Switch) extends Player(playerInventory, switch) {
|
||||||
addSlotToContainer(151, 15, Slot.CPU)
|
addSlotToContainer(151, 15, Slot.CPU)
|
||||||
@ -11,58 +11,22 @@ class Switch(playerInventory: InventoryPlayer, switch: tileentity.Switch) extend
|
|||||||
addSlotToContainer(151, 53, Slot.HDD)
|
addSlotToContainer(151, 53, Slot.HDD)
|
||||||
addPlayerInventorySlots(8, 84)
|
addPlayerInventorySlots(8, 84)
|
||||||
|
|
||||||
var relayDelay = 0
|
def relayDelay = synchronizedData.getInteger("relayDelay")
|
||||||
|
|
||||||
var relayAmount = 0
|
def relayAmount = synchronizedData.getInteger("relayAmount")
|
||||||
|
|
||||||
var maxQueueSize = 0
|
def maxQueueSize = synchronizedData.getInteger("maxQueueSize")
|
||||||
|
|
||||||
var packetsPerCycleAvg = 0
|
def packetsPerCycleAvg = synchronizedData.getInteger("packetsPerCycleAvg")
|
||||||
|
|
||||||
var queueSize = 0
|
def queueSize = synchronizedData.getInteger("queueSize")
|
||||||
|
|
||||||
override def updateProgressBar(id: Int, value: Int) {
|
override protected def detectCustomDataChanges(nbt: NBTTagCompound): Unit = {
|
||||||
super.updateProgressBar(id, value)
|
synchronizedData.setInteger("relayDelay", switch.relayDelay)
|
||||||
if (id == 0) {
|
synchronizedData.setInteger("relayAmount", switch.relayAmount)
|
||||||
relayDelay = value
|
synchronizedData.setInteger("maxQueueSize", switch.maxQueueSize)
|
||||||
}
|
synchronizedData.setInteger("packetsPerCycleAvg", switch.packetsPerCycleAvg())
|
||||||
else if (id == 1) {
|
synchronizedData.setInteger("queueSize", switch.queue.size)
|
||||||
relayAmount = value
|
super.detectCustomDataChanges(nbt)
|
||||||
}
|
|
||||||
else if (id == 2) {
|
|
||||||
maxQueueSize = value
|
|
||||||
}
|
|
||||||
else if (id == 3) {
|
|
||||||
packetsPerCycleAvg = value
|
|
||||||
}
|
|
||||||
else if (id == 4) {
|
|
||||||
queueSize = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def detectAndSendChanges() {
|
|
||||||
super.detectAndSendChanges()
|
|
||||||
if (FMLCommonHandler.instance.getEffectiveSide.isServer) {
|
|
||||||
if (switch.relayDelay != relayDelay) {
|
|
||||||
relayDelay = switch.relayDelay
|
|
||||||
sendProgressBarUpdate(0, relayDelay)
|
|
||||||
}
|
|
||||||
if (switch.relayAmount != relayAmount) {
|
|
||||||
relayAmount = switch.relayAmount
|
|
||||||
sendProgressBarUpdate(1, relayAmount)
|
|
||||||
}
|
|
||||||
if (switch.maxQueueSize != maxQueueSize) {
|
|
||||||
maxQueueSize = switch.maxQueueSize
|
|
||||||
sendProgressBarUpdate(2, maxQueueSize)
|
|
||||||
}
|
|
||||||
if (switch.packetsPerCycleAvg() != packetsPerCycleAvg) {
|
|
||||||
packetsPerCycleAvg = switch.packetsPerCycleAvg()
|
|
||||||
sendProgressBarUpdate(3, packetsPerCycleAvg)
|
|
||||||
}
|
|
||||||
if (switch.queue.size != queueSize) {
|
|
||||||
queueSize = switch.queue.size
|
|
||||||
sendProgressBarUpdate(4, queueSize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@ object Blocks {
|
|||||||
GameRegistry.registerTileEntity(classOf[tileentity.MotionSensor], Settings.namespace + "motion_sensor")
|
GameRegistry.registerTileEntity(classOf[tileentity.MotionSensor], Settings.namespace + "motion_sensor")
|
||||||
GameRegistry.registerTileEntity(classOf[tileentity.PowerConverter], Settings.namespace + "power_converter")
|
GameRegistry.registerTileEntity(classOf[tileentity.PowerConverter], Settings.namespace + "power_converter")
|
||||||
GameRegistry.registerTileEntity(classOf[tileentity.PowerDistributor], Settings.namespace + "power_distributor")
|
GameRegistry.registerTileEntity(classOf[tileentity.PowerDistributor], Settings.namespace + "power_distributor")
|
||||||
|
GameRegistry.registerTileEntity(classOf[tileentity.Print], Settings.namespace + "print")
|
||||||
|
GameRegistry.registerTileEntity(classOf[tileentity.Printer], Settings.namespace + "printer")
|
||||||
GameRegistry.registerTileEntity(classOf[tileentity.Raid], Settings.namespace + "raid")
|
GameRegistry.registerTileEntity(classOf[tileentity.Raid], Settings.namespace + "raid")
|
||||||
GameRegistry.registerTileEntity(classOf[tileentity.Redstone], Settings.namespace + "redstone")
|
GameRegistry.registerTileEntity(classOf[tileentity.Redstone], Settings.namespace + "redstone")
|
||||||
GameRegistry.registerTileEntity(classOf[tileentity.RobotProxy], Settings.namespace + "robot")
|
GameRegistry.registerTileEntity(classOf[tileentity.RobotProxy], Settings.namespace + "robot")
|
||||||
@ -81,5 +83,9 @@ object Blocks {
|
|||||||
// v1.4.2
|
// v1.4.2
|
||||||
Recipes.addBlock(new Raid(), "raid", "oc:raid")
|
Recipes.addBlock(new Raid(), "raid", "oc:raid")
|
||||||
Items.registerBlock(new Microcontroller(), "microcontroller")
|
Items.registerBlock(new Microcontroller(), "microcontroller")
|
||||||
|
|
||||||
|
// v1.5.4
|
||||||
|
Items.registerBlock(new Print(), "print")
|
||||||
|
Items.registerBlock(new Printer(), "printer")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,5 +470,11 @@ object Items extends ItemAPI {
|
|||||||
// 1.4.7
|
// 1.4.7
|
||||||
Recipes.addMultiItem(new item.TabletCase(multi, Tier.Two), "tabletCase2", "oc:tabletCase2")
|
Recipes.addMultiItem(new item.TabletCase(multi, Tier.Two), "tabletCase2", "oc:tabletCase2")
|
||||||
registerItem(new item.TabletCase(multi, Tier.Four), "tabletCaseCreative")
|
registerItem(new item.TabletCase(multi, Tier.Four), "tabletCaseCreative")
|
||||||
|
|
||||||
|
// 1.5.4
|
||||||
|
Recipes.addMultiItem(new item.InkCartridgeEmpty(multi), "inkCartridgeEmpty", "oc:inkCartridgeEmpty")
|
||||||
|
Recipes.addMultiItem(new item.InkCartridge(multi), "inkCartridge", "oc:inkCartridge")
|
||||||
|
Recipes.addMultiItem(new item.Chamelium(multi), "chamelium", "oc:chamelium")
|
||||||
|
Recipes.addMultiItem(new item.TexturePicker(multi), "texturePicker", "oc:texturePicker")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
src/main/scala/li/cil/oc/common/item/Chamelium.scala
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package li.cil.oc.common.item
|
||||||
|
|
||||||
|
class Chamelium(val parent: Delegator) extends Delegate
|
5
src/main/scala/li/cil/oc/common/item/InkCartridge.scala
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package li.cil.oc.common.item
|
||||||
|
|
||||||
|
class InkCartridge(val parent: Delegator) extends Delegate {
|
||||||
|
override def maxStackSize = 1
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package li.cil.oc.common.item
|
||||||
|
|
||||||
|
class InkCartridgeEmpty(val parent: Delegator) extends Delegate {
|
||||||
|
override def maxStackSize = 1
|
||||||
|
}
|
24
src/main/scala/li/cil/oc/common/item/TexturePicker.scala
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package li.cil.oc.common.item
|
||||||
|
|
||||||
|
import li.cil.oc.Localization
|
||||||
|
import li.cil.oc.util.BlockPosition
|
||||||
|
import li.cil.oc.util.ExtendedWorld._
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
|
||||||
|
class TexturePicker(val parent: Delegator) extends Delegate {
|
||||||
|
override def onItemUse(stack: ItemStack, player: EntityPlayer, position: BlockPosition, side: Int, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
|
||||||
|
player.getEntityWorld.getBlock(position) match {
|
||||||
|
case block: Block =>
|
||||||
|
if (player.getEntityWorld.isRemote) {
|
||||||
|
val icon = block.getIcon(player.getEntityWorld, position.x, position.y, position.z, side)
|
||||||
|
if (icon != null) {
|
||||||
|
player.addChatMessage(Localization.Chat.TextureName(icon.getIconName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
case _ => super.onItemUse(stack, player, position, side, hitX, hitY, hitZ)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,10 +4,6 @@ import li.cil.oc.api.Persistable
|
|||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
|
||||||
object ItemData {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class ItemData extends Persistable {
|
abstract class ItemData extends Persistable {
|
||||||
def load(stack: ItemStack) {
|
def load(stack: ItemStack) {
|
||||||
if (stack.hasTagCompound) {
|
if (stack.hasTagCompound) {
|
||||||
|
81
src/main/scala/li/cil/oc/common/item/data/PrintData.scala
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package li.cil.oc.common.item.data
|
||||||
|
|
||||||
|
import li.cil.oc.api
|
||||||
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
import net.minecraft.util.AxisAlignedBB
|
||||||
|
import net.minecraftforge.common.util.Constants.NBT
|
||||||
|
|
||||||
|
import scala.collection.mutable
|
||||||
|
|
||||||
|
class PrintData extends ItemData {
|
||||||
|
def this(stack: ItemStack) {
|
||||||
|
this()
|
||||||
|
load(stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
var label: Option[String] = None
|
||||||
|
var tooltip: Option[String] = None
|
||||||
|
var isButtonMode = false
|
||||||
|
var emitRedstone = false
|
||||||
|
var pressurePlate = false
|
||||||
|
val stateOff = mutable.Set.empty[PrintData.Shape]
|
||||||
|
val stateOn = mutable.Set.empty[PrintData.Shape]
|
||||||
|
|
||||||
|
override def load(nbt: NBTTagCompound): Unit = {
|
||||||
|
if (nbt.hasKey("label")) label = Option(nbt.getString("label")) else label = None
|
||||||
|
if (nbt.hasKey("tooltip")) tooltip = Option(nbt.getString("tooltip")) else tooltip = None
|
||||||
|
isButtonMode = nbt.getBoolean("isButtonMode")
|
||||||
|
emitRedstone = nbt.getBoolean("emitRedstone")
|
||||||
|
pressurePlate = nbt.getBoolean("pressurePlate")
|
||||||
|
stateOff.clear()
|
||||||
|
stateOff ++= nbt.getTagList("stateOff", NBT.TAG_COMPOUND).map(PrintData.nbtToShape)
|
||||||
|
stateOn.clear()
|
||||||
|
stateOn ++= nbt.getTagList("stateOn", NBT.TAG_COMPOUND).map(PrintData.nbtToShape)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def save(nbt: NBTTagCompound): Unit = {
|
||||||
|
label.foreach(nbt.setString("label", _))
|
||||||
|
tooltip.foreach(nbt.setString("tooltip", _))
|
||||||
|
nbt.setBoolean("isButtonMode", isButtonMode)
|
||||||
|
nbt.setBoolean("emitRedstone", emitRedstone)
|
||||||
|
nbt.setBoolean("pressurePlate", pressurePlate)
|
||||||
|
nbt.setNewTagList("stateOff", stateOff.map(PrintData.shapeToNBT))
|
||||||
|
nbt.setNewTagList("stateOn", stateOn.map(PrintData.shapeToNBT))
|
||||||
|
}
|
||||||
|
|
||||||
|
def createItemStack() = {
|
||||||
|
val stack = api.Items.get("print").createItemStack(1)
|
||||||
|
save(stack)
|
||||||
|
stack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object PrintData {
|
||||||
|
def nbtToShape(nbt: NBTTagCompound): Shape = {
|
||||||
|
val minX = nbt.getByte("minX") / 16f
|
||||||
|
val minY = nbt.getByte("minY") / 16f
|
||||||
|
val minZ = nbt.getByte("minZ") / 16f
|
||||||
|
val maxX = nbt.getByte("maxX") / 16f
|
||||||
|
val maxY = nbt.getByte("maxY") / 16f
|
||||||
|
val maxZ = nbt.getByte("maxZ") / 16f
|
||||||
|
val texture = nbt.getString("texture")
|
||||||
|
new Shape(AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ), texture)
|
||||||
|
}
|
||||||
|
|
||||||
|
def shapeToNBT(shape: Shape): NBTTagCompound = {
|
||||||
|
val nbt = new NBTTagCompound()
|
||||||
|
nbt.setByte("minX", (shape.bounds.minX * 16).round.toByte)
|
||||||
|
nbt.setByte("minY", (shape.bounds.minY * 16).round.toByte)
|
||||||
|
nbt.setByte("minZ", (shape.bounds.minZ * 16).round.toByte)
|
||||||
|
nbt.setByte("maxX", (shape.bounds.maxX * 16).round.toByte)
|
||||||
|
nbt.setByte("maxY", (shape.bounds.maxY * 16).round.toByte)
|
||||||
|
nbt.setByte("maxZ", (shape.bounds.maxZ * 16).round.toByte)
|
||||||
|
nbt.setString("texture", shape.texture)
|
||||||
|
nbt
|
||||||
|
}
|
||||||
|
|
||||||
|
class Shape(val bounds: AxisAlignedBB, val texture: String)
|
||||||
|
|
||||||
|
}
|
95
src/main/scala/li/cil/oc/common/tileentity/Print.scala
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package li.cil.oc.common.tileentity
|
||||||
|
|
||||||
|
import cpw.mods.fml.relauncher.Side
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly
|
||||||
|
import li.cil.oc.common.item.data.PrintData
|
||||||
|
import li.cil.oc.util.ExtendedAABB
|
||||||
|
import li.cil.oc.util.ExtendedAABB._
|
||||||
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection
|
||||||
|
|
||||||
|
class Print extends traits.TileEntity with traits.RedstoneAware with traits.Rotatable {
|
||||||
|
val data = new PrintData()
|
||||||
|
|
||||||
|
var boundsOff = ExtendedAABB.unitBounds
|
||||||
|
var boundsOn = ExtendedAABB.unitBounds
|
||||||
|
var state = false
|
||||||
|
|
||||||
|
_isOutputEnabled = true
|
||||||
|
|
||||||
|
def activate(): Boolean = {
|
||||||
|
if (data.stateOn.size > 0) {
|
||||||
|
if (!state || !data.isButtonMode) {
|
||||||
|
toggleState()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
def toggleState(): Unit = {
|
||||||
|
state = !state
|
||||||
|
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "random.click", 0.3F, if (state) 0.6F else 0.5F)
|
||||||
|
world.markBlockForUpdate(x, y, z)
|
||||||
|
if (data.emitRedstone) {
|
||||||
|
ForgeDirection.VALID_DIRECTIONS.foreach(output(_, if (state) 15 else 0))
|
||||||
|
}
|
||||||
|
if (state && data.isButtonMode) {
|
||||||
|
world.scheduleBlockUpdate(x, y, z, block, block.tickRate(world))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def canUpdate = false
|
||||||
|
|
||||||
|
override protected def onRedstoneInputChanged(side: ForgeDirection, oldMaxValue: Int, newMaxValue: Int): Unit = {
|
||||||
|
super.onRedstoneInputChanged(side, oldMaxValue, newMaxValue)
|
||||||
|
if (!data.emitRedstone && data.stateOn.size > 0) {
|
||||||
|
state = newMaxValue > 0
|
||||||
|
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "random.click", 0.3F, if (state) 0.6F else 0.5F)
|
||||||
|
world.markBlockForUpdate(x, y, z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def readFromNBTForServer(nbt: NBTTagCompound): Unit = {
|
||||||
|
super.readFromNBTForServer(nbt)
|
||||||
|
data.load(nbt.getCompoundTag("data"))
|
||||||
|
state = nbt.getBoolean("state")
|
||||||
|
updateBounds()
|
||||||
|
}
|
||||||
|
|
||||||
|
override def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
|
||||||
|
super.writeToNBTForServer(nbt)
|
||||||
|
nbt.setNewCompoundTag("data", data.save)
|
||||||
|
nbt.setBoolean("state", state)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
override def readFromNBTForClient(nbt: NBTTagCompound): Unit = {
|
||||||
|
super.readFromNBTForClient(nbt)
|
||||||
|
data.load(nbt.getCompoundTag("data"))
|
||||||
|
state = nbt.getBoolean("state")
|
||||||
|
updateBounds()
|
||||||
|
world.markBlockForUpdate(x, y, z)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def writeToNBTForClient(nbt: NBTTagCompound): Unit = {
|
||||||
|
super.writeToNBTForClient(nbt)
|
||||||
|
nbt.setNewCompoundTag("data", data.save)
|
||||||
|
nbt.setBoolean("state", state)
|
||||||
|
}
|
||||||
|
|
||||||
|
def updateBounds(): Unit = {
|
||||||
|
boundsOff = data.stateOff.drop(1).foldLeft(data.stateOff.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds))
|
||||||
|
if (boundsOff.volume == 0) boundsOff = ExtendedAABB.unitBounds
|
||||||
|
else boundsOff = boundsOff.rotateTowards(facing)
|
||||||
|
boundsOn = data.stateOn.drop(1).foldLeft(data.stateOn.headOption.fold(ExtendedAABB.unitBounds)(_.bounds))((a, b) => a.func_111270_a(b.bounds))
|
||||||
|
if (boundsOn.volume == 0) boundsOn = ExtendedAABB.unitBounds
|
||||||
|
else boundsOn = boundsOn.rotateTowards(facing)
|
||||||
|
}
|
||||||
|
|
||||||
|
override protected def onRotationChanged(): Unit = {
|
||||||
|
super.onRotationChanged()
|
||||||
|
updateBounds()
|
||||||
|
}
|
||||||
|
}
|
307
src/main/scala/li/cil/oc/common/tileentity/Printer.scala
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
package li.cil.oc.common.tileentity
|
||||||
|
|
||||||
|
import java.util
|
||||||
|
|
||||||
|
import cpw.mods.fml.relauncher.Side
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly
|
||||||
|
import li.cil.oc.Settings
|
||||||
|
import li.cil.oc.api
|
||||||
|
import li.cil.oc.api.machine.Arguments
|
||||||
|
import li.cil.oc.api.machine.Callback
|
||||||
|
import li.cil.oc.api.machine.Context
|
||||||
|
import li.cil.oc.api.network._
|
||||||
|
import li.cil.oc.common.item.data.PrintData
|
||||||
|
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||||
|
import li.cil.oc.util.ExtendedAABB._
|
||||||
|
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.AxisAlignedBB
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection
|
||||||
|
|
||||||
|
class Printer extends traits.Environment with traits.Inventory with traits.Rotatable with SidedEnvironment with traits.StateAware {
|
||||||
|
val node = api.Network.newNode(this, Visibility.Network).
|
||||||
|
withComponent("printer3d").
|
||||||
|
withConnector(Settings.get.bufferConverter).
|
||||||
|
create()
|
||||||
|
|
||||||
|
val maxAmountMaterial = 256000
|
||||||
|
var amountMaterial = 0
|
||||||
|
val maxAmountInk = 100000
|
||||||
|
var amountInk = 0
|
||||||
|
|
||||||
|
var data = new PrintData()
|
||||||
|
var isActive = false
|
||||||
|
var output: Option[ItemStack] = None
|
||||||
|
var totalRequiredEnergy = 0.0
|
||||||
|
var requiredEnergy = 0.0
|
||||||
|
|
||||||
|
val materialPerItem = 2000
|
||||||
|
val inkPerCartridge = 50000
|
||||||
|
|
||||||
|
val slotMaterial = 0
|
||||||
|
val slotInk = 1
|
||||||
|
val slotOutput = 2
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
override def canConnect(side: ForgeDirection) = side != ForgeDirection.UP
|
||||||
|
|
||||||
|
override def sidedNode(side: ForgeDirection) = if (side != ForgeDirection.UP) node else null
|
||||||
|
|
||||||
|
override def currentState = {
|
||||||
|
if (isPrinting) util.EnumSet.of(traits.State.IsWorking)
|
||||||
|
else if (canPrint) util.EnumSet.of(traits.State.CanWork)
|
||||||
|
else util.EnumSet.noneOf(classOf[traits.State])
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
def canPrint = data.stateOff.size > 0 && data.stateOff.size + data.stateOn.size <= Settings.get.maxPrintComplexity
|
||||||
|
|
||||||
|
def isPrinting = (requiredEnergy > 0 || isActive) && Option(getStackInSlot(slotOutput)).fold(true)(stack => {
|
||||||
|
stack.stackSize < stack.getMaxStackSize && output.fold(true)(ItemStack.areItemStackTagsEqual(stack, _))
|
||||||
|
})
|
||||||
|
|
||||||
|
def progress = (1 - requiredEnergy / totalRequiredEnergy) * 100
|
||||||
|
|
||||||
|
def timeRemaining = (requiredEnergy / Settings.get.assemblerTickAmount / 20).toInt
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
@Callback(doc = """function() -- Resets the configuration of the printer and stop printing (current job will finish).""")
|
||||||
|
def reset(context: Context, args: Arguments): Array[Object] = {
|
||||||
|
data = new PrintData()
|
||||||
|
isActive = false // Needs committing.
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function(value:string) -- Set a label for the block being printed.""")
|
||||||
|
def setLabel(context: Context, args: Arguments): Array[Object] = {
|
||||||
|
data.label = Option(args.optString(0, null)).map(_.take(24))
|
||||||
|
if (data.label.fold(false)(_.isEmpty)) data.label = None
|
||||||
|
isActive = false // Needs committing.
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function():string -- Get the current label for the block being printed.""")
|
||||||
|
def getLabel(context: Context, args: Arguments): Array[Object] = {
|
||||||
|
result(data.label.orNull)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function(value:string) -- Set a tooltip for the block being printed.""")
|
||||||
|
def setTooltip(context: Context, args: Arguments): Array[Object] = {
|
||||||
|
data.tooltip = Option(args.optString(0, null)).map(_.take(128))
|
||||||
|
if (data.tooltip.fold(false)(_.isEmpty)) data.tooltip = None
|
||||||
|
isActive = false // Needs committing.
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function():string -- Get the current tooltip for the block being printed.""")
|
||||||
|
def getTooltip(context: Context, args: Arguments): Array[Object] = {
|
||||||
|
result(data.tooltip.orNull)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function(value:boolean) -- Set whether the printed block should emit redstone when in its active state.""")
|
||||||
|
def setRedstoneEmitter(context: Context, args: Arguments): Array[Object] = {
|
||||||
|
data.emitRedstone = args.checkBoolean(0)
|
||||||
|
isActive = false // Needs committing.
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function():boolean -- Get whether the printed block should emit redstone when in its active state.""")
|
||||||
|
def isRedstoneEmitter(context: Context, args: Arguments): Array[Object] = {
|
||||||
|
result(data.emitRedstone)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function(value:boolean) -- Set whether the printed block should automatically return to its off state.""")
|
||||||
|
def setButtonMode(context: Context, args: Arguments): Array[Object] = {
|
||||||
|
data.isButtonMode = args.checkBoolean(0)
|
||||||
|
isActive = false // Needs committing.
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function():boolean -- Get whether the printed block should automatically return to its off state.""")
|
||||||
|
def isButtonMode(context: Context, args: Arguments): Array[Object] = {
|
||||||
|
result(data.isButtonMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function(minX:number, minY:number, minZ:number, maxX:number, maxY:number, maxZ:number, texture:string[, state:boolean=false]) -- Adds a shape to the printers configuration, optionally specifying whether it is for the off or on state.""")
|
||||||
|
def addShape(context: Context, args: Arguments): Array[Object] = {
|
||||||
|
if (data.stateOff.size + data.stateOn.size >= Settings.get.maxPrintComplexity) {
|
||||||
|
return result(null, "model too complex")
|
||||||
|
}
|
||||||
|
val minX = (args.checkInteger(0) max 0 min 16) / 16f
|
||||||
|
val minY = (args.checkInteger(1) max 0 min 16) / 16f
|
||||||
|
val minZ = (16 - (args.checkInteger(2) max 0 min 16)) / 16f
|
||||||
|
val maxX = (args.checkInteger(3) max 0 min 16) / 16f
|
||||||
|
val maxY = (args.checkInteger(4) max 0 min 16) / 16f
|
||||||
|
val maxZ = (16 - (args.checkInteger(5) max 0 min 16)) / 16f
|
||||||
|
val texture = args.checkString(6).take(64)
|
||||||
|
val state = args.checkAny(7) != null && args.optBoolean(7, false)
|
||||||
|
|
||||||
|
if (minX == maxX) throw new IllegalArgumentException("empty block")
|
||||||
|
if (minY == maxY) throw new IllegalArgumentException("empty block")
|
||||||
|
if (minZ == maxZ) throw new IllegalArgumentException("empty block")
|
||||||
|
|
||||||
|
val list = if (state) data.stateOn else data.stateOff
|
||||||
|
list += new PrintData.Shape(AxisAlignedBB.getBoundingBox(
|
||||||
|
math.min(minX, maxX),
|
||||||
|
math.min(minY, maxY),
|
||||||
|
math.min(minZ, maxZ),
|
||||||
|
math.max(maxX, minX),
|
||||||
|
math.max(maxY, minY),
|
||||||
|
math.max(maxZ, minZ)), texture)
|
||||||
|
isActive = false // Needs committing.
|
||||||
|
|
||||||
|
world.markBlockForUpdate(x, y, z)
|
||||||
|
|
||||||
|
result(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function():number -- Get the number of shapes in the current configuration.""")
|
||||||
|
def getShapeCount(context: Context, args: Arguments): Array[Object] = result(data.stateOff.size + data.stateOn.size)
|
||||||
|
|
||||||
|
@Callback(doc = """function():number -- Get the maximum allowed number of shapes.""")
|
||||||
|
def getMaxShapeCount(context: Context, args: Arguments): Array[Object] = result(Settings.get.maxPrintComplexity)
|
||||||
|
|
||||||
|
@Callback(doc = """function():boolean -- Commit and begin printing the current configuration.""")
|
||||||
|
def commit(context: Context, args: Arguments): Array[Object] = {
|
||||||
|
if (!canPrint) {
|
||||||
|
return result(null, "model invalid")
|
||||||
|
}
|
||||||
|
isActive = true
|
||||||
|
result(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(doc = """function(): string, number or boolean -- The current state of the printer, `busy' or `idle', followed by the progress or model validity, respectively.""")
|
||||||
|
def status(context: Context, args: Arguments): Array[Object] = {
|
||||||
|
if (isPrinting) result("busy", progress)
|
||||||
|
else if (canPrint) result("idle", true)
|
||||||
|
else result("idle", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
override def canUpdate = isServer
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
override def updateEntity() {
|
||||||
|
super.updateEntity()
|
||||||
|
|
||||||
|
if (isActive && output.isEmpty && Option(getStackInSlot(slotOutput)).fold(true)(stack => stack.stackSize < stack.getMaxStackSize)) {
|
||||||
|
val totalVolume = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.volume) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.volume)
|
||||||
|
val totalSurface = data.stateOn.foldLeft(0)((acc, shape) => acc + shape.bounds.surface) + data.stateOff.foldLeft(0)((acc, shape) => acc + shape.bounds.surface)
|
||||||
|
|
||||||
|
if (totalVolume == 0) {
|
||||||
|
isActive = false
|
||||||
|
data = new PrintData()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val materialRequired = (totalVolume / 2) max 1
|
||||||
|
val inkRequired = (totalSurface / 6) max 1
|
||||||
|
|
||||||
|
totalRequiredEnergy = Settings.get.printCost
|
||||||
|
requiredEnergy = totalRequiredEnergy
|
||||||
|
|
||||||
|
if (amountMaterial >= materialRequired && amountInk >= inkRequired) {
|
||||||
|
amountMaterial -= materialRequired
|
||||||
|
amountInk -= inkRequired
|
||||||
|
output = Option(data.createItemStack())
|
||||||
|
ServerPacketSender.sendPrinting(this, printing = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output.isDefined) {
|
||||||
|
val want = math.max(1, math.min(requiredEnergy, Settings.get.printerTickAmount))
|
||||||
|
val success = Settings.get.ignorePower || node.tryChangeBuffer(-want)
|
||||||
|
if (success) {
|
||||||
|
requiredEnergy -= want
|
||||||
|
}
|
||||||
|
if (requiredEnergy <= 0) {
|
||||||
|
val result = getStackInSlot(slotOutput)
|
||||||
|
if (result == null) {
|
||||||
|
setInventorySlotContents(slotOutput, output.get)
|
||||||
|
}
|
||||||
|
else if (output.get.isItemEqual(result) && ItemStack.areItemStackTagsEqual(output.get, result) && result.stackSize < result.getMaxStackSize) {
|
||||||
|
result.stackSize += 1
|
||||||
|
markDirty()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
requiredEnergy = 0
|
||||||
|
output = None
|
||||||
|
}
|
||||||
|
ServerPacketSender.sendPrinting(this, success && output.isDefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxAmountMaterial - amountMaterial >= materialPerItem) {
|
||||||
|
val material = decrStackSize(slotMaterial, 1)
|
||||||
|
if (material != null) {
|
||||||
|
amountMaterial += materialPerItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxAmountInk - amountInk >= inkPerCartridge) {
|
||||||
|
if (api.Items.get(getStackInSlot(slotInk)) == api.Items.get("inkCartridge")) {
|
||||||
|
setInventorySlotContents(slotInk, api.Items.get("inkCartridgeEmpty").createItemStack(1))
|
||||||
|
amountInk += inkPerCartridge
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def readFromNBTForServer(nbt: NBTTagCompound) {
|
||||||
|
super.readFromNBTForServer(nbt)
|
||||||
|
amountMaterial = nbt.getInteger(Settings.namespace + "amountMaterial")
|
||||||
|
amountInk = nbt.getInteger(Settings.namespace + "amountInk")
|
||||||
|
data.load(nbt.getCompoundTag(Settings.namespace + "data"))
|
||||||
|
isActive = nbt.getBoolean(Settings.namespace + "active")
|
||||||
|
if (nbt.hasKey(Settings.namespace + "output")) {
|
||||||
|
output = Option(ItemUtils.loadStack(nbt.getCompoundTag(Settings.namespace + "output")))
|
||||||
|
}
|
||||||
|
totalRequiredEnergy = nbt.getDouble(Settings.namespace + "total")
|
||||||
|
requiredEnergy = nbt.getDouble(Settings.namespace + "remaining")
|
||||||
|
}
|
||||||
|
|
||||||
|
override def writeToNBTForServer(nbt: NBTTagCompound) {
|
||||||
|
super.writeToNBTForServer(nbt)
|
||||||
|
nbt.setInteger(Settings.namespace + "amountMaterial", amountMaterial)
|
||||||
|
nbt.setInteger(Settings.namespace + "amountInk", amountInk)
|
||||||
|
nbt.setNewCompoundTag(Settings.namespace + "data", data.save)
|
||||||
|
nbt.setBoolean(Settings.namespace + "active", isActive)
|
||||||
|
output.foreach(stack => nbt.setNewCompoundTag(Settings.namespace + "output", stack.writeToNBT))
|
||||||
|
nbt.setDouble(Settings.namespace + "total", totalRequiredEnergy)
|
||||||
|
nbt.setDouble(Settings.namespace + "remaining", requiredEnergy)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT) override
|
||||||
|
def readFromNBTForClient(nbt: NBTTagCompound) {
|
||||||
|
super.readFromNBTForClient(nbt)
|
||||||
|
data.load(nbt.getCompoundTag(Settings.namespace + "data"))
|
||||||
|
requiredEnergy = nbt.getDouble("remaining")
|
||||||
|
}
|
||||||
|
|
||||||
|
override def writeToNBTForClient(nbt: NBTTagCompound) {
|
||||||
|
super.writeToNBTForClient(nbt)
|
||||||
|
nbt.setNewCompoundTag(Settings.namespace + "data", data.save)
|
||||||
|
nbt.setDouble("remaining", requiredEnergy)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
override def getSizeInventory = 3
|
||||||
|
|
||||||
|
override def getInventoryStackLimit = 64
|
||||||
|
|
||||||
|
override def isItemValidForSlot(slot: Int, stack: ItemStack) =
|
||||||
|
if (slot == 0)
|
||||||
|
api.Items.get(stack) == api.Items.get("chamelium")
|
||||||
|
else if (slot == 1)
|
||||||
|
api.Items.get(stack) == api.Items.get("inkCartridge")
|
||||||
|
else false
|
||||||
|
}
|
@ -75,7 +75,7 @@ trait RedstoneAware extends RotationAware with IConnectable with IRedstoneEmitte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected def updateRedstoneInput(side: ForgeDirection) {
|
def updateRedstoneInput(side: ForgeDirection) {
|
||||||
val oldInput = _input(side.ordinal())
|
val oldInput = _input(side.ordinal())
|
||||||
val newInput = computeInput(side)
|
val newInput = computeInput(side)
|
||||||
_input(side.ordinal()) = newInput
|
_input(side.ordinal()) = newInput
|
||||||
|
@ -9,6 +9,7 @@ import li.cil.oc.common.tileentity.traits._
|
|||||||
import li.cil.oc.util.BlockPosition
|
import li.cil.oc.util.BlockPosition
|
||||||
import li.cil.oc.util.PackedColor
|
import li.cil.oc.util.PackedColor
|
||||||
import net.minecraft.entity.player.EntityPlayerMP
|
import net.minecraft.entity.player.EntityPlayerMP
|
||||||
|
import net.minecraft.inventory.Container
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.CompressedStreamTools
|
import net.minecraft.nbt.CompressedStreamTools
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
@ -74,6 +75,17 @@ object PacketSender {
|
|||||||
pb.sendToPlayersNearTileEntity(t)
|
pb.sendToPlayersNearTileEntity(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def sendContainerUpdate(c: Container, nbt: NBTTagCompound, player: EntityPlayerMP): Unit = {
|
||||||
|
if (!nbt.hasNoTags) {
|
||||||
|
val pb = new SimplePacketBuilder(PacketType.ContainerUpdate)
|
||||||
|
|
||||||
|
pb.writeByte(c.windowId.toByte)
|
||||||
|
pb.writeNBT(nbt)
|
||||||
|
|
||||||
|
pb.sendToPlayer(player)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def sendDisassemblerActive(t: tileentity.Disassembler, active: Boolean) {
|
def sendDisassemblerActive(t: tileentity.Disassembler, active: Boolean) {
|
||||||
val pb = new SimplePacketBuilder(PacketType.DisassemblerActiveChange)
|
val pb = new SimplePacketBuilder(PacketType.DisassemblerActiveChange)
|
||||||
|
|
||||||
@ -226,6 +238,15 @@ object PacketSender {
|
|||||||
pb.sendToPlayersNearTileEntity(t)
|
pb.sendToPlayersNearTileEntity(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def sendPrinting(t: tileentity.Printer, printing: Boolean) {
|
||||||
|
val pb = new SimplePacketBuilder(PacketType.PrinterState)
|
||||||
|
|
||||||
|
pb.writeTileEntity(t)
|
||||||
|
pb.writeBoolean(printing)
|
||||||
|
|
||||||
|
pb.sendToPlayersNearHost(t)
|
||||||
|
}
|
||||||
|
|
||||||
def sendRaidChange(t: tileentity.Raid) {
|
def sendRaidChange(t: tileentity.Raid) {
|
||||||
val pb = new SimplePacketBuilder(PacketType.RaidStateChange)
|
val pb = new SimplePacketBuilder(PacketType.RaidStateChange)
|
||||||
|
|
||||||
|
51
src/main/scala/li/cil/oc/util/ExtendedAABB.scala
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package li.cil.oc.util
|
||||||
|
|
||||||
|
import net.minecraft.util.AxisAlignedBB
|
||||||
|
import net.minecraft.util.Vec3
|
||||||
|
import net.minecraftforge.common.util.ForgeDirection
|
||||||
|
|
||||||
|
import scala.language.implicitConversions
|
||||||
|
|
||||||
|
object ExtendedAABB {
|
||||||
|
implicit def extendedAABB(bounds: AxisAlignedBB): ExtendedAABB = new ExtendedAABB(bounds)
|
||||||
|
|
||||||
|
def unitBounds = AxisAlignedBB.getBoundingBox(0, 0, 0, 1, 1, 1)
|
||||||
|
|
||||||
|
class ExtendedAABB(val bounds: AxisAlignedBB) {
|
||||||
|
def volume: Int = {
|
||||||
|
val sx = ((bounds.maxX - bounds.minX) * 16).round.toInt
|
||||||
|
val sy = ((bounds.maxY - bounds.minY) * 16).round.toInt
|
||||||
|
val sz = ((bounds.maxZ - bounds.minZ) * 16).round.toInt
|
||||||
|
sx * sy * sz
|
||||||
|
}
|
||||||
|
|
||||||
|
def surface: Int = {
|
||||||
|
val sx = ((bounds.maxX - bounds.minX) * 16).round.toInt
|
||||||
|
val sy = ((bounds.maxY - bounds.minY) * 16).round.toInt
|
||||||
|
val sz = ((bounds.maxZ - bounds.minZ) * 16).round.toInt
|
||||||
|
sx * sy * 2 + sx * sz * 2 + sy * sz * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
def rotateTowards(facing: ForgeDirection) = rotateY(facing match {
|
||||||
|
case ForgeDirection.WEST => 3
|
||||||
|
case ForgeDirection.NORTH => 2
|
||||||
|
case ForgeDirection.EAST => 1
|
||||||
|
case _ => 0
|
||||||
|
})
|
||||||
|
|
||||||
|
def rotateY(count: Int): AxisAlignedBB = {
|
||||||
|
val min = Vec3.createVectorHelper(bounds.minX - 0.5, bounds.minY - 0.5, bounds.minZ - 0.5)
|
||||||
|
val max = Vec3.createVectorHelper(bounds.maxX - 0.5, bounds.maxY - 0.5, bounds.maxZ - 0.5)
|
||||||
|
min.rotateAroundY(count * Math.PI.toFloat * 0.5f)
|
||||||
|
max.rotateAroundY(count * Math.PI.toFloat * 0.5f)
|
||||||
|
AxisAlignedBB.getBoundingBox(
|
||||||
|
(math.min(min.xCoord + 0.5, max.xCoord + 0.5) * 32).round / 32f,
|
||||||
|
(math.min(min.yCoord + 0.5, max.yCoord + 0.5) * 32).round / 32f,
|
||||||
|
(math.min(min.zCoord + 0.5, max.zCoord + 0.5) * 32).round / 32f,
|
||||||
|
(math.max(min.xCoord + 0.5, max.xCoord + 0.5) * 32).round / 32f,
|
||||||
|
(math.max(min.yCoord + 0.5, max.yCoord + 0.5) * 32).round / 32f,
|
||||||
|
(math.max(min.zCoord + 0.5, max.zCoord + 0.5) * 32).round / 32f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|