Merge branch 'master-MC1.8' of github.com:MightyPirates/OpenComputers into OC1.5-MC1.8

Conflicts:
	build.properties
This commit is contained in:
Florian Nücke 2015-07-12 19:55:43 +02:00
commit 394962e308
92 changed files with 994 additions and 185 deletions

Binary file not shown.

View File

@ -78,6 +78,10 @@ repositories {
name = "mobius"
url = "http://mobiusstrip.eu/maven"
}
maven {
name = "fallback"
url = "http://maven.cil.li/"
}
/*
maven {
name = "BluePower"
@ -115,7 +119,14 @@ repositories {
name 'DVS1 Maven FS'
url 'http://dvs1.progwml6.com/files/maven'
}
maven {
name 'ProjectRed'
url 'http://files.projectredwiki.com/maven/'
}
maven {
name 'ColoredLightCore'
url "http://coloredlightscore.us.to/maven/clc/"
}
ivy {
name "BuildCraft"
artifactPattern "http://www.mod-buildcraft.com/releases/BuildCraft/[revision]/[module]-[revision]-[classifier].[ext]"
@ -128,19 +139,18 @@ repositories {
name 'Mekanism'
artifactPattern "http://ci.cil.li/job/Mekanism/${config.mekanism.build}/artifact/output/[module]-${config.minecraft.version}-[revision].${config.mekanism.build}.[ext]"
}
ivy {
name 'ProjectRed'
artifactPattern "http://projectredwiki.com/maven/mrtjp/[module]/${config.minecraft.version}-[revision]/[module]-${config.minecraft.version}-[revision]-dev.[ext]"
}
ivy {
name 'immibis'
artifactPattern "https://dl.dropboxusercontent.com/u/2944265/mods/autobuilt/files/[module]-[revision].[ext]"
}
ivy {
name 'CoFHLib'
artifactPattern "http://addons-origin.cursecdn.com/files/${config.cofhlib.cf}/[module]-[revision].[ext]"
}
ivy {
name 'CoFHCore'
artifactPattern "http://addons-origin.cursecdn.com/files/${config.cofhcore.cf}/[module]-[revision].[ext]"
}
ivy {
name 'MineFactoryReloaded'
artifactPattern "http://addons-origin.cursecdn.com/files/${config.mfr.cf}/[module]-[revision].[ext]"
@ -181,7 +191,9 @@ dependencies {
provided "mcp.mobius.waila:Waila:${config.waila.version}:dev"
/*
provided "appeng:RotaryCraft:${config.rotc.version}:api"
provided "appeng:appliedenergistics2:${config.ae2.version}:dev"
provided ("appeng:appliedenergistics2:${config.ae2.version}:dev") {
exclude module: 'buildcraft'
}
provided "codechicken:EnderStorage:${config.minecraft.version}-${config.es.version}:dev"
provided "codechicken:ForgeMultipart:${config.minecraft.version}-${config.fmp.version}:dev"
provided "codechicken:WR-CBE:${config.minecraft.version}-${config.wrcbe.version}:dev"
@ -195,22 +207,27 @@ dependencies {
provided "notenoughkeys:NeK:${config.minecraft.version}-${config.nek.version}:deobf-dev"
provided "qmunity:QmunityLib:${config.qmunitylib.version}:deobf"
provided "tmech:TMechworks:${config.minecraft.version}-${config.tmech.version}:deobf"
provided ("mrtjp:ProjectRed:${config.projred.version}:dev") {
exclude module: 'CoFHCore'
}
provided "coloredlightscore:ColoredLightsCore:${config.coloredlights.version}:api"
provided name: "buildcraft", version: "${config.bc.version}", classifier: "dev", ext: 'jar'
provided name: 'buildcraft', version: config.bc.version, classifier: "dev", ext: 'jar'
provided name: 'GalacticraftCoreAll', version: config.gc.version, ext: 'jar'
provided name: 'MekanismAll', version: config.mekanism.version, ext: 'jar'
provided name: 'ProjectRed', version: config.projred.version, ext: 'jar'
provided name: 'redlogic', version: config.redlogic.version, ext: 'jar'
provided name: 'CoFHLib', version: URLEncoder.encode(config.cofhlib.version, "UTF-8"), ext: 'jar'
provided name: 'MineFactoryReloaded', version: URLEncoder.encode(config.mfr.version, "UTF-8"), ext: 'jar'
provided name: 'CoFHLib', version: config.cofhlib.version, ext: 'jar'
provided name: 'CoFHCore', version: config.cofhcore.version, ext: 'jar'
provided name: 'MineFactoryReloaded', version: config.mfr.version, ext: 'jar'
provided name: 'ComputerCraft', version: config.cc.version, ext: 'jar'
provided name: 'EnderIO', version: config.eio.version, ext: 'jar'
provided name: 'Railcraft', version: config.rc.version, ext: 'jar'
provided name: 'BloodMagic', version: config.bloodmagic.version, ext: 'jar'
provided name: 'ExtraCells', version: config.ec.version, ext: 'jar'
*/
provided "cyano.poweradvantage:PowerAdvantage-API:${config.poweradvantage.version}"
compile 'com.google.code.findbugs:jsr305:1.3.9' // Annotations used by google libs.
embedded files('libs/OpenComputers-JNLua.jar', 'libs/OpenComputers-LuaJ.jar')

View File

@ -1,7 +1,7 @@
minecraft.version=1.8
forge.version=11.14.3.1450
oc.version=1.5.13
oc.version=1.5.14
oc.subversion=
ae2.version=rv2-beta-26
@ -15,6 +15,7 @@ ccc.version=1.0.5.34
ccl.version=1.1.2.115
cofhlib.cf=2230/207
cofhlib.version=[1.7.10]1.0.0RC7-127
coloredlights.version=1.3.7.35
ec.cf=2242/839
ec.version=deobf-1.7.10-2.2.73b129
eio.cf=2219/296
@ -33,7 +34,8 @@ mfr.cf=2229/626
mfr.version=[1.7.10]2.8.0RC8-86
nei.version=1.0.5.82
nek.version=1.0.0b35dev
projred.version=4.7.0pre2.87
poweradvantage.version=1.2.0
projred.version=1.7.10-4.6.2.82
qmunitylib.version=0.1.105
rc.cf=2219/321
rc.version=1.7.10-9.4.0.0
@ -43,5 +45,7 @@ tmech.version=75.0afb56c
re.version=3.0.0.342
waila.version=1.6.0_B1_1.8.1
wrcbe.version=1.4.1.2
cofhcore.cf=2246/697
cofhcore.version=[1.7.10]3.0.3B4-302-dev
maven.url=file:///home/www/maven.cil.li/web

View File

@ -12,7 +12,7 @@ import li.cil.oc.api.detail.*;
*/
public class API {
public static final String ID_OWNER = "OpenComputers|Core";
public static final String VERSION = "5.5.2";
public static final String VERSION = "5.5.3";
public static DriverAPI driver = null;
public static FileSystemAPI fileSystem = null;

View File

@ -107,6 +107,19 @@ public final class FileSystem {
return null;
}
/**
* Wrap a file system retrieved via one of the <tt>from???</tt> methods to
* make it read-only.
*
* @param fileSystem the file system to wrap.
* @return the specified file system wrapped to be read-only.
*/
public static li.cil.oc.api.fs.FileSystem asReadOnly(final li.cil.oc.api.fs.FileSystem fileSystem) {
if (API.fileSystem != null)
return API.fileSystem.asReadOnly(fileSystem);
return null;
}
/**
* Creates a network node that makes the specified file system available via
* the common file system driver.

View File

@ -67,6 +67,15 @@ public interface FileSystemAPI {
*/
FileSystem fromMemory(long capacity);
/**
* Wrap a file system retrieved via one of the <tt>from???</tt> methods to
* make it read-only.
*
* @param fileSystem the file system to wrap.
* @return the specified file system wrapped to be read-only.
*/
FileSystem asReadOnly(final FileSystem fileSystem);
/**
* Creates a network node that makes the specified file system available via
* the common file system driver.

View File

@ -780,6 +780,7 @@ opencomputers {
Galacticraft: 48.0
IndustrialCraft2: 400.0
Mekanism: 1333.33
PowerAdvantage: 31.25
RedstoneFlux: 100.0
}
}

View File

@ -23,7 +23,6 @@ Keep in mind that some of these may not be available, depending on the recipe se
### Extensions
* [Adapter](adapter.md)
* [Cable](cable.md)
* [Geolyzer](geolyzer.md)
* [Motion Sensor](motionSensor.md)
* [Redstone I/O](redstone.md)
@ -38,6 +37,8 @@ Keep in mind that some of these may not be available, depending on the recipe se
## Networking
* [Access Point](accessPoint.md)
* [Cable](cable.md)
* [Net Splitter](netSplitter.md)
* [Switch](switch.md)
## Power management

View File

@ -0,0 +1,7 @@
# Net Splitter
![*.net *.split](oredict:oc:netSplitter)
The net splitter is a device that allows controlling connectivity between subnetworks. Unlike the [switch](switch.md) or [power converter](powerConverter.md) it directly connects adjacent subnetworks, i.e. components can be accessed. Each side's connectivity can be toggled using a wrench (e.g. the [scrench](../item/wrench.md)). When a redstone signal is applied to the net splitter, all sides' connectivity is inverted.
This block can therefore be used to toggle connectivity to certain parts of a component network. Use a [redstone I/O block](redstone.md) or [redstone cards](../item/redstoneCard1.md) to automate the net splitter.

View File

@ -4,13 +4,13 @@ Also know as "how to build your first computer". To get your first [computer](co
**Disclaimer**: this will be step-by-step, and also provide some information on how to look for issues yourself later on, so this is quite long. If you have never built a computer in real life, and/or are completely new to the mod, it is highly recommended you read through it all.
First off, you will need a [computer case](../block/case1.md). This is the block which will contain of the components, defining the behavior of the computer you are building.
First off, you will need a [computer case](../block/case1.md). This is the block which will contain all of the components, defining the behavior of the computer you are building.
![A tier two computer case.](oredict:oc:case2)
For example, you will need to choose what tier of [graphics card](../item/graphicsCard1.md) you wish to use, if you need a [network card](../item/lanCard.md), a [redstone card](../item/redstoneCard1.md) or, if you're just playing around in creative mode, maybe even a [debug card](../item/debugCard.md).
When you open the [computer case](../block/case1.md)'s GUI you will see a few slots to the right. The number of slots, and what tier of component can be placed into them (indicated by the small roman numeral in the slot) depends on the tier of the case itself.
When you open the [computer case](../block/case1.md)'s GUI, you will see a few slots to the right. The number of slots, and what tier of component can be placed into them (indicated by the small roman numeral in the slot) depends on the tier of the case itself.
![GUI of a tier two computer case.](opencomputers:doc/img/configuration_case1.png)
In their empty state, [computer cases](../block/case1.md) are pretty useless. You can try to power up your [computer](computer.md) now, but it'll immediately print an error message to your chat log, and make its dissatisfaction heard by beeping at you. Good thing the error message is telling you what you can do to fix this situation: it requires energy. Connect your [computer](computer.md) to some power, either directly or via a [power converter](../block/powerConverter.md).

View File

@ -23,7 +23,6 @@
### Расширения
* [Адаптер](adapter.md)
* [Кабель](cable.md)
* [Геоанализатор](geolyzer.md)
* [Датчик движения](motionSensor.md)
* [Редстоун I/O](redstone.md)
@ -38,6 +37,8 @@
## Сеть
* [Точка доступа](accessPoint.md)
* [Кабель](cable.md)
* [Сетевой переключатель](netSplitter.md)
* [Коммутатор](switch.md)
## Управление питанием

View File

@ -0,0 +1,7 @@
# Сетевой переключатель
![*.net *.split](oredict:oc:netSplitter)
Сетевой переключатель позволяет контролировать соединение между подсетями. В отличие от [коммутатора](switch.md) или [конвертера энергии](powerConverter.md) позволяет непосредственно соединить подсети, делая при этом доступными все компоненты. Соединение каждой стороны переключается [ключем](../item/wrench.md). При подаче сигнала красного камня все соединения инвертируются.
Таким образом, этот блок может быть использован для переключения соединения определенных компонентов сети. Используйте [редстоун I/O](redstone.md) или [редстоун карты](../item/redstoneCard1.md) для автоматизации сетевого переключателя.

View File

@ -36,6 +36,7 @@ tile.oc.screen2.name=Screen (Tier 2)
tile.oc.screen3.name=Screen (Tier 3)
tile.oc.serverRack.name=Server Rack
tile.oc.switch.name=Switch
tile.oc.netSplitter.name=Net Splitter
tile.oc.waypoint.name=Waypoint
# Items
@ -155,6 +156,7 @@ oc:gui.Analyzer.AddressCopied=Address copied to clipboard.
oc:gui.Analyzer.ChargerSpeed=§6Charge speed§f: %s
oc:gui.Analyzer.ComponentName=§6Component name§f: %s
oc:gui.Analyzer.Components=§6Number of connected components§f: %s
oc:gui.Analyzer.CopyToClipboard=Click to copy to clipboard.
oc:gui.Analyzer.LastError=§6Last error§f: %s
oc:gui.Analyzer.RobotName=§6Name§f: %s
oc:gui.Analyzer.RobotOwner=§6Owner§f: %s
@ -330,6 +332,7 @@ oc:tooltip.TabletCase=Basic case for tablets. Place it into the assembler to add
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.NetSplitter=Acts as a dynamic connector. Connectivity of each side can be toggled by hitting it with a wrench. Connectivity of all sides can be inverted by applying a redstone signal.
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.UpgradeAngel=Allows robots to place blocks in thin air, even if there is no point of reference.

View File

@ -36,6 +36,7 @@ tile.oc.screen2.name=Монитор (2-ой уровень)
tile.oc.screen3.name=Монитор (3-ий уровень)
tile.oc.serverRack.name=Серверная стойка
tile.oc.switch.name=Коммутатор
tile.oc.netSplitter.name=Сетевой переключатель
tile.oc.waypoint.name=Путевая точка
# Items
@ -154,6 +155,7 @@ oc:gui.Analyzer.AddressCopied=Адрес скопирован в буфер об
oc:gui.Analyzer.ChargerSpeed=§6Скорость зарядки§f: %s
oc:gui.Analyzer.ComponentName=§6Имя компонента§f: %s
oc:gui.Analyzer.Components=§6Количество подключенных компонентов§f: %s
oc:gui.Analyzer.CopyToClipboard=Кликните для копирования в буфер обмена.
oc:gui.Analyzer.LastError=§6Последняя ошибка§f: %s
oc:gui.Analyzer.RobotName=§6Имя§f: %s
oc:gui.Analyzer.RobotOwner=§6Владелец§f: %s
@ -329,6 +331,7 @@ oc:tooltip.TabletCase=Простой корпус для планшета. По
oc:tooltip.Terminal=Позволяет дистанционно управлять сервером, пока вы находитесь в радиусе его действия. Действует как портативный дисплей с клавиатурой.[nl] Shift+ПКМ по серверу в стойке для привязки к нему терминала.
oc:tooltip.TexturePicker=Простой инструмент, позволяющий узнать название текстуры блока, которое можно использовать в 3D печати.
oc:tooltip.Tier=§8Уровень %s
oc:tooltip.NetSplitter=Работает как переключатель. Соединение каждой стороны переключается ключем. При подаче сигнала красного камня все соединения инвертируются.
oc:tooltip.TooLong=Удерживайте [§f%s§7], чтобы отобразить описание.
oc:tooltip.Transistor=Базовый элемент для других частей компьютера. Он немного деформирован, но отлично выполняет свою работу.
oc:tooltip.UpgradeAngel=Позволяет роботам размещать блоки в воздухе, даже если отсутствует точка опоры.

View File

@ -9,7 +9,7 @@ local args, options = shell.parse(...)
local fromAddress = options.from and component.get(options.from) or filesystem.get(os.getenv("_")).address
local candidates = {}
for address in component.list("filesystem") do
for address in component.list("filesystem", true) do
local dev = component.proxy(address)
if not dev.isReadOnly() and dev.address ~= computer.tmpAddress() and dev.address ~= fromAddress then
table.insert(candidates, dev)

View File

@ -38,7 +38,11 @@ end
function memoryStream:write(value)
if not self.redirect.write and self.closed then
error("attempt to use a closed stream")
-- if next is dead, ignore all writes
if coroutine.status(self.next) ~= "dead" then
error("attempt to use a closed stream")
end
return true
end
if self.redirect.write then
self.redirect.write:write(value)
@ -306,6 +310,7 @@ local function execute(env, command, ...)
elseif pipes[i] then
io.output(pipes[i])
end
io.write('')
end, command)
if not threads[i] then
return false, reason

View File

@ -116,7 +116,7 @@ end
-------------------------------------------------------------------------------
for address in component.list('screen') do
for address in component.list('screen', true) do
if #component.invoke(address,'getKeyboards') > 0 then
component.setPrimary('screen',address)
end

View File

@ -28,8 +28,8 @@ do
function rom.inits() return ipairs(rom.invoke("list", "boot")) end
function rom.isDirectory(path) return rom.invoke("isDirectory", path) end
local screen = component.list('screen')()
for address in component.list('screen') do
local screen = component.list('screen', true)()
for address in component.list('screen', true) do
if #component.invoke(address, 'getKeyboards') > 0 then
screen = address
end

View File

@ -242,7 +242,7 @@ end
function filesystem.proxy(filter)
checkArg(1, filter, "string")
local address
for c in component.list("filesystem") do
for c in component.list("filesystem", true) do
if component.invoke(c, "getLabel") == filter then
address = c
break

View File

@ -22,6 +22,6 @@ else
read = read .. current
until current ~= ""
file:close()
io.write(data.toHex(data.md5(read)) .. "\t".. args[i])
io.write(data.toHex(data.md5(read)) .. "\t".. args[i] .. "\n")
end
end

View File

@ -22,6 +22,6 @@ else
read = read .. current
until current ~= ""
file:close()
io.write(data.toHex(data.sha256(read)) .. "\t".. args[i])
io.write(data.toHex(data.sha256(read)) .. "\t".. args[i] .. "\n")
end
end

View File

@ -732,7 +732,7 @@ sandbox = {
tonumber = tonumber,
tostring = tostring,
type = type,
_VERSION = _VERSION:match("5.3") and "Lua 5.3.0" or "Lua 5.2.4",
_VERSION = _VERSION:match("5.3") and "Lua 5.3" or "Lua 5.2",
xpcall = function(f, msgh, ...)
local handled = false
local result = table.pack(xpcall(f, function(...)

View File

@ -576,6 +576,11 @@ motionSensor {
[daylightDetector, "oc:cpu2", daylightDetector]
[ingotGold, "oc:materialCircuitBoardPrinted", ingotGold]]
}
netSplitter {
input: [[ingotIron, "oc:cable", ingotIron]
["oc:cable", craftingPiston, "oc:cable"]
[ingotIron, "oc:materialCircuitBoardPrinted", ingotIron]]
}
printer {
input: [[ingotIron, hopper, ingotIron]
[craftingPiston, "oc:circuitChip3", craftingPiston]

View File

@ -30,6 +30,7 @@ Crypto # Kodos
Curiosity # Mars Rover
Daedalus # Deus Ex
Dalek Sec # Doctor Who
David # A.I. (the movie)
Death Trap # Borderlands 2's Mechromancer
Deputy ANDY # Eureka
Dog # Half-Life

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

View File

@ -38,6 +38,7 @@ object Constants {
final val ScreenTier3 = "screen3"
final val ServerRack = "serverRack"
final val Switch = "switch"
final val NetSplitter = "netSplitter"
final val Waypoint = "waypoint"
def Case(tier: Int) = ItemUtils.caseNameWithTierSuffix("case", tier)

View File

@ -1,5 +1,8 @@
package li.cil.oc
import li.cil.oc.client.CommandHandler.SetClipboardCommand
import net.minecraft.event.ClickEvent
import net.minecraft.event.HoverEvent
import net.minecraft.util.ChatComponentText
import net.minecraft.util.ChatComponentTranslation
import net.minecraft.util.StatCollector
@ -23,7 +26,12 @@ object Localization {
def localizeImmediately(key: String) = StatCollector.translateToLocal(resolveKey(key)).split(nl).map(_.trim).mkString("\n")
object Analyzer {
def Address(value: String) = localizeLater("gui.Analyzer.Address", value)
def Address(value: String) = {
val result = localizeLater("gui.Analyzer.Address", value)
result.getChatStyle.setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, s"/${SetClipboardCommand.name} $value"))
result.getChatStyle.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, localizeLater("gui.Analyzer.CopyToClipboard")))
result
}
def AddressCopied = localizeLater("gui.Analyzer.AddressCopied")

View File

@ -2,7 +2,7 @@ package li.cil.oc
import li.cil.oc.common.IMC
import li.cil.oc.common.Proxy
import li.cil.oc.server.CommandHandler
import li.cil.oc.server.command.CommandHandler
import net.minecraftforge.fml.common.Mod
import net.minecraftforge.fml.common.Mod.EventHandler
import net.minecraftforge.fml.common.SidedProxy

View File

@ -218,6 +218,7 @@ class Settings(val config: Config) {
private val valueGalacticraft = config.getDouble("power.value.Galacticraft")
private val valueIndustrialCraft2 = config.getDouble("power.value.IndustrialCraft2")
private val valueMekanism = config.getDouble("power.value.Mekanism")
private val valuePowerAdvantage = config.getDouble("power.value.PowerAdvantage")
private val valueRedstoneFlux = config.getDouble("power.value.RedstoneFlux")
private val valueInternal = 1000
@ -227,6 +228,7 @@ class Settings(val config: Config) {
val ratioGalacticraft = valueGalacticraft / valueInternal
val ratioIndustrialCraft2 = valueIndustrialCraft2 / valueInternal
val ratioMekanism = valueMekanism / valueInternal
val ratioPowerAdvantage = valuePowerAdvantage / valueInternal
val ratioRedstoneFlux = valueRedstoneFlux / valueInternal
// ----------------------------------------------------------------------- //

View File

@ -0,0 +1,31 @@
package li.cil.oc.client
import li.cil.oc.common.command.SimpleCommand
import net.minecraft.client.gui.GuiScreen
import net.minecraft.command.ICommandSender
import net.minecraftforge.client.ClientCommandHandler
object CommandHandler {
def register(): Unit = {
ClientCommandHandler.instance.registerCommand(SetClipboardCommand)
}
object SetClipboardCommand extends SimpleCommand("oc_setclipboard") {
override def getCommandUsage(source: ICommandSender): String = name + " <value>"
override def execute(source: ICommandSender, command: Array[String]): Unit = {
if (source.getEntityWorld.isRemote && command != null && command.length > 0) {
GuiScreen.setClipboardString(command(0))
}
}
// OP levels for reference:
// 1 - Ops can bypass spawn protection.
// 2 - Ops can use /clear, /difficulty, /effect, /gamemode, /gamerule, /give, /summon, /setblock and /tp, and can edit command blocks.
// 3 - Ops can use /ban, /deop, /kick, and /op.
// 4 - Ops can use /stop.
override def getRequiredPermissionLevel = 0
}
}

View File

@ -58,6 +58,7 @@ object PacketHandler extends CommonPacketHandler {
case PacketType.HologramTranslation => onHologramPositionOffsetY(p)
case PacketType.HologramValues => onHologramValues(p)
case PacketType.LootDisk => onLootDisk(p)
case PacketType.NetSplitterState => onNetSplitterState(p)
case PacketType.ParticleEffect => onParticleEffect(p)
case PacketType.PetVisibility => onPetVisibility(p)
case PacketType.PowerState => onPowerState(p)
@ -442,6 +443,7 @@ object PacketHandler extends CommonPacketHandler {
}
buffer.data.load(nbt)
buffer.proxy.markDirty()
buffer.markInitialized()
case _ => // Invalid packet.
}
}
@ -587,6 +589,15 @@ object PacketHandler extends CommonPacketHandler {
buffer.rawSetForeground(col, row, color)
}
def onNetSplitterState(p: PacketParser) =
p.readTileEntity[NetSplitter]() match {
case Some(t) =>
t.isInverted = p.readBoolean()
t.openSides = t.uncompressSides(p.readByte())
t.world.markBlockForUpdate(t.getPos)
case _ => // Invalid packet.
}
def onScreenTouchMode(p: PacketParser) =
p.readTileEntity[Screen]() match {
case Some(t) => t.invertTouchMode = p.readBoolean()

View File

@ -34,6 +34,8 @@ private[oc] class Proxy extends CommonProxy {
api.API.manual = client.Manual
CommandHandler.register()
MinecraftForge.EVENT_BUS.register(Textures)
ModelInitialization.preInit()
@ -67,6 +69,7 @@ private[oc] class Proxy extends CommonProxy {
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.AccessPoint], SwitchRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.RobotProxy], RobotRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.Screen], ScreenRenderer)
ClientRegistry.bindTileEntitySpecialRenderer(classOf[tileentity.NetSplitter], NetSplitterRenderer)
ClientRegistry.registerKeyBinding(KeyBindings.materialCosts)
ClientRegistry.registerKeyBinding(KeyBindings.clipboardPaste)

View File

@ -131,6 +131,7 @@ object Textures {
val GeolyzerTopOn = L("overlay/geolyzer_top_on")
val MicrocontrollerFrontLight = L("overlay/microcontroller_front_light")
val MicrocontrollerFrontOn = L("overlay/microcontroller_front_on")
val NetSplitterOn = L("overlay/netSplitter_on")
val PowerDistributorSideOn = L("overlay/powerDistributor_side_on")
val PowerDistributorTopOn = L("overlay/powerDistributor_top_on")
val RackFrontActivity = L("overlay/serverRack_front_activity")
@ -143,6 +144,8 @@ object Textures {
val Cable = L("cable")
val CableCap = L("cableCap")
val GenericTop = L("generic_top", load = false)
val NetSplitterSide = L("netSplitter_side")
val NetSplitterTop = L("netSplitter_top")
val RackFront = L("serverRack_front", load = false)
val RackSide = L("serverRack_side", load = false)

View File

@ -31,7 +31,10 @@ object PetRenderer {
"DaKaTotal" ->(0.5, 0.7, 1.0),
"MichiyoRavencroft" ->(1.0, 0.0, 0.0),
"Vexatos" ->(0.18, 0.95, 0.922),
"StoneNomad" ->(0.8, 0.77, 0.75)
"StoneNomad" ->(0.8, 0.77, 0.75),
"LizzyTheSiren" ->(0.3, 0.3, 1.0),
"vifino" ->(0.2, 1.0, 0.1),
"Izaya" ->(0.0, 0.2, 0.6)
)
private val petLocations = com.google.common.cache.CacheBuilder.newBuilder().

View File

@ -83,17 +83,17 @@ object CableModel extends SmartBlockModelBase with ISmartItemModel {
class BlockModel(val state: IExtendedBlockState) extends SmartBlockModelBase {
override def getGeneralQuads =
state.getValue(block.property.PropertyTile.Tile) match {
case cable: tileentity.Cable =>
case t: tileentity.Cable =>
val faces = mutable.ArrayBuffer.empty[BakedQuad]
val color = Some(cable.color)
val mask = Cable.neighbors(cable.world, cable.getPos)
val color = Some(t.color)
val mask = Cable.neighbors(t.world, t.getPos)
faces ++= bakeQuads(Middle, cableTexture, color)
for (side <- EnumFacing.values) {
val connected = (mask & (1 << side.getIndex)) != 0
val (plug, shortBody, longBody) = Connected(side.getIndex)
if (connected) {
if (isCable(cable.position.offset(side))) {
if (isCable(t.position.offset(side))) {
faces ++= bakeQuads(longBody, cableTexture, color)
}
else {

View File

@ -29,6 +29,8 @@ import scala.collection.mutable
object ModelInitialization {
final val CableBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Cable, "normal")
final val CableItemLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Cable, "inventory")
final val NetSplitterBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.NetSplitter, "normal")
final val NetSplitterItemLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.NetSplitter, "inventory")
final val PrintBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Print, "normal")
final val PrintItemLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Print, "inventory")
final val RobotBlockLocation = new ModelResourceLocation(Settings.resourceDomain + ":" + Constants.BlockName.Robot, "normal")
@ -45,6 +47,7 @@ object ModelInitialization {
MinecraftForge.EVENT_BUS.register(this)
registerModel(Constants.BlockName.Cable, CableBlockLocation, CableItemLocation)
registerModel(Constants.BlockName.NetSplitter, NetSplitterBlockLocation, NetSplitterItemLocation)
registerModel(Constants.BlockName.Print, PrintBlockLocation, PrintItemLocation)
registerModel(Constants.BlockName.Robot, RobotBlockLocation, RobotItemLocation)
registerModel(Constants.BlockName.RobotAfterimage, RobotAfterimageBlockLocation, RobotAfterimageItemLocation)
@ -137,6 +140,8 @@ object ModelInitialization {
registry.putObject(CableBlockLocation, CableModel)
registry.putObject(CableItemLocation, CableModel)
registry.putObject(NetSplitterBlockLocation, NetSplitterModel)
registry.putObject(NetSplitterItemLocation, NetSplitterModel)
registry.putObject(PrintBlockLocation, PrintModel)
registry.putObject(PrintItemLocation, PrintModel)
registry.putObject(RobotBlockLocation, RobotModel)

View File

@ -0,0 +1,106 @@
package li.cil.oc.client.renderer.block
import li.cil.oc.client.Textures
import li.cil.oc.common.block
import li.cil.oc.common.item.data.PrintData
import li.cil.oc.common.tileentity
import net.minecraft.block.state.IBlockState
import net.minecraft.client.renderer.block.model.BakedQuad
import net.minecraft.item.ItemStack
import net.minecraft.util.EnumFacing
import net.minecraft.util.Vec3
import net.minecraftforge.client.model.ISmartItemModel
import net.minecraftforge.common.property.IExtendedBlockState
import scala.collection.convert.WrapAsJava.bufferAsJavaList
import scala.collection.mutable
object NetSplitterModel extends SmartBlockModelBase with ISmartItemModel {
override def handleBlockState(state: IBlockState) = state match {
case extended: IExtendedBlockState => new BlockModel(extended)
case _ => missingModel
}
override def handleItemState(stack: ItemStack) = new ItemModel(stack)
protected def splitterTexture = Array(
Textures.getSprite(Textures.Block.NetSplitterTop),
Textures.getSprite(Textures.Block.NetSplitterTop),
Textures.getSprite(Textures.Block.NetSplitterSide),
Textures.getSprite(Textures.Block.NetSplitterSide),
Textures.getSprite(Textures.Block.NetSplitterSide),
Textures.getSprite(Textures.Block.NetSplitterSide)
)
protected final val BaseModel = {
val faces = mutable.ArrayBuffer.empty[BakedQuad]
// Bottom.
faces ++= bakeQuads(makeBox(new Vec3(0 / 16f, 0 / 16f, 5 / 16f), new Vec3(5 / 16f, 5 / 16f, 11 / 16f)), splitterTexture, None)
faces ++= bakeQuads(makeBox(new Vec3(11 / 16f, 0 / 16f, 5 / 16f), new Vec3(16 / 16f, 5 / 16f, 11 / 16f)), splitterTexture, None)
faces ++= bakeQuads(makeBox(new Vec3(5 / 16f, 0 / 16f, 0 / 16f), new Vec3(11 / 16f, 5 / 16f, 5 / 16f)), splitterTexture, None)
faces ++= bakeQuads(makeBox(new Vec3(5 / 16f, 0 / 16f, 11 / 16f), new Vec3(11 / 16f, 5 / 16f, 16 / 16f)), splitterTexture, None)
// Corners.
faces ++= bakeQuads(makeBox(new Vec3(0 / 16f, 0 / 16f, 0 / 16f), new Vec3(5 / 16f, 16 / 16f, 5 / 16f)), splitterTexture, None)
faces ++= bakeQuads(makeBox(new Vec3(11 / 16f, 0 / 16f, 0 / 16f), new Vec3(16 / 16f, 16 / 16f, 5 / 16f)), splitterTexture, None)
faces ++= bakeQuads(makeBox(new Vec3(0 / 16f, 0 / 16f, 11 / 16f), new Vec3(5 / 16f, 16 / 16f, 16 / 16f)), splitterTexture, None)
faces ++= bakeQuads(makeBox(new Vec3(11 / 16f, 0 / 16f, 11 / 16f), new Vec3(16 / 16f, 16 / 16f, 16 / 16f)), splitterTexture, None)
// Top.
faces ++= bakeQuads(makeBox(new Vec3(0 / 16f, 11 / 16f, 5 / 16f), new Vec3(5 / 16f, 16 / 16f, 11 / 16f)), splitterTexture, None)
faces ++= bakeQuads(makeBox(new Vec3(11 / 16f, 11 / 16f, 5 / 16f), new Vec3(16 / 16f, 16 / 16f, 11 / 16f)), splitterTexture, None)
faces ++= bakeQuads(makeBox(new Vec3(5 / 16f, 11 / 16f, 0 / 16f), new Vec3(11 / 16f, 16 / 16f, 5 / 16f)), splitterTexture, None)
faces ++= bakeQuads(makeBox(new Vec3(5 / 16f, 11 / 16f, 11 / 16f), new Vec3(11 / 16f, 16 / 16f, 16 / 16f)), splitterTexture, None)
faces.toArray
}
protected def addSideQuads(faces: mutable.ArrayBuffer[BakedQuad], openSides: Array[Boolean]): Unit = {
val down = openSides(EnumFacing.DOWN.ordinal())
faces ++= bakeQuads(makeBox(new Vec3(5 / 16f, if (down) 0 / 16f else 2 / 16f, 5 / 16f), new Vec3(11 / 16f, 5 / 16f, 11 / 16f)), splitterTexture, None)
val up = openSides(EnumFacing.UP.ordinal())
faces ++= bakeQuads(makeBox(new Vec3(5 / 16f, 11 / 16f, 5 / 16f), new Vec3(11 / 16f, if (up) 16 / 16f else 14f / 16f, 11 / 16f)), splitterTexture, None)
val north = openSides(EnumFacing.NORTH.ordinal())
faces ++= bakeQuads(makeBox(new Vec3(5 / 16f, 5 / 16f, if (north) 0 / 16f else 2 / 16f), new Vec3(11 / 16f, 11 / 16f, 5 / 16f)), splitterTexture, None)
val south = openSides(EnumFacing.SOUTH.ordinal())
faces ++= bakeQuads(makeBox(new Vec3(5 / 16f, 5 / 16f, 11 / 16f), new Vec3(11 / 16f, 11 / 16f, if (south) 16 / 16f else 14 / 16f)), splitterTexture, None)
val west = openSides(EnumFacing.WEST.ordinal())
faces ++= bakeQuads(makeBox(new Vec3(if (west) 0 / 16f else 2 / 16f, 5 / 16f, 5 / 16f), new Vec3(5 / 16f, 11 / 16f, 11 / 16f)), splitterTexture, None)
val east = openSides(EnumFacing.EAST.ordinal())
faces ++= bakeQuads(makeBox(new Vec3(11 / 16f, 5 / 16f, 5 / 16f), new Vec3(if (east) 16 / 16f else 14 / 16f, 11 / 16f, 11 / 16f)), splitterTexture, None)
}
class BlockModel(val state: IExtendedBlockState) extends SmartBlockModelBase {
override def getGeneralQuads =
state.getValue(block.property.PropertyTile.Tile) match {
case t: tileentity.NetSplitter =>
val faces = mutable.ArrayBuffer.empty[BakedQuad]
faces ++= BaseModel
addSideQuads(faces, EnumFacing.values().map(t.isSideOpen))
bufferAsJavaList(faces)
case _ => super.getGeneralQuads
}
}
class ItemModel(val stack: ItemStack) extends SmartBlockModelBase {
val data = new PrintData(stack)
override def getGeneralQuads = {
val faces = mutable.ArrayBuffer.empty[BakedQuad]
Textures.Block.bind()
faces ++= BaseModel
addSideQuads(faces, EnumFacing.values().map(_ => false))
bufferAsJavaList(faces)
}
}
}

View File

@ -32,11 +32,11 @@ object PrintModel extends SmartBlockModelBase with ISmartItemModel {
class BlockModel(val state: IExtendedBlockState) extends SmartBlockModelBase {
override def getGeneralQuads =
state.getValue(block.property.PropertyTile.Tile) match {
case print: tileentity.Print =>
case t: tileentity.Print =>
val faces = mutable.ArrayBuffer.empty[BakedQuad]
for (shape <- if (print.state) print.data.stateOn else print.data.stateOff if !Strings.isNullOrEmpty(shape.texture)) {
val bounds = shape.bounds.rotateTowards(print.facing)
for (shape <- if (t.state) t.data.stateOn else t.data.stateOff if !Strings.isNullOrEmpty(shape.texture)) {
val bounds = shape.bounds.rotateTowards(t.facing)
val texture = resolveTexture(shape.texture)
faces ++= bakeQuads(makeBox(bounds.min, bounds.max), Array.fill(6)(texture), shape.tint.getOrElse(NoTint))
}

View File

@ -0,0 +1,91 @@
package li.cil.oc.client.renderer.tileentity
import li.cil.oc.client.Textures
import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.texture.TextureMap
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.EnumFacing
import org.lwjgl.opengl.GL11
object NetSplitterRenderer extends TileEntitySpecialRenderer {
override def renderTileEntityAt(tileEntity: TileEntity, x: Double, y: Double, z: Double, f: Float, damage: Int) {
RenderState.checkError(getClass.getName + ".renderTileEntityAt: entering (aka: wasntme)")
val splitter = tileEntity.asInstanceOf[tileentity.NetSplitter]
if (splitter.openSides.contains(!splitter.isInverted)) {
RenderState.pushAttrib()
RenderState.disableEntityLighting()
RenderState.makeItBlend()
RenderState.pushMatrix()
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
GL11.glScaled(1.0025, -1.0025, 1.0025)
GL11.glTranslatef(-0.5f, -0.5f, -0.5f)
bindTexture(TextureMap.locationBlocksTexture)
val t = Tessellator.getInstance
val r = t.getWorldRenderer
Textures.Block.bind()
r.startDrawingQuads()
val sideActivity = Textures.getSprite(Textures.Block.NetSplitterOn)
if (splitter.isSideOpen(EnumFacing.DOWN)) {
r.addVertexWithUV(0, 1, 0, sideActivity.getMaxU, sideActivity.getMinV)
r.addVertexWithUV(1, 1, 0, sideActivity.getMinU, sideActivity.getMinV)
r.addVertexWithUV(1, 1, 1, sideActivity.getMinU, sideActivity.getMaxV)
r.addVertexWithUV(0, 1, 1, sideActivity.getMaxU, sideActivity.getMaxV)
}
if (splitter.isSideOpen(EnumFacing.UP)) {
r.addVertexWithUV(0, 0, 0, sideActivity.getMaxU, sideActivity.getMaxV)
r.addVertexWithUV(0, 0, 1, sideActivity.getMaxU, sideActivity.getMinV)
r.addVertexWithUV(1, 0, 1, sideActivity.getMinU, sideActivity.getMinV)
r.addVertexWithUV(1, 0, 0, sideActivity.getMinU, sideActivity.getMaxV)
}
if (splitter.isSideOpen(EnumFacing.NORTH)) {
r.addVertexWithUV(1, 1, 0, sideActivity.getMinU, sideActivity.getMaxV)
r.addVertexWithUV(0, 1, 0, sideActivity.getMaxU, sideActivity.getMaxV)
r.addVertexWithUV(0, 0, 0, sideActivity.getMaxU, sideActivity.getMinV)
r.addVertexWithUV(1, 0, 0, sideActivity.getMinU, sideActivity.getMinV)
}
if (splitter.isSideOpen(EnumFacing.SOUTH)) {
r.addVertexWithUV(0, 1, 1, sideActivity.getMinU, sideActivity.getMaxV)
r.addVertexWithUV(1, 1, 1, sideActivity.getMaxU, sideActivity.getMaxV)
r.addVertexWithUV(1, 0, 1, sideActivity.getMaxU, sideActivity.getMinV)
r.addVertexWithUV(0, 0, 1, sideActivity.getMinU, sideActivity.getMinV)
}
if (splitter.isSideOpen(EnumFacing.WEST)) {
r.addVertexWithUV(0, 1, 0, sideActivity.getMinU, sideActivity.getMaxV)
r.addVertexWithUV(0, 1, 1, sideActivity.getMaxU, sideActivity.getMaxV)
r.addVertexWithUV(0, 0, 1, sideActivity.getMaxU, sideActivity.getMinV)
r.addVertexWithUV(0, 0, 0, sideActivity.getMinU, sideActivity.getMinV)
}
if (splitter.isSideOpen(EnumFacing.EAST)) {
r.addVertexWithUV(1, 1, 1, sideActivity.getMinU, sideActivity.getMaxV)
r.addVertexWithUV(1, 1, 0, sideActivity.getMaxU, sideActivity.getMaxV)
r.addVertexWithUV(1, 0, 0, sideActivity.getMaxU, sideActivity.getMinV)
r.addVertexWithUV(1, 0, 1, sideActivity.getMinU, sideActivity.getMinV)
}
t.draw()
RenderState.enableEntityLighting()
RenderState.popMatrix()
RenderState.popAttrib()
}
RenderState.checkError(getClass.getName + ".renderTileEntityAt: leaving")
}
}

View File

@ -135,7 +135,7 @@ object Loot extends WeightedRandomChestContent(new ItemStack(null: Item), 1, 1,
def createLootDisk(name: String, path: String, external: Boolean, color: Option[EnumDyeColor] = None) = {
val callable = if (external) new Callable[FileSystem] {
override def call(): FileSystem = api.FileSystem.fromSaveDirectory("loot/" + path, 0, false)
override def call(): FileSystem = api.FileSystem.asReadOnly(api.FileSystem.fromSaveDirectory("loot/" + path, 0, false))
} else new Callable[FileSystem] {
override def call(): FileSystem = api.FileSystem.fromClass(OpenComputers.getClass, Settings.resourceDomain, "loot/" + path)
}

View File

@ -49,6 +49,7 @@ object PacketType extends Enumeration {
TextBufferMultiRawSetBackground,
TextBufferMultiRawSetForeground,
TextBufferPowerChange,
NetSplitterState,
ScreenTouchMode,
ServerPresence,
Sound,

View File

@ -3,6 +3,7 @@ package li.cil.oc.common.block
import li.cil.oc.Settings
import li.cil.oc.common.GuiType
import li.cil.oc.common.tileentity
import li.cil.oc.integration.coloredlights.ModColoredLights
import net.minecraft.block.state.IBlockState
import net.minecraft.util.BlockPos
import net.minecraft.util.EnumFacing
@ -10,7 +11,7 @@ import net.minecraft.world.IBlockAccess
import net.minecraft.world.World
class Assembler extends SimpleBlock with traits.PowerAcceptor with traits.StateAware with traits.GUI {
setLightLevel(0.34f)
ModColoredLights.setLightLevel(this, 0, 3, 5)
override def isOpaqueCube = false

View File

@ -3,13 +3,15 @@ package li.cil.oc.common.block
import java.util.Random
import li.cil.oc.common.tileentity
import li.cil.oc.integration.coloredlights.ModColoredLights
import net.minecraft.block.Block
import net.minecraft.block.state.IBlockState
import net.minecraft.util.BlockPos
import net.minecraft.world.World
class Capacitor extends SimpleBlock {
setLightLevel(0.34f)
ModColoredLights.setLightLevel(this, 5, 5, 5)
setTickRandomly(true)
// ----------------------------------------------------------------------- //

View File

@ -1,11 +1,12 @@
package li.cil.oc.common.block
import li.cil.oc.common.tileentity
import li.cil.oc.integration.coloredlights.ModColoredLights
import net.minecraft.block.state.IBlockState
import net.minecraft.world.World
class Geolyzer extends SimpleBlock {
setLightLevel(0.14f)
ModColoredLights.setLightLevel(this, 3, 1, 1)
// ----------------------------------------------------------------------- //

View File

@ -3,6 +3,7 @@ package li.cil.oc.common.block
import java.util
import li.cil.oc.common.tileentity
import li.cil.oc.integration.coloredlights.ModColoredLights
import li.cil.oc.util.Rarity
import li.cil.oc.util.Tooltip
import net.minecraft.block.state.IBlockState
@ -16,7 +17,7 @@ import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly
class Hologram(val tier: Int) extends SimpleBlock {
setLightLevel(1)
ModColoredLights.setLightLevel(this, 15, 15, 15)
setBlockBounds(0, 0, 0, 1, 0.5f, 1)
// ----------------------------------------------------------------------- //

View File

@ -0,0 +1,58 @@
package li.cil.oc.common.block
import li.cil.oc.common.tileentity
import li.cil.oc.integration.util.Wrench
import net.minecraft.block.properties.IProperty
import net.minecraft.block.state.IBlockState
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.util.BlockPos
import net.minecraft.util.EnumFacing
import net.minecraft.world.IBlockAccess
import net.minecraft.world.World
import net.minecraftforge.common.property.IExtendedBlockState
import net.minecraftforge.common.property.IUnlistedProperty
import scala.collection.mutable.ArrayBuffer
class NetSplitter extends RedstoneAware with traits.Extended {
override protected def setDefaultExtendedState(state: IBlockState) = setDefaultState(state)
override protected def addExtendedState(state: IBlockState, world: IBlockAccess, pos: BlockPos) =
(state, world.getTileEntity(pos)) match {
case (extendedState: IExtendedBlockState, t: tileentity.NetSplitter) =>
super.addExtendedState(extendedState.withProperty(property.PropertyTile.Tile, t), world, pos)
case _ => None
}
override protected def createProperties(listed: ArrayBuffer[IProperty], unlisted: ArrayBuffer[IUnlistedProperty[_]]) {
super.createProperties(listed, unlisted)
unlisted += property.PropertyTile.Tile
}
// ----------------------------------------------------------------------- //
override def isSideSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing): Boolean = false
// ----------------------------------------------------------------------- //
override def createNewTileEntity(world: World, meta: Int) = new tileentity.NetSplitter()
// ----------------------------------------------------------------------- //
// NOTE: must not be final for immibis microblocks to work.
override def onBlockActivated(world: World, pos: BlockPos, state: IBlockState, player: EntityPlayer, side: EnumFacing, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
if (Wrench.holdsApplicableWrench(player, pos)) {
val sideToToggle = if (player.isSneaking) side.getOpposite else side
world.getTileEntity(pos) match {
case splitter: tileentity.NetSplitter =>
if (!world.isRemote) {
val oldValue = splitter.openSides(sideToToggle.ordinal())
splitter.setSideOpen(sideToToggle, !oldValue)
}
true
case _ => false
}
}
else super.onBlockActivated(world, pos, state, player, side, hitX, hitY, hitZ)
}
}

View File

@ -1,11 +1,12 @@
package li.cil.oc.common.block
import li.cil.oc.common.tileentity
import li.cil.oc.integration.coloredlights.ModColoredLights
import net.minecraft.block.state.IBlockState
import net.minecraft.world.World
class PowerDistributor extends SimpleBlock {
setLightLevel(0.34f)
ModColoredLights.setLightLevel(this, 5, 5, 3)
// ----------------------------------------------------------------------- //

View File

@ -48,8 +48,8 @@ class Print(protected implicit val tileTag: ClassTag[tileentity.Print]) extends
override protected def addExtendedState(state: IBlockState, world: IBlockAccess, pos: BlockPos) =
(state, world.getTileEntity(pos)) match {
case (extendedState: IExtendedBlockState, print: tileentity.Print) =>
super.addExtendedState(extendedState.withProperty(property.PropertyTile.Tile, print), world, pos)
case (extendedState: IExtendedBlockState, t: tileentity.Print) =>
super.addExtendedState(extendedState.withProperty(property.PropertyTile.Tile, t), world, pos)
case _ => None
}

View File

@ -8,6 +8,7 @@ import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.common.GuiType
import li.cil.oc.common.tileentity
import li.cil.oc.integration.coloredlights.ModColoredLights
import li.cil.oc.integration.util.Wrench
import li.cil.oc.util.Color
import li.cil.oc.util.PackedColor
@ -33,7 +34,7 @@ import net.minecraftforge.fml.relauncher.SideOnly
import scala.collection.mutable.ArrayBuffer
class Screen(val tier: Int) extends RedstoneAware with traits.OmniRotatable {
setLightLevel(0.34f)
ModColoredLights.setLightLevel(this, 5, 5, 5)
override def isSideSolid(world: IBlockAccess, pos: BlockPos, side: EnumFacing) = toLocal(world, pos, side) != EnumFacing.SOUTH
@ -89,7 +90,7 @@ class Screen(val tier: Int) extends RedstoneAware with traits.OmniRotatable {
if (Wrench.holdsApplicableWrench(player, pos) && getValidRotations(world, pos).contains(side) && !force) false
else if (api.Items.get(player.getHeldItem) == api.Items.get(Constants.ItemName.Analyzer)) false
else world.getTileEntity(pos) match {
case screen: tileentity.Screen if screen.hasKeyboard && (force || player.isSneaking == screen.invertTouchMode) =>
case screen: tileentity.Screen if screen.hasKeyboard && (force || player.isSneaking == screen.origin.invertTouchMode) =>
// Yep, this GUI is actually purely client side. We could skip this
// if, but it is clearer this way (to trigger it from the server we
// would have to give screens a "container", which we do not want).

View File

@ -190,10 +190,10 @@ abstract class SimpleBlock(material: Material = Material.iron) extends BlockCont
override def recolorBlock(world: World, pos: BlockPos, side: EnumFacing, color: EnumDyeColor) =
world.getTileEntity(pos) match {
case colored: Colored if colored.color != color =>
colored.color = color
case colored: Colored if colored.color != Color.byMeta(color) =>
colored.color = Color.byMeta(color)
world.markBlockForUpdate(pos)
false // Don't consume items.
true // Blame Vexatos.
case _ => super.recolorBlock(world, pos, side, color)
}

View File

@ -0,0 +1,22 @@
package li.cil.oc.common.command
import net.minecraft.command.CommandBase
import net.minecraft.command.ICommandSender
import net.minecraft.util.BlockPos
import scala.collection.convert.WrapAsJava._
import scala.collection.mutable
abstract class SimpleCommand(val name: String) extends CommandBase {
protected var aliases = mutable.ListBuffer.empty[String]
override def getName = name
override def getAliases = aliases
override def canCommandSenderUse(source: ICommandSender) = true
override def isUsernameIndex(command: Array[String], i: Int) = false
override def addTabCompletionOptions(source: ICommandSender, command: Array[String], pos: BlockPos) = List.empty[AnyRef]
}

View File

@ -63,6 +63,10 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
private var _pendingCommands: Option[PacketBuilder] = None
private val syncInterval = 100
private var syncCooldown = syncInterval
private def pendingCommands = _pendingCommands.getOrElse {
val pb = new CompressedPacketBuilder(PacketType.TextBufferMulti)
pb.writeUTF(node.address)
@ -89,6 +93,8 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
val data = new util.TextBuffer(maxResolution, PackedColor.Depth.format(maxDepth))
def markInitialized(): Unit = syncCooldown = -1 // Stop polling for init state.
// ----------------------------------------------------------------------- //
override val canUpdate = true
@ -128,6 +134,14 @@ class TextBuffer(val host: EnvironmentHost) extends prefab.ManagedEnvironment wi
_pendingCommands.foreach(_.sendToPlayersNearHost(host, Option(Settings.get.maxWirelessRange * Settings.get.maxWirelessRange)))
_pendingCommands = None
}
if (SideTracker.isClient && syncCooldown > 0) {
syncCooldown -= 1
if (syncCooldown == 0) {
syncCooldown = syncInterval
ClientPacketSender.sendTextBufferInit(proxy.nodeAddress)
}
}
}
// ----------------------------------------------------------------------- //

View File

@ -34,6 +34,7 @@ object Blocks {
GameRegistry.registerTileEntity(classOf[tileentity.Switch], Settings.namespace + "switch")
GameRegistry.registerTileEntity(classOf[tileentity.Screen], Settings.namespace + "screen")
GameRegistry.registerTileEntity(classOf[tileentity.ServerRack], Settings.namespace + "serverRack")
GameRegistry.registerTileEntity(classOf[tileentity.NetSplitter], Settings.namespace + "netSplitter")
GameRegistry.registerTileEntity(classOf[tileentity.Waypoint], Settings.namespace + "waypoint")
Recipes.addBlock(new AccessPoint(), Constants.BlockName.AccessPoint, "oc:accessPoint")
@ -73,5 +74,8 @@ object Blocks {
// v1.5.10
Recipes.addBlock(new FakeEndstone(), Constants.BlockName.Endstone, "oc:stoneEndstone")
// v1.5.14
Recipes.addBlock(new NetSplitter(), Constants.BlockName.NetSplitter, "oc:netSplitter")
}
}

View File

@ -3,6 +3,7 @@ package li.cil.oc.common.template
import java.lang.reflect.Method
import com.google.common.base.Strings
import li.cil.oc.OpenComputers
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.common.IMC
@ -74,7 +75,11 @@ object AssemblerTemplates {
def validate(inventory: IInventory, slot: Int, stack: ItemStack) = validator match {
case Some(method) => IMC.tryInvokeStatic(method, inventory, slot.underlying(), tier.underlying(), stack)(false)
case _ => Option(hostClass.fold(api.Driver.driverFor(stack))(api.Driver.driverFor(stack, _))) match {
case Some(driver) => driver.slot(stack) == kind && driver.tier(stack) <= tier
case Some(driver) => try driver.slot(stack) == kind && driver.tier(stack) <= tier catch {
case t: AbstractMethodError =>
OpenComputers.log.warn(s"Error trying to query driver '${driver.getClass.getName}' for slot and/or tier information. Probably their fault. Yell at them before coming to OpenComputers for support. :P")
false
}
case _ => false
}
}

View File

@ -34,7 +34,7 @@ class AccessPoint extends Switch with WirelessEndpoint with traits.PowerAcceptor
case _ => None
}
override protected def energyThroughput = Settings.get.accessPointRate
override def energyThroughput = Settings.get.accessPointRate
// ----------------------------------------------------------------------- //

View File

@ -41,7 +41,7 @@ class Assembler extends traits.Environment with traits.PowerAcceptor with traits
override protected def connector(side: EnumFacing) = Option(if (side != EnumFacing.UP) node else null)
override protected def energyThroughput = Settings.get.assemblerRate
override def energyThroughput = Settings.get.assemblerRate
override def currentState = {
if (isAssembling) util.EnumSet.of(traits.State.IsWorking)

View File

@ -29,7 +29,7 @@ class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with
override protected def connector(side: EnumFacing) = Option(if (side != facing && machine != null) machine.node.asInstanceOf[Connector] else null)
override protected def energyThroughput = Settings.get.caseRate(tier)
override def energyThroughput = Settings.get.caseRate(tier)
def isCreative = tier == Tier.Four

View File

@ -45,7 +45,7 @@ class Charger extends traits.Environment with traits.PowerAcceptor with traits.R
override protected def connector(side: EnumFacing) = Option(if (side != facing) node else null)
override protected def energyThroughput = Settings.get.chargerRate
override def energyThroughput = Settings.get.chargerRate
override def currentState = {
// TODO Refine to only report working if present robots/drones actually *need* power.

View File

@ -36,7 +36,7 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
var disassembleNextInstantly = false
def progress = if (queue.isEmpty) 0 else (1 - (queue.size * Settings.get.disassemblerItemCost - buffer) / totalRequiredEnergy) * 100
def progress = if (queue.isEmpty) 0.0 else (1 - (queue.size * Settings.get.disassemblerItemCost - buffer) / totalRequiredEnergy) * 100
private def setActive(value: Boolean) = if (value != isActive) {
isActive = value
@ -51,7 +51,7 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
override protected def connector(side: EnumFacing) = Option(if (side != EnumFacing.UP) node else null)
override protected def energyThroughput = Settings.get.disassemblerRate
override def energyThroughput = Settings.get.disassemblerRate
override def currentState = {
if (isActive) util.EnumSet.of(traits.State.IsWorking)
@ -113,7 +113,7 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
private def drop(stack: ItemStack) {
if (stack != null) {
for (side <- EnumFacing.values if stack.stackSize > 0) {
InventoryUtils.insertIntoInventoryAt(stack, BlockPosition(this).offset(side), side.getOpposite)
InventoryUtils.insertIntoInventoryAt(stack, BlockPosition(this).offset(side), Some(side.getOpposite))
}
if (stack.stackSize > 0) {
spawnStackInWorld(stack, Option(EnumFacing.UP))
@ -160,7 +160,7 @@ class Disassembler extends traits.Environment with traits.PowerAcceptor with tra
override def isItemValidForSlot(i: Int, stack: ItemStack) =
allowDisassembling(stack) &&
(((Settings.get.disassembleAllTheThings || api.Items.get(stack) != null) && ItemUtils.getIngredients(stack).nonEmpty) ||
DisassemblerTemplates.select(stack) != None)
DisassemblerTemplates.select(stack).isDefined)
private def allowDisassembling(stack: ItemStack) = stack != null && (!stack.hasTagCompound || !stack.getTagCompound.getBoolean(Settings.namespace + "undisassemblable"))

View File

@ -57,7 +57,7 @@ class Microcontroller extends traits.PowerAcceptor with traits.Hub with traits.C
override protected def connector(side: EnumFacing) = Option(if (side != facing) snooperNode else null)
override protected def energyThroughput = Settings.get.caseRate(Tier.One)
override def energyThroughput = Settings.get.caseRate(Tier.One)
// ----------------------------------------------------------------------- //

View File

@ -0,0 +1,106 @@
package li.cil.oc.common.tileentity
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.network.Visibility
import li.cil.oc.common.EventHandler
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.EnumFacing
import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly
class NetSplitter extends traits.Environment with traits.RedstoneAware with api.network.SidedEnvironment {
private final val SideCount = EnumFacing.values().length
_isOutputEnabled = true
val node = api.Network.newNode(this, Visibility.None).
create()
var isInverted = false
var openSides = Array.fill(SideCount)(false)
def compressSides = (EnumFacing.values(), openSides).zipped.foldLeft(0)((acc, entry) => acc | (if (entry._2) 1 << entry._1.ordinal() else 0)).toByte
def uncompressSides(byte: Byte) = EnumFacing.values().map(d => ((1 << d.ordinal()) & byte) != 0)
def isSideOpen(side: EnumFacing) = side != null && {
val isOpen = openSides(side.ordinal())
if (isInverted) !isOpen else isOpen
}
def setSideOpen(side: EnumFacing, value: Boolean): Unit = if (side != null && openSides(side.ordinal()) != value) {
openSides(side.ordinal()) = value
if (isServer) {
node.remove()
api.Network.joinOrCreateNetwork(this)
ServerPacketSender.sendNetSplitterState(this)
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "tile.piston.out", 0.5f, world.rand.nextFloat() * 0.25f + 0.7f)
}
else {
world.markBlockForUpdate(getPos)
}
}
// ----------------------------------------------------------------------- //
override def sidedNode(side: EnumFacing) = if (isSideOpen(side)) node else null
@SideOnly(Side.CLIENT)
override def canConnect(side: EnumFacing) = isSideOpen(side)
// ----------------------------------------------------------------------- //
override def canUpdate = false
override protected def initialize(): Unit = {
super.initialize()
EventHandler.schedule(this)
}
// ----------------------------------------------------------------------- //
override protected def onRedstoneInputChanged(side: EnumFacing, oldMaxValue: Int, newMaxValue: Int): Unit = {
super.onRedstoneInputChanged(side, oldMaxValue, newMaxValue)
val oldIsInverted = isInverted
isInverted = newMaxValue > 0
if (isInverted != oldIsInverted) {
if (isServer) {
node.remove()
api.Network.joinOrCreateNetwork(this)
ServerPacketSender.sendNetSplitterState(this)
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "tile.piston.in", 0.5f, world.rand.nextFloat() * 0.25f + 0.7f)
}
else {
world.markBlockForUpdate(getPos)
}
}
}
override def readFromNBTForServer(nbt: NBTTagCompound): Unit = {
super.readFromNBTForServer(nbt)
isInverted = nbt.getBoolean(Settings.namespace + "isInverted")
openSides = uncompressSides(nbt.getByte(Settings.namespace + "openSides"))
}
override def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
super.writeToNBTForServer(nbt)
nbt.setBoolean(Settings.namespace + "isInverted", isInverted)
nbt.setByte(Settings.namespace + "openSides", compressSides)
}
@SideOnly(Side.CLIENT) override
def readFromNBTForClient(nbt: NBTTagCompound): Unit = {
super.readFromNBTForClient(nbt)
isInverted = nbt.getBoolean(Settings.namespace + "isInverted")
openSides = uncompressSides(nbt.getByte(Settings.namespace + "openSides"))
}
override def writeToNBTForClient(nbt: NBTTagCompound): Unit = {
super.writeToNBTForClient(nbt)
nbt.setBoolean(Settings.namespace + "isInverted", isInverted)
nbt.setByte(Settings.namespace + "openSides", compressSides)
}
}

View File

@ -17,7 +17,7 @@ class PowerConverter extends traits.PowerAcceptor with traits.Environment with t
override protected def connector(side: EnumFacing) = Option(node)
override protected def energyThroughput = Settings.get.powerConverterRate
override def energyThroughput = Settings.get.powerConverterRate
override def canUpdate = isServer
}

View File

@ -244,7 +244,7 @@ class Screen(var tier: Int) extends traits.TextBuffer with SidedEnvironment with
}
})
}
if (arrows.size > 0) {
if (arrows.nonEmpty) {
for (arrow <- arrows) {
val hitX = arrow.posX - x
val hitY = arrow.posY - y

View File

@ -58,7 +58,7 @@ class ServerRack extends traits.PowerAcceptor with traits.Hub with traits.PowerB
override protected def connector(side: EnumFacing) = Option(if (side != facing) sidedNode(side).asInstanceOf[Connector] else null)
override protected def energyThroughput = Settings.get.serverRackRate
override def energyThroughput = Settings.get.serverRackRate
// ----------------------------------------------------------------------- //

View File

@ -1,6 +1,7 @@
package li.cil.oc.common.tileentity.traits
import li.cil.oc.Settings
import li.cil.oc.common.EventHandler
import li.cil.oc.integration.Mods
import li.cil.oc.integration.util.BundledRedstone
import li.cil.oc.server.{PacketSender => ServerPacketSender}
@ -78,13 +79,18 @@ trait RedstoneAware extends RotationAware /* with IConnectable with IRedstoneEmi
if (isServer) {
if (shouldUpdateInput) {
shouldUpdateInput = false
for (side <- EnumFacing.values) {
updateRedstoneInput(side)
}
EnumFacing.values().foreach(updateRedstoneInput)
}
}
}
override def validate(): Unit = {
super.validate()
if (!canUpdate) {
EventHandler.schedule(() => EnumFacing.values().foreach(updateRedstoneInput))
}
}
def updateRedstoneInput(side: EnumFacing) {
input(side, BundledRedstone.computeInput(position, side))
}

View File

@ -1,11 +1,11 @@
package li.cil.oc.common.tileentity.traits.power
import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly
import li.cil.oc.Settings
import li.cil.oc.api.network.Connector
import li.cil.oc.common.tileentity.traits.TileEntity
import net.minecraft.util.EnumFacing
import net.minecraftforge.fml.relauncher.Side
import net.minecraftforge.fml.relauncher.SideOnly
trait Common extends TileEntity {
@SideOnly(Side.CLIENT)
@ -15,7 +15,7 @@ trait Common extends TileEntity {
// ----------------------------------------------------------------------- //
protected def energyThroughput: Double
def energyThroughput: Double
protected def tryAllSides(provider: (Double, EnumFacing) => Double, ratio: Double) {
// We make sure to only call this every `Settings.get.tickFrequency` ticks,
@ -37,7 +37,15 @@ trait Common extends TileEntity {
def canConnectPower(side: EnumFacing) =
!Settings.get.ignorePower && (if (isClient) hasConnector(side) else connector(side).isDefined)
def tryChangeBuffer(side: EnumFacing, amount: Double, doReceive: Boolean = true) =
/**
* Tries to inject the specified amount of energy into the buffer via the specified side.
*
* @param side the side to change the buffer through.
* @param amount the amount to change the buffer by.
* @param doReceive whether to actually inject energy or only simulate it.
* @return the amount of energy that was actually injected.
*/
def tryChangeBuffer(side: EnumFacing, amount: Double, doReceive: Boolean = true): Double =
if (isClient || Settings.get.ignorePower) 0
else connector(side) match {
case Some(node) =>
@ -47,14 +55,14 @@ trait Common extends TileEntity {
case _ => 0
}
def globalBuffer(side: EnumFacing) =
def globalBuffer(side: EnumFacing): Double =
if (isClient) 0
else connector(side) match {
case Some(node) => node.globalBuffer
case _ => 0
}
def globalBufferSize(side: EnumFacing) =
def globalBufferSize(side: EnumFacing): Double =
if (isClient) 0
else connector(side) match {
case Some(node) => node.globalBufferSize

View File

@ -32,6 +32,7 @@ object Mods {
val CoFHItem = new SimpleMod(IDs.CoFHItem)
val CoFHTileEntity = new SimpleMod(IDs.CoFHTileEntity)
val CoFHTransport = new SimpleMod(IDs.CoFHTransport)
val ColoredLights = new SimpleMod(IDs.ColoredLights)
val ComputerCraft = new SimpleMod(IDs.ComputerCraft, version = "@[1.73,)")
val CraftingCosts = new SimpleMod(IDs.CraftingCosts)
val DeepStorageUnit = new ClassBasedMod(IDs.DeepStorageUnit, "powercrystals.minefactoryreloaded.api.IDeepStorageUnit")()
@ -56,6 +57,7 @@ object Mods {
val NotEnoughKeys = new SimpleMod(IDs.NotEnoughKeys)
val OpenComputers = new SimpleMod(IDs.OpenComputers)
val PortalGun = new SimpleMod(IDs.PortalGun)
val PowerAdvantage = new SimpleMod(IDs.PowerAdvantage, version = "@[1.2.0,)", providesPower = true)
val ProjectRedCore = new SimpleMod(IDs.ProjectRedCore)
val ProjectRedTransmission = new SimpleMod(IDs.ProjectRedTransmission)
val Railcraft = new SimpleMod(IDs.Railcraft)
@ -105,6 +107,7 @@ object Mods {
// integration.mystcraft.ModMystcraft,
// integration.nek.ModNotEnoughKeys,
// integration.projectred.ModProjectRed,
integration.poweradvantage.ModPowerAdvantage,
// integration.railcraft.ModRailcraft,
// integration.redlogic.ModRedLogic,
// integration.stargatetech2.ModStargateTech2,
@ -165,6 +168,7 @@ object Mods {
final val CoFHItem = "CoFHAPI|item"
final val CoFHTileEntity = "CoFHAPI|tileentity"
final val CoFHTransport = "CoFHAPI|transport"
final val ColoredLights = "easycoloredlights"
final val ComputerCraft = "ComputerCraft"
final val CraftingCosts = "CraftingCosts"
final val ElectricalAge = "Eln"
@ -174,8 +178,7 @@ object Mods {
final val Factorization = "factorization"
final val Forestry = "Forestry"
final val ForgeMultipart = "ForgeMultipart"
final val DeepStorageUnit = "MineFactoryReloaded|DeepStorageUnit"
// Doesn't really exist.
final val DeepStorageUnit = "MineFactoryReloaded|DeepStorageUnit" // Doesn't really exist.
final val Galacticraft = "Galacticraft API"
final val GregTech = "gregtech"
final val IndustrialCraft2 = "IC2"
@ -190,6 +193,7 @@ object Mods {
final val NotEnoughKeys = "notenoughkeys"
final val OpenComputers = "OpenComputers"
final val PortalGun = "PortalGun"
final val PowerAdvantage = "poweradvantage"
final val ProjectRedCore = "ProjRed|Core"
final val ProjectRedTransmission = "ProjRed|Transmission"
final val Railcraft = "Railcraft"

View File

@ -0,0 +1,29 @@
package li.cil.oc.integration.coloredlights
/* TODO Colored Lights
import coloredlightscore.src.api.CLApi
*/
import li.cil.oc.integration.Mods
import net.minecraft.block.Block
// Doesn't need initialization, just a thin wrapper for block light value initialization.
object ModColoredLights {
def setLightLevel(block: Block, r: Int, g: Int, b: Int): Unit = {
// Extra layer of indirection because I've learned to be paranoid when it comes to class loading...
if (Mods.ColoredLights.isAvailable)
setColoredLightLevel(block, r, g, b)
else
setPlainLightLevel(block, r, g, b)
}
private def setColoredLightLevel(block: Block, r: Int, g: Int, b: Int): Unit = {
/* TODO Colored Lights
CLApi.setBlockColorRGB(block, r, g, b)
*/
}
private def setPlainLightLevel(block: Block, r: Int, g: Int, b: Int): Unit = {
val brightness = Array(r, g, b).max
block.setLightLevel((brightness + 0.1f) / 15f)
}
}

View File

@ -121,7 +121,7 @@ class SwitchPeripheral(val switch: Switch) extends IPeripheral {
}
private def checkPort(args: Array[AnyRef], index: Int) = {
if (args.length < index - 1 || !args(index).isInstanceOf[Double])
if (args.length < index - 1 || !args(index).isInstanceOf[Number])
throw new IllegalArgumentException(s"bad argument #${index + 1} (number expected)")
val port = args(index).asInstanceOf[Double].toInt
if (port < 0 || port > 0xFFFF)

View File

@ -4,6 +4,10 @@ import codechicken.lib.data.MCDataInput
import codechicken.lib.data.MCDataOutput
import codechicken.lib.vec.Cuboid6
import codechicken.lib.vec.Vector3
import codechicken.microblock.ISidedHollowConnect
import codechicken.multipart._
import cpw.mods.fml.relauncher.Side
import cpw.mods.fml.relauncher.SideOnly
import li.cil.oc.Constants
import li.cil.oc.Settings
import li.cil.oc.api
@ -27,7 +31,7 @@ import net.minecraft.util.MovingObjectPosition
import scala.collection.convert.WrapAsJava
import scala.collection.convert.WrapAsScala._
class CablePart(val original: Option[tileentity.Cable] = None) extends SimpleBlockPart with TCuboidPart with TNormalOcclusion with network.Environment {
class CablePart(val original: Option[tileentity.Cable] = None) extends SimpleBlockPart with TCuboidPart with TSlottedPart with ISidedHollowConnect with TNormalOcclusion with network.Environment {
val node = api.Network.newNode(this, Visibility.None).create()
private var _color = Color.LightGray
@ -64,6 +68,11 @@ class CablePart(val original: Option[tileentity.Cable] = None) extends SimpleBlo
override def getRenderBounds = new Cuboid6(Cable.bounds(world, x, y, z).offset(x, y, z))
override def getHollowSize(side: Int) = 4 // 4 pixels as this is width of cable.
override def getSlotMask = 1 << 6 // 6 is center part.
// ----------------------------------------------------------------------- //
override def activate(player: EntityPlayer, hit: MovingObjectPosition, item: ItemStack) = {

View File

@ -245,7 +245,6 @@ public class ConverterIIndividual implements Converter {
output.put("generation", bee.getGeneration());
output.put("hasEffect", bee.hasEffect());
output.put("isAlive", bee.isAlive());
output.put("isIrregularMating", bee.isIrregularMating());
output.put("isNatural", bee.isNatural());
if (isAnalyzed) genomeReader = new BeeGenomeReader(bee.getGenome());

View File

@ -27,7 +27,7 @@ object DriverAPU extends DriverCPU with HostAware with EnvironmentAware {
override def cpuTier(stack: ItemStack) =
Delegator.subItem(stack) match {
case Some(apu: common.item.APU) => apu.tier
case Some(apu: common.item.APU) => apu.cpuTier
case _ => Tier.One
}

View File

@ -33,7 +33,7 @@ abstract class DriverCPU extends Item with Processor {
def cpuTier(stack: ItemStack): Int =
Delegator.subItem(stack) match {
case Some(cpu: item.CPU) => cpu.tier
case Some(cpu: item.CPU) => cpu.cpuTier
case _ => Tier.One
}

View File

@ -30,7 +30,7 @@ object DriverGraphicsCard extends Item with HostAware with EnvironmentAware {
override def tier(stack: ItemStack) =
Delegator.subItem(stack) match {
case Some(gpu: common.item.GraphicsCard) => gpu.tier
case Some(gpu: common.item.GraphicsCard) => gpu.gpuTier
case _ => Tier.One
}

View File

@ -0,0 +1,46 @@
package li.cil.oc.integration.poweradvantage
import cyano.poweradvantage.api.ConduitType
import cyano.poweradvantage.api.modsupport.ILightWeightPowerAcceptor
import cyano.poweradvantage.api.modsupport.LightWeightPowerRegistry
import li.cil.oc.Settings
import li.cil.oc.common.block
import li.cil.oc.common.tileentity.traits.PowerAcceptor
import net.minecraft.block.Block
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.EnumFacing
import scala.collection.convert.WrapAsScala._
object LightWeightPowerAcceptor extends ILightWeightPowerAcceptor {
def init(): Unit = {
Block.blockRegistry.collect {
case b: Block with block.traits.PowerAcceptor =>
LightWeightPowerRegistry.registerLightWeightPowerAcceptor(b, this)
}
}
def canAcceptEnergyType(powerType: ConduitType) = ConduitType.areSameType(powerType, "electricity")
def getEnergyDemand(tileEntity: TileEntity, powerType: ConduitType) = tileEntity match {
case acceptor: PowerAcceptor if canAcceptEnergyType(powerType) =>
(EnumFacing.values().map(side => {
val capacity = acceptor.globalBufferSize(side)
val stored = acceptor.globalBuffer(side)
capacity - stored
}).max / Settings.get.ratioPowerAdvantage).toInt
case _ => 0
}
def addEnergy(tileEntity: TileEntity, amountAdded: Float, powerType: ConduitType) = tileEntity match {
case acceptor: PowerAcceptor if canAcceptEnergyType(powerType) =>
var remainingEnergy = math.min(amountAdded, acceptor.energyThroughput) * Settings.get.ratioPowerAdvantage
// .exists() for early exit.
EnumFacing.values().exists(side => {
remainingEnergy -= acceptor.tryChangeBuffer(side, remainingEnergy)
remainingEnergy <= 0
})
amountAdded - (remainingEnergy / Settings.get.ratioPowerAdvantage).toFloat
case _ => 0
}
}

View File

@ -0,0 +1,12 @@
package li.cil.oc.integration.poweradvantage
import li.cil.oc.integration.ModProxy
import li.cil.oc.integration.Mods
object ModPowerAdvantage extends ModProxy {
override def getMod = Mods.PowerAdvantage
override def initialize(): Unit = {
LightWeightPowerAcceptor.init()
}
}

View File

@ -1,90 +0,0 @@
package li.cil.oc.server
import li.cil.oc.Settings
import net.minecraft.command.CommandBase
import net.minecraft.command.ICommandSender
import net.minecraft.command.WrongUsageException
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.util.BlockPos
import net.minecraftforge.fml.common.event.FMLServerStartingEvent
import scala.collection.convert.wrapAsJava._
import scala.collection.mutable
object CommandHandler {
def register(e: FMLServerStartingEvent) {
e.registerServerCommand(WirelessRenderingCommand)
e.registerServerCommand(NonDisassemblyAgreementCommand)
}
// OP levels for reference:
// 1 - Ops can bypass spawn protection.
// 2 - Ops can use /clear, /difficulty, /effect, /gamemode, /gamerule, /give, /summon, /setblock and /tp, and can edit command blocks.
// 3 - Ops can use /ban, /deop, /kick, and /op.
// 4 - Ops can use /stop.
object WirelessRenderingCommand extends SimpleCommand("oc_renderWirelessNetwork") {
aliases += "oc_wlan"
override def getCommandUsage(source: ICommandSender) = name + " <boolean>"
override def execute(sender: ICommandSender, command: Array[String]) {
Settings.rTreeDebugRenderer =
if (command != null && command.length > 0)
CommandBase.parseBoolean(command(0))
else
!Settings.rTreeDebugRenderer
}
override def getRequiredPermissionLevel = 2
}
object NonDisassemblyAgreementCommand extends SimpleCommand("oc_preventDisassembling") {
aliases += "oc_nodis"
aliases += "oc_prevdis"
override def getCommandUsage(source: ICommandSender) = name + " <boolean>"
override def execute(sender: ICommandSender, command: Array[String]) {
sender match {
case player: EntityPlayer =>
val stack = player.getHeldItem
if (stack != null) {
if (!stack.hasTagCompound) {
stack.setTagCompound(new NBTTagCompound())
}
val nbt = stack.getTagCompound
val preventDisassembly =
if (command != null && command.length > 0)
CommandBase.parseBoolean(command(0))
else
!nbt.getBoolean(Settings.namespace + "undisassemblable")
if (preventDisassembly)
nbt.setBoolean(Settings.namespace + "undisassemblable", true)
else
nbt.removeTag(Settings.namespace + "undisassemblable")
if (nbt.hasNoTags) stack.setTagCompound(null)
}
case _ => throw new WrongUsageException("Can only be used by players.")
}
}
override def getRequiredPermissionLevel = 2
}
abstract class SimpleCommand(val name: String) extends CommandBase {
protected var aliases = mutable.ListBuffer.empty[String]
override def getName = name
override def getAliases = aliases
override def canCommandSenderUse(sender: ICommandSender) = true
override def addTabCompletionOptions(sender: ICommandSender, args: Array[String], pos: BlockPos) = List.empty[AnyRef]
override def isUsernameIndex(command: Array[String], i: Int) = false
}
}

View File

@ -522,6 +522,16 @@ object PacketSender {
pb.sendToPlayersNearHost(host)
}
def sendNetSplitterState(t: tileentity.NetSplitter): Unit = {
val pb = new SimplePacketBuilder(PacketType.NetSplitterState)
pb.writeTileEntity(t)
pb.writeBoolean(t.isInverted)
pb.writeByte(t.compressSides)
pb.sendToPlayersNearTileEntity(t)
}
def sendScreenTouchMode(t: tileentity.Screen, value: Boolean) {
val pb = new SimplePacketBuilder(PacketType.ScreenTouchMode)

View File

@ -0,0 +1,11 @@
package li.cil.oc.server.command
import net.minecraftforge.fml.common.event.FMLServerStartingEvent
object CommandHandler {
def register(e: FMLServerStartingEvent) {
e.registerServerCommand(NonDisassemblyAgreementCommand)
e.registerServerCommand(WirelessRenderingCommand)
e.registerServerCommand(SpawnComputerCommand)
}
}

View File

@ -0,0 +1,48 @@
package li.cil.oc.server.command
import li.cil.oc.Settings
import li.cil.oc.common.command.SimpleCommand
import net.minecraft.command.CommandBase
import net.minecraft.command.ICommandSender
import net.minecraft.command.WrongUsageException
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
object NonDisassemblyAgreementCommand extends SimpleCommand("oc_preventDisassembling") {
aliases += "oc_nodis"
aliases += "oc_prevdis"
override def getCommandUsage(source: ICommandSender) = name + " <boolean>"
override def execute(source: ICommandSender, command: Array[String]) {
source match {
case player: EntityPlayer =>
val stack = player.getHeldItem
if (stack != null) {
if (!stack.hasTagCompound) {
stack.setTagCompound(new NBTTagCompound())
}
val nbt = stack.getTagCompound
val preventDisassembly =
if (command != null && command.length > 0)
CommandBase.parseBoolean(command(0))
else
!nbt.getBoolean(Settings.namespace + "undisassemblable")
if (preventDisassembly)
nbt.setBoolean(Settings.namespace + "undisassemblable", true)
else
nbt.removeTag(Settings.namespace + "undisassemblable")
if (nbt.hasNoTags) stack.setTagCompound(null)
}
case _ => throw new WrongUsageException("Can only be used by players.")
}
}
// OP levels for reference:
// 1 - Ops can bypass spawn protection.
// 2 - Ops can use /clear, /difficulty, /effect, /gamemode, /gamerule, /give, /summon, /setblock and /tp, and can edit command blocks.
// 3 - Ops can use /ban, /deop, /kick, and /op.
// 4 - Ops can use /stop.
override def getRequiredPermissionLevel = 2
}

View File

@ -0,0 +1,76 @@
package li.cil.oc.server.command
import li.cil.oc.Constants
import li.cil.oc.api
import li.cil.oc.common.command.SimpleCommand
import li.cil.oc.common.tileentity
import li.cil.oc.util.BlockPosition
import li.cil.oc.util.ExtendedWorld._
import li.cil.oc.util.InventoryUtils
import net.minecraft.command.ICommandSender
import net.minecraft.command.WrongUsageException
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.util.ChatComponentText
import net.minecraft.util.EnumFacing
import net.minecraft.util.MovingObjectPosition
import net.minecraft.util.Vec3
object SpawnComputerCommand extends SimpleCommand("oc_spawnComputer") {
aliases += "oc_sc"
final val MaxDistance = 16
override def getCommandUsage(source: ICommandSender): String = name
override def execute(source: ICommandSender, command: Array[String]) {
source match {
case player: EntityPlayer =>
val world = player.getEntityWorld
val origin = new Vec3(player.posX, player.posY + player.getEyeHeight, player.posZ)
val direction = player.getLookVec
val lookAt = origin.addVector(direction.xCoord * MaxDistance, direction.yCoord * MaxDistance, direction.zCoord * MaxDistance)
world.rayTraceBlocks(origin, lookAt) match {
case hit: MovingObjectPosition if hit.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK =>
val hitPos = BlockPosition(hit.getBlockPos, world)
val casePos = hitPos.offset(hit.sideHit)
val screenPos = casePos.offset(EnumFacing.UP)
val keyboardPos = screenPos.offset(EnumFacing.UP)
if (!world.isAirBlock(casePos) || !world.isAirBlock(screenPos) || !world.isAirBlock(keyboardPos)) {
player.addChatMessage(new ChatComponentText("Target position obstructed."))
return
}
world.setBlock(casePos, api.Items.get(Constants.BlockName.CaseCreative).block())
world.setBlock(screenPos, api.Items.get(Constants.BlockName.ScreenTier2).block())
world.setBlock(keyboardPos, api.Items.get(Constants.BlockName.Keyboard).block())
world.getTileEntity(keyboardPos) match {
case t: tileentity.traits.Rotatable => t.setFromFacing(EnumFacing.UP)
case _ => // ???
}
world.getTileEntity(screenPos) match {
case t: tileentity.traits.Rotatable => t.setFromFacing(EnumFacing.NORTH)
case _ => // ???
}
api.Network.joinOrCreateNetwork(world.getTileEntity(casePos))
InventoryUtils.insertIntoInventoryAt(api.Items.get(Constants.ItemName.APUCreative).createItemStack(1), casePos)
InventoryUtils.insertIntoInventoryAt(api.Items.get(Constants.ItemName.RAMTier6).createItemStack(2), casePos)
InventoryUtils.insertIntoInventoryAt(api.Items.get(Constants.ItemName.HDDTier3).createItemStack(1), casePos)
InventoryUtils.insertIntoInventoryAt(api.Items.get(Constants.ItemName.LuaBios).createItemStack(1), casePos)
InventoryUtils.insertIntoInventoryAt(api.Items.get(Constants.ItemName.OpenOS).createItemStack(1), casePos)
case _ => player.addChatMessage(new ChatComponentText("You need to be looking at a nearby block."))
}
case _ => throw new WrongUsageException("Can only be used by players.")
}
}
// OP levels for reference:
// 1 - Ops can bypass spawn protection.
// 2 - Ops can use /clear, /difficulty, /effect, /gamemode, /gamerule, /give, /summon, /setblock and /tp, and can edit command blocks.
// 3 - Ops can use /ban, /deop, /kick, and /op.
// 4 - Ops can use /stop.
override def getRequiredPermissionLevel = 2
}

View File

@ -0,0 +1,28 @@
package li.cil.oc.server.command
import li.cil.oc.Settings
import li.cil.oc.common.command.SimpleCommand
import net.minecraft.command.CommandBase
import net.minecraft.command.ICommandSender
object WirelessRenderingCommand extends SimpleCommand("oc_renderWirelessNetwork") {
aliases += "oc_wlan"
override def getCommandUsage(source: ICommandSender) = name + " <boolean>"
override def execute(source: ICommandSender, command: Array[String]) {
Settings.rTreeDebugRenderer =
if (command != null && command.length > 0)
CommandBase.parseBoolean(command(0))
else
!Settings.rTreeDebugRenderer
}
// OP levels for reference:
// 1 - Ops can bypass spawn protection.
// 2 - Ops can use /clear, /difficulty, /effect, /gamemode, /gamerule, /give, /summon, /setblock and /tp, and can edit command blocks.
// 3 - Ops can use /ban, /deop, /kick, and /op.
// 4 - Ops can use /stop.
override def getRequiredPermissionLevel = 2
}

View File

@ -99,6 +99,10 @@ object FileSystem extends api.detail.FileSystemAPI {
def fromMemory(capacity: Long): api.fs.FileSystem = new RamFileSystem(capacity)
override def asReadOnly(fileSystem: api.fs.FileSystem) =
if (fileSystem.isReadOnly) fileSystem
else new ReadOnlyWrapper(fileSystem)
def asManagedEnvironment(fileSystem: api.fs.FileSystem, label: Label, host: EnvironmentHost, accessSound: String, speed: Int) =
Option(fileSystem).flatMap(fs => Some(component.FileSystem(fs, label, Option(host), Option(accessSound), speed))).orNull

View File

@ -0,0 +1,47 @@
package li.cil.oc.server.fs
import java.io.FileNotFoundException
import li.cil.oc.api
import li.cil.oc.api.fs.Mode
import net.minecraft.nbt.NBTTagCompound
private class ReadOnlyWrapper(val fileSystem: api.fs.FileSystem) extends api.fs.FileSystem {
override def isReadOnly = true
override def spaceTotal = fileSystem.spaceUsed()
override def spaceUsed = fileSystem.spaceUsed()
override def exists(path: String) = fileSystem.exists(path)
override def size(path: String) = fileSystem.size(path)
override def isDirectory(path: String) = fileSystem.isDirectory(path)
override def lastModified(path: String) = fileSystem.lastModified(path)
override def list(path: String) = fileSystem.list(path)
override def delete(path: String) = false
override def makeDirectory(path: String) = false
override def rename(from: String, to: String) = false
override def setLastModified(path: String, time: Long) = false
override def open(path: String, mode: Mode) = mode match {
case Mode.Read => fileSystem.open(path, mode)
case Mode.Write => throw new FileNotFoundException()
case Mode.Append => throw new FileNotFoundException()
}
override def getHandle(handle: Int) = fileSystem.getHandle(handle)
override def close() = fileSystem.close()
override def load(nbt: NBTTagCompound) = fileSystem.load(nbt)
override def save(nbt: NBTTagCompound) = fileSystem.save(nbt)
}

View File

@ -25,7 +25,7 @@ class OSAPI(owner: NativeLuaArchitecture) extends NativeLuaAPI(owner) {
else "%d/%m/%y %H:%M:%S"
val time =
if (lua.getTop > 1 && lua.isNumber(2)) lua.toNumber(2) * 1000 / 60 / 60
else machine.worldTime + 5000
else machine.worldTime + 6000
val dt = GameTimeFormatter.parse(time)
def fmt(format: String) {

View File

@ -18,7 +18,7 @@ class OSAPI(owner: LuaJLuaArchitecture) extends LuaJAPI(owner) {
else "%d/%m/%y %H:%M:%S"
val time =
if (args.narg > 1 && args.isnumber(2)) args.todouble(2) * 1000 / 60 / 60
else machine.worldTime + 5000
else machine.worldTime + 6000
val dt = GameTimeFormatter.parse(time)
def fmt(format: String) = {

View File

@ -64,6 +64,8 @@ object Color {
val byTier = Array(EnumDyeColor.SILVER, EnumDyeColor.YELLOW, EnumDyeColor.CYAN, EnumDyeColor.MAGENTA)
def byMeta(meta: EnumDyeColor) = byOreName(dyes(meta.getDyeDamage))
def findDye(stack: ItemStack) = byOreName.keys.find(OreDictionary.getOres(_).exists(oreStack => OreDictionary.itemMatches(stack, oreStack, false)))
def isDye(stack: ItemStack) = findDye(stack).isDefined

View File

@ -67,8 +67,8 @@ object GameTimeFormatter {
def parse(time: Double) = {
var day = (time / 24000).toLong
val weekDay = ((4 + day) % 7).toInt
val year = 1970 + (day / 365.2425).toInt
val yearDay = (day % 365.2425).toInt
val year = 1970 + (day / 364.2425).toInt
val yearDay = (day % 364.2425).toInt
day = yearDay
val monthLengths = monthLengthsForYear(year)
var month = 0
@ -80,7 +80,7 @@ object GameTimeFormatter {
var seconds = ((time % 24000) * 60 * 60 / 1000).toInt
var minutes = seconds / 60
seconds = seconds % 60
val hours = (1 + minutes / 60) % 24
val hours = (minutes / 60) % 24
minutes = minutes % 60
new DateTime(year, month + 1, day.toInt + 1, weekDay + 1, yearDay + 1, hours, minutes, seconds)
@ -107,7 +107,6 @@ object GameTimeFormatter {
val monthLengths = monthLengthsForYear(year)
val days = ((year - 1970) * 365.2425).ceil.toInt + (0 until mon - 1).foldLeft(0)((d, m) => d + monthLengths(m)) + mday - 1
val secs = sec + (min + (hour - 1 + days * 24) * 60) * 60
if (secs < 0) None
else Option(secs)
Option(secs)
}
}

View File

@ -211,8 +211,8 @@ object InventoryUtils {
* Utility method for calling <tt>insertIntoInventory</tt> on an inventory
* in the world.
*/
def insertIntoInventoryAt(stack: ItemStack, position: BlockPosition, side: EnumFacing, limit: Int = 64, simulate: Boolean = false): Boolean =
inventoryAt(position).exists(insertIntoInventory(stack, _, Option(side), limit, simulate))
def insertIntoInventoryAt(stack: ItemStack, position: BlockPosition, side: Option[EnumFacing] = None, limit: Int = 64, simulate: Boolean = false): Boolean =
inventoryAt(position).exists(insertIntoInventory(stack, _, side, limit, simulate))
/**
* Utility method for calling <tt>extractFromInventory</tt> on an inventory

View File

@ -12,13 +12,14 @@ class RTree[Data](private val M: Int)(implicit val coordinate: Data => (Double,
private var root = new NonLeaf()
def apply(value: Data): Option[(Double, Double, Double)] =
def apply(value: Data): Option[(Double, Double, Double)] = this.synchronized {
entries.get(value).fold(None: Option[(Double, Double, Double)])(position => Some(position.bounds.min.asTuple))
}
// Allows debug rendering of the tree.
def allBounds = root.allBounds(0)
def allBounds = this.synchronized(root.allBounds(0))
def add(value: Data): Boolean = {
def add(value: Data): Boolean = this.synchronized {
val replaced = remove(value)
val entry = new Leaf(value, new Point(value))
entries += value -> entry
@ -29,7 +30,7 @@ class RTree[Data](private val M: Int)(implicit val coordinate: Data => (Double,
!replaced
}
def remove(value: Data): Boolean =
def remove(value: Data): Boolean = this.synchronized {
entries.remove(value) match {
case Some(node) =>
val change = root.remove(node)
@ -43,9 +44,11 @@ class RTree[Data](private val M: Int)(implicit val coordinate: Data => (Double,
true
case _ => false
}
}
def query(from: (Double, Double, Double), to: (Double, Double, Double)) =
def query(from: (Double, Double, Double), to: (Double, Double, Double)) = this.synchronized {
root.query(new Rectangle(new Point(from), new Point(to)))
}
private abstract class Node {
def bounds: Rectangle