mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-17 11:15:12 -04:00
Added architecture switching on CPUs by shift-right clicking them.
Fixed an issue with synchronized calls potentially throwing limit reached exceptions.
This commit is contained in:
parent
ca68021166
commit
092bd17a84
@ -2,6 +2,11 @@ package li.cil.oc.api.machine;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This interface abstracts away any language specific details for the Machine.
|
||||
* <p/>
|
||||
@ -11,12 +16,6 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
* Java Lua architecture (using LuaJ).
|
||||
*/
|
||||
public interface Architecture {
|
||||
/**
|
||||
* A display friendly name of the architecture, mainly intended to be used
|
||||
* when iterating all {@link li.cil.oc.api.Machine#architectures()}.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Used to check if the machine is fully initialized. If this is false no
|
||||
* signals for detected components will be generated. Avoids duplicate
|
||||
@ -133,4 +132,16 @@ public interface Architecture {
|
||||
* @param nbt the tag compound to save to.
|
||||
*/
|
||||
void save(NBTTagCompound nbt);
|
||||
|
||||
/**
|
||||
* Architectures can be annotated with this to provide a nice display name.
|
||||
* <p/>
|
||||
* This is used when the name of an architecture has to be displayed to the
|
||||
* user, such as when cycling architectures on a CPU.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
static @interface Name {
|
||||
String value();
|
||||
}
|
||||
}
|
||||
|
@ -195,6 +195,7 @@ oc:tooltip.CircuitBoard=Mühsam ernährt sich das Eichhörnchen. Wenn es groß w
|
||||
oc:tooltip.ControlUnit=Klingt wichtig, ist es auch. Man baut daraus immerhin CPUs. Wie könnte es da nicht wichtig sein.
|
||||
oc:tooltip.ComponentBus=Diese Erweiterung erlaubt es es Servern, mit noch mehr Komponenten gleichzeitig zu kommunizieren, ähnlich wie CPUs.[nl] Supported components: §f%s§7.
|
||||
oc:tooltip.CPU=Kernstück eines jeden Computers. Die Taktrate hat einen leichten Schatten, aber was kann man von einer Taschensonnenuhr schon erwarten?[nl] Unterstützte Komponenten: §f%s§7.
|
||||
oc:tooltip.CPU.Architecture=Architektur: §f%s§7
|
||||
oc:tooltip.CuttingWire=Wird gebraucht, um Tonblöcke in Leiterplattenform zu bekommen. Vermutlich das ineffizienteste Werkzeug in der Geschichte der Menschheit, da es nach einer Verwendung kaputt geht.
|
||||
oc:tooltip.DebugCard=Kreativ-Modus-Gegenstand, erlaubt es die Welt zu manipulieren um das Testen zu erleichtern. Verwendung auf eigene Gefahr.
|
||||
oc:tooltip.Disassembler=Zerlegt Gegenstände in ihre Einzelteile. §lWarnung§7: zurückgewonnene Gegenstände haben eine %s%%-ige Chance beim Extrahieren kaputt zu gehen!
|
||||
|
@ -195,6 +195,7 @@ oc:tooltip.CircuitBoard=Now we're getting somewhere. Can be etched to obtain a p
|
||||
oc:tooltip.ControlUnit=This is the unit that... controls... stuff. You need it to build a CPU. So yeah, totally important.
|
||||
oc:tooltip.ComponentBus=This expansion allows servers to communicate with more components at the same time, similar to how CPUs do.[nl] Supported components: §f%s§7.
|
||||
oc:tooltip.CPU=An essential component of all computers. The clock rate is a bit unreliable, but what do you expect when it runs on a pocket sundial?[nl] Supported components: §f%s§7.
|
||||
oc:tooltip.CPU.Architecture=Architecture: §f%s§7
|
||||
oc:tooltip.CuttingWire=Used to cut clay blocks into circuit board shape. Breaks after one use, which probably makes it the most inefficient tool ever.
|
||||
oc:tooltip.DebugCard=Creative mode item, allows manipulating the world to make testing easier. Use at your own peril.
|
||||
oc:tooltip.Disassembler=Separates items into their original components. §lWarning§7: returned items have a %s%% chance of breaking in the process!
|
||||
|
@ -480,12 +480,13 @@ local function isDirect(address, method)
|
||||
return cachedValue
|
||||
end
|
||||
local methods, reason = spcall(component.methods, address)
|
||||
if methods then
|
||||
for name, info in pairs(methods) do
|
||||
if name == method then
|
||||
directCache[cacheKey] = info.direct
|
||||
return info.direct
|
||||
end
|
||||
if not methods then
|
||||
return false
|
||||
end
|
||||
for name, info in pairs(methods) do
|
||||
if name == method then
|
||||
directCache[cacheKey] = info.direct
|
||||
return info.direct
|
||||
end
|
||||
end
|
||||
error("no such method", 1)
|
||||
|
@ -62,6 +62,7 @@ class Proxy {
|
||||
api.Machine.LuaArchitecture =
|
||||
if (LuaStateFactory.isAvailable && !Settings.get.forceLuaJ) classOf[NativeLuaArchitecture]
|
||||
else classOf[LuaJLuaArchitecture]
|
||||
api.Machine.add(api.Machine.LuaArchitecture)
|
||||
api.Network.instance = network.Network
|
||||
|
||||
if (Mods.ForgeMultipart.isAvailable) {
|
||||
|
@ -1,6 +1,19 @@
|
||||
package li.cil.oc.common.item
|
||||
|
||||
import java.util
|
||||
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.machine.Architecture
|
||||
import li.cil.oc.util.Tooltip
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.ChatComponentTranslation
|
||||
import net.minecraft.world.World
|
||||
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
import scala.language.existentials
|
||||
|
||||
class CPU(val parent: Delegator, val tier: Int) extends Delegate with ItemTier {
|
||||
override val unlocalizedName = super.unlocalizedName + tier
|
||||
@ -8,4 +21,49 @@ class CPU(val parent: Delegator, val tier: Int) extends Delegate with ItemTier {
|
||||
override protected def tooltipName = Option(super.unlocalizedName)
|
||||
|
||||
override protected def tooltipData = Seq(Settings.get.cpuComponentSupport(tier))
|
||||
|
||||
override protected def tooltipExtended(stack: ItemStack, tooltip: util.List[String]) {
|
||||
(if (stack.hasTagCompound) {
|
||||
Option(stack.getTagCompound.getString(Settings.namespace + "archName"))
|
||||
}
|
||||
else {
|
||||
val architectures = allArchitectures
|
||||
architectures.headOption.map(_._2)
|
||||
}) match {
|
||||
case Some(archName) => tooltip.addAll(Tooltip.get("CPU.Architecture", archName))
|
||||
case _ => // No architecture.
|
||||
}
|
||||
}
|
||||
|
||||
override def onItemRightClick(stack: ItemStack, world: World, player: EntityPlayer) = {
|
||||
if (player.isSneaking) {
|
||||
if (!world.isRemote) {
|
||||
val architectures = allArchitectures
|
||||
if (architectures.length > 0) {
|
||||
val currentIndex = if (stack.hasTagCompound) {
|
||||
val currentArch = stack.getTagCompound.getString(Settings.namespace + "archClass")
|
||||
architectures.indexWhere(_._1.getName == currentArch)
|
||||
}
|
||||
else {
|
||||
stack.setTagCompound(new NBTTagCompound())
|
||||
-1
|
||||
}
|
||||
val index = (currentIndex + 1) % architectures.length
|
||||
val (archClass, archName) = architectures(index)
|
||||
stack.getTagCompound.setString(Settings.namespace + "archClass", archClass.getName)
|
||||
stack.getTagCompound.setString(Settings.namespace + "archName", archName)
|
||||
player.addChatMessage(new ChatComponentTranslation(Settings.namespace + "tooltip.CPU.Architecture", archName))
|
||||
}
|
||||
player.swingItem()
|
||||
}
|
||||
}
|
||||
stack
|
||||
}
|
||||
|
||||
private def allArchitectures = api.Machine.architectures.map { arch =>
|
||||
arch.getAnnotation(classOf[Architecture.Name]) match {
|
||||
case annotation: Architecture.Name => (arch, annotation.value)
|
||||
case _ => (arch, arch.getSimpleName)
|
||||
}
|
||||
}.toArray
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
package li.cil.oc.server.driver.item
|
||||
|
||||
import li.cil.oc.OpenComputers
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.Machine
|
||||
import li.cil.oc.api.driver.EnvironmentHost
|
||||
import li.cil.oc.api.driver.item.Processor
|
||||
import li.cil.oc.api.machine.Architecture
|
||||
import li.cil.oc.common.Slot
|
||||
import li.cil.oc.common.init.Items
|
||||
import li.cil.oc.common.item
|
||||
import net.minecraft.item.ItemStack
|
||||
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
|
||||
object CPU extends Item with Processor {
|
||||
override def worksWith(stack: ItemStack) =
|
||||
isOneOf(stack, api.Items.get("cpu1"), api.Items.get("cpu2"), api.Items.get("cpu3"))
|
||||
@ -30,5 +33,15 @@ object CPU extends Item with Processor {
|
||||
case _ => 0
|
||||
}
|
||||
|
||||
override def architecture(stack: ItemStack) = Machine.LuaArchitecture
|
||||
override def architecture(stack: ItemStack) = {
|
||||
if (stack.hasTagCompound) {
|
||||
val archClass = stack.getTagCompound.getString(Settings.namespace + "archClass")
|
||||
try Class.forName(archClass).asSubclass(classOf[Architecture]) catch {
|
||||
case t: Throwable =>
|
||||
OpenComputers.log.warn("Failed getting class for CPU architecture.", t)
|
||||
null
|
||||
}
|
||||
}
|
||||
else api.Machine.architectures.headOption.orNull
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,9 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
|
||||
@volatile private var callBudget = 0.0
|
||||
|
||||
// We want to ignore the call limit in synchronized calls to avoid errors.
|
||||
private var inSynchronizedCall = false
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
var worldTime = 0L // Game-world time for os.time().
|
||||
@ -268,7 +271,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
case _ => throw new NoSuchMethodException()
|
||||
}
|
||||
|
||||
private def checkLimit(limit: Int) {
|
||||
private def checkLimit(limit: Int): Unit = if (!inSynchronizedCall) {
|
||||
val callCost = math.max(1.0 / limit, 0.001)
|
||||
if (callCost >= callBudget) {
|
||||
throw new LimitReachedException()
|
||||
@ -421,16 +424,13 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
}
|
||||
// Perform a synchronized call (message sending).
|
||||
case Machine.State.SynchronizedCall =>
|
||||
// Reset direct call budget again, just to be on the safe side...
|
||||
// Theoretically it'd be possible for the executor to do some direct
|
||||
// calls between the clear and the state check, which could in turn
|
||||
// make this synchronized call fail due the limit still being maxed.
|
||||
callBudget = maxCallBudget
|
||||
// We switch into running state, since we'll behave as though the call
|
||||
// were performed from our executor thread.
|
||||
switchTo(Machine.State.Running)
|
||||
try {
|
||||
inSynchronizedCall = true
|
||||
architecture.runSynchronized()
|
||||
inSynchronizedCall = false
|
||||
// Check if the callback called pause() or stop().
|
||||
state.top match {
|
||||
case Machine.State.Running =>
|
||||
@ -451,6 +451,9 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
OpenComputers.log.warn("Faulty architecture implementation for synchronized calls.", e)
|
||||
crash("gui.Error.InternalError")
|
||||
}
|
||||
finally {
|
||||
inSynchronizedCall = false
|
||||
}
|
||||
|
||||
assert(state.top != Machine.State.Running)
|
||||
case _ => // Nothing special to do, just avoid match errors.
|
||||
@ -871,7 +874,8 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
}
|
||||
|
||||
object Machine extends MachineAPI {
|
||||
val checked = mutable.Set.empty[Class[_ <: Architecture]]
|
||||
// Keep registration order, to allow deterministic iteration of the architectures.
|
||||
val checked = mutable.LinkedHashSet.empty[Class[_ <: Architecture]]
|
||||
|
||||
override def add(architecture: Class[_ <: Architecture]) {
|
||||
if (!checked.contains(architecture)) {
|
||||
@ -885,7 +889,7 @@ object Machine extends MachineAPI {
|
||||
}
|
||||
}
|
||||
|
||||
override def architectures() = scala.collection.convert.WrapAsJava.asJavaIterable(checked)
|
||||
override def architectures = scala.collection.convert.WrapAsJava.asJavaIterable(checked)
|
||||
|
||||
override def create(host: MachineHost) = new Machine(host)
|
||||
|
||||
|
@ -4,6 +4,9 @@ import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
|
||||
import com.google.common.base.Strings
|
||||
import li.cil.oc.OpenComputers
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.machine.Architecture
|
||||
import li.cil.oc.api.machine.ExecutionResult
|
||||
import li.cil.oc.api.machine.LimitReachedException
|
||||
@ -11,12 +14,10 @@ import li.cil.oc.common.SaveHandler
|
||||
import li.cil.oc.server.machine.Machine
|
||||
import li.cil.oc.util.ExtendedLuaState.extendLuaState
|
||||
import li.cil.oc.util.LuaStateFactory
|
||||
import li.cil.oc.OpenComputers
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
import li.cil.repack.com.naef.jnlua._
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
@Architecture.Name("Lua")
|
||||
class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architecture {
|
||||
private[machine] var lua: LuaState = null
|
||||
|
||||
@ -127,8 +128,6 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def name() = "Lua"
|
||||
|
||||
override def isInitialized = kernelMemory > 0
|
||||
|
||||
override def recomputeMemory() = Option(lua) match {
|
||||
|
@ -4,19 +4,20 @@ import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
|
||||
import com.google.common.base.Strings
|
||||
import li.cil.oc.OpenComputers
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.machine.Architecture
|
||||
import li.cil.oc.api.machine.ExecutionResult
|
||||
import li.cil.oc.api.machine.LimitReachedException
|
||||
import li.cil.oc.server.machine.Machine
|
||||
import li.cil.oc.util.ScalaClosure
|
||||
import li.cil.oc.util.ScalaClosure._
|
||||
import li.cil.oc.OpenComputers
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
import li.cil.repack.org.luaj.vm2._
|
||||
import li.cil.repack.org.luaj.vm2.lib.jse.JsePlatform
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
@Architecture.Name("LuaJ")
|
||||
class LuaJLuaArchitecture(val machine: api.machine.Machine) extends Architecture {
|
||||
private[machine] var lua: Globals = _
|
||||
|
||||
@ -90,8 +91,6 @@ class LuaJLuaArchitecture(val machine: api.machine.Machine) extends Architecture
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def name() = "LuaJ"
|
||||
|
||||
override def isInitialized = doneWithInitRun
|
||||
|
||||
override def recomputeMemory() = memory = machine.host.installedMemory
|
||||
|
Loading…
x
Reference in New Issue
Block a user