mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-18 11:48:02 -04:00
overscaling chars on screens a little (amount configurable) to (hopefully) suppress/reduce render glitches on less accurate graphics cards
fixed potential NPE in analyzer fixed minor derp in adapter triggering ic2 events in tick handler to avoid recreating tile entity in invalidate in certain cases (RiM) saving chunk coords in computer nbt for reliably loading them again even when moved (RiM or similar)
This commit is contained in:
parent
4c564d72d9
commit
75f661696f
@ -61,6 +61,10 @@ opencomputers {
|
||||
# The volume multiplier applied to sounds from this mod like the computer
|
||||
# running noise. Disable sounds by setting this to zero.
|
||||
soundVolume: 1.0
|
||||
|
||||
# This is the scaling of the individual chars rendered on screens. This
|
||||
# is set to slightly overscale per default, to avoid
|
||||
fontCharScale: 1.01
|
||||
}
|
||||
|
||||
# Computer related settings, concerns server performance and security.
|
||||
|
@ -29,6 +29,7 @@ class Settings(config: Config) {
|
||||
val pasteShortcut = config.getStringList("client.pasteShortcut").toSet
|
||||
val robotLabels = config.getBoolean("client.robotLabels")
|
||||
val soundVolume = config.getDouble("client.soundVolume").toFloat max 0 min 2
|
||||
val fontCharScale = config.getDouble("client.fontCharScale") max 0.5 min 2
|
||||
val rTreeDebugRenderer = false // *Not* to be configurable via config file.
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
@ -43,6 +43,9 @@ object MonospaceFontRenderer {
|
||||
|
||||
// Set up the display lists.
|
||||
{
|
||||
val s = Settings.get.fontCharScale
|
||||
val dw = charWidth * s - charWidth
|
||||
val dh = charHeight * s - charHeight
|
||||
val t = Tessellator.instance
|
||||
// Now create lists for all printable chars.
|
||||
for (index <- 1 until 0xFF) {
|
||||
@ -52,10 +55,10 @@ object MonospaceFontRenderer {
|
||||
val v = y * vStep
|
||||
GL11.glNewList(charLists + index, GL11.GL_COMPILE)
|
||||
t.startDrawingQuads()
|
||||
t.addVertexWithUV(0, charHeight, 0, u, v + vSize)
|
||||
t.addVertexWithUV(charWidth, charHeight, 0, u + uSize, v + vSize)
|
||||
t.addVertexWithUV(charWidth, 0, 0, u + uSize, v)
|
||||
t.addVertexWithUV(0, 0, 0, u, v)
|
||||
t.addVertexWithUV(-dw, charHeight * s, 0, u, v + vSize)
|
||||
t.addVertexWithUV(charWidth * s, charHeight * s, 0, u + uSize, v + vSize)
|
||||
t.addVertexWithUV(charWidth * s, -dh, 0, u + uSize, v)
|
||||
t.addVertexWithUV(-dw, -dh, 0, u, v)
|
||||
t.draw()
|
||||
GL11.glTranslatef(charWidth, 0, 0)
|
||||
GL11.glEndList()
|
||||
|
@ -19,7 +19,13 @@ object SaveHandler {
|
||||
|
||||
def scheduleSave(dimension: Int, chunk: ChunkCoordIntPair, name: String, data: Array[Byte]) = saveData.synchronized {
|
||||
if (chunk == null) throw new IllegalArgumentException("chunk is null")
|
||||
else saveData.getOrElseUpdate(dimension, mutable.Map.empty).getOrElseUpdate(chunk, mutable.Map.empty) += name -> data
|
||||
else {
|
||||
val chunks = saveData.getOrElseUpdate(dimension, mutable.Map.empty)
|
||||
// Make sure we get rid of old versions (e.g. left over by other mods
|
||||
// triggering a save - this is mostly used for RiM compatibility).
|
||||
chunks.values.foreach(_ -= name)
|
||||
chunks.getOrElseUpdate(chunk, mutable.Map.empty) += name -> data
|
||||
}
|
||||
}
|
||||
|
||||
def load(dimension: Int, chunk: ChunkCoordIntPair, name: String): Array[Byte] = {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package li.cil.oc.common.item
|
||||
|
||||
import cpw.mods.fml.common.network.Player
|
||||
import java.util
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api.network._
|
||||
@ -70,8 +69,8 @@ class Analyzer(val parent: Delegator) extends Delegate {
|
||||
player.sendChatToPlayer(ChatMessageComponent.createFromTranslationWithSubstitutions(
|
||||
Settings.namespace + "gui.Analyzer.Address",
|
||||
address))
|
||||
PacketSender.sendAnalyze(address, player)
|
||||
}
|
||||
PacketSender.sendAnalyze(address, player)
|
||||
}
|
||||
|
||||
override def registerIcons(iconRegister: IconRegister) {
|
||||
|
@ -27,7 +27,7 @@ class Adapter extends traits.Environment with Analyzable {
|
||||
|
||||
override def updateEntity() {
|
||||
super.updateEntity()
|
||||
if (blocks.nonEmpty) {
|
||||
if (updatingBlocks.nonEmpty) {
|
||||
for (block <- updatingBlocks) {
|
||||
block.update()
|
||||
}
|
||||
@ -100,6 +100,13 @@ class Adapter extends traits.Environment with Analyzable {
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def onDisconnect(node: Node) {
|
||||
super.onDisconnect(node)
|
||||
if (node == this.node) {
|
||||
updatingBlocks.clear()
|
||||
}
|
||||
}
|
||||
|
||||
override def readFromNBT(nbt: NBTTagCompound) {
|
||||
super.readFromNBT(nbt)
|
||||
|
||||
|
@ -0,0 +1,9 @@
|
||||
package li.cil.oc.common.tileentity.traits
|
||||
|
||||
import ic2.api.energy.tile.IEnergySink
|
||||
import cpw.mods.fml.common.Optional
|
||||
|
||||
@Optional.Interface(iface = "ic2.api.energy.tile.IEnergySink", modid = "IC2")
|
||||
trait IC2PowerGridAware extends IEnergySink {
|
||||
var addedToPowerGrid = false
|
||||
}
|
@ -4,21 +4,19 @@ import buildcraft.api.power.{PowerHandler, IPowerReceptor}
|
||||
import cofh.api.energy.IEnergyHandler
|
||||
import cpw.mods.fml.common.{ModAPIManager, Loader, Optional}
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import ic2.api.energy.event.{EnergyTileUnloadEvent, EnergyTileLoadEvent}
|
||||
import ic2.api.energy.tile.IEnergySink
|
||||
import li.cil.oc.api.network.Connector
|
||||
import li.cil.oc.server.TickHandler
|
||||
import li.cil.oc.Settings
|
||||
import net.minecraftforge.common.{MinecraftForge, ForgeDirection}
|
||||
import net.minecraftforge.common.ForgeDirection
|
||||
import universalelectricity.api.energy.{IEnergyContainer, IEnergyInterface}
|
||||
|
||||
@Optional.InterfaceList(Array(
|
||||
new Optional.Interface(iface = "buildcraft.api.power.IPowerReceptor", modid = "BuildCraftAPI|power"),
|
||||
new Optional.Interface(iface = "ic2.api.energy.tile.IEnergySink", modid = "IC2"),
|
||||
new Optional.Interface(iface = "cofh.api.energy.IEnergyHandler", modid = "ThermalExpansion"),
|
||||
new Optional.Interface(iface = "universalelectricity.api.energy.IEnergyInterface", modid = "UniversalElectricity"),
|
||||
new Optional.Interface(iface = "universalelectricity.api.energy.IEnergyContainer", modid = "UniversalElectricity")
|
||||
))
|
||||
trait PowerAcceptor extends TileEntity with IPowerReceptor with IEnergySink with IEnergyHandler with IEnergyInterface with IEnergyContainer {
|
||||
trait PowerAcceptor extends TileEntity with IPowerReceptor with IC2PowerGridAware with IEnergyHandler with IEnergyInterface with IEnergyContainer {
|
||||
@SideOnly(Side.CLIENT)
|
||||
protected def hasConnector(side: ForgeDirection) = false
|
||||
|
||||
@ -99,22 +97,14 @@ trait PowerAcceptor extends TileEntity with IPowerReceptor with IEnergySink with
|
||||
// ----------------------------------------------------------------------- //
|
||||
// IndustrialCraft2
|
||||
|
||||
private var addedToPowerGrid = false
|
||||
|
||||
@Optional.Method(modid = "IC2")
|
||||
def loadIC2() {
|
||||
if (!addedToPowerGrid) {
|
||||
MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this))
|
||||
addedToPowerGrid = true
|
||||
}
|
||||
if (!addedToPowerGrid) TickHandler.scheduleIC2Add(this)
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "IC2")
|
||||
def unloadIC2() {
|
||||
if (addedToPowerGrid) {
|
||||
MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this))
|
||||
addedToPowerGrid = false
|
||||
}
|
||||
if (addedToPowerGrid) TickHandler.scheduleIC2Remove(this)
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "IC2")
|
||||
|
@ -2,35 +2,58 @@ package li.cil.oc.server
|
||||
|
||||
import codechicken.multipart.TMultiPart
|
||||
import cpw.mods.fml.common.{FMLCommonHandler, Optional, TickType, ITickHandler}
|
||||
import ic2.api.energy.event.{EnergyTileUnloadEvent, EnergyTileLoadEvent}
|
||||
import java.util
|
||||
import li.cil.oc.api.Network
|
||||
import li.cil.oc.common.tileentity.traits.IC2PowerGridAware
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
import scala.collection.mutable
|
||||
import li.cil.oc.OpenComputers
|
||||
import java.util.logging.Level
|
||||
|
||||
object TickHandler extends ITickHandler {
|
||||
val pendingAdds = mutable.Buffer.empty[() => Unit]
|
||||
val pending = mutable.Buffer.empty[() => Unit]
|
||||
|
||||
def schedule(tileEntity: TileEntity) =
|
||||
if (FMLCommonHandler.instance.getEffectiveSide.isServer) pendingAdds.synchronized {
|
||||
pendingAdds += (() => Network.joinOrCreateNetwork(tileEntity))
|
||||
if (FMLCommonHandler.instance.getEffectiveSide.isServer) pending.synchronized {
|
||||
pending += (() => Network.joinOrCreateNetwork(tileEntity))
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "ForgeMultipart")
|
||||
def schedule(part: TMultiPart) =
|
||||
if (FMLCommonHandler.instance.getEffectiveSide.isServer) pendingAdds.synchronized {
|
||||
pendingAdds += (() => Network.joinOrCreateNetwork(part.tile))
|
||||
if (FMLCommonHandler.instance.getEffectiveSide.isServer) pending.synchronized {
|
||||
pending += (() => Network.joinOrCreateNetwork(part.tile))
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "IC2")
|
||||
def scheduleIC2Add(tileEntity: TileEntity with IC2PowerGridAware) = pending.synchronized {
|
||||
pending += (() => if (!tileEntity.addedToPowerGrid && !tileEntity.isInvalid) {
|
||||
MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(tileEntity))
|
||||
tileEntity.addedToPowerGrid = true
|
||||
})
|
||||
}
|
||||
|
||||
@Optional.Method(modid = "IC2")
|
||||
def scheduleIC2Remove(tileEntity: TileEntity with IC2PowerGridAware) = pending.synchronized {
|
||||
pending += (() => if (tileEntity.addedToPowerGrid) {
|
||||
MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(tileEntity))
|
||||
tileEntity.addedToPowerGrid = false
|
||||
})
|
||||
}
|
||||
|
||||
override def getLabel = "OpenComputers Network Initialization Ticker"
|
||||
|
||||
override def ticks() = util.EnumSet.of(TickType.SERVER)
|
||||
|
||||
override def tickStart(`type`: util.EnumSet[TickType], tickData: AnyRef*) {}
|
||||
|
||||
override def tickEnd(`type`: util.EnumSet[TickType], tickData: AnyRef*) = pendingAdds.synchronized {
|
||||
for (callback <- pendingAdds) {
|
||||
callback()
|
||||
override def tickEnd(`type`: util.EnumSet[TickType], tickData: AnyRef*) = pending.synchronized {
|
||||
for (callback <- pending) {
|
||||
try callback() catch {
|
||||
case t: Throwable => OpenComputers.log.log(Level.WARNING, "Error in scheduled tick action.", t)
|
||||
}
|
||||
}
|
||||
pendingAdds.clear()
|
||||
pending.clear()
|
||||
}
|
||||
}
|
||||
|
@ -505,10 +505,10 @@ class Machine(val owner: Owner, val rom: Option[ManagedEnvironment], constructor
|
||||
for ((address, name) <- _components) {
|
||||
if (node.network.node(address) == null) {
|
||||
if (name == "filesystem") {
|
||||
OpenComputers.log.fine("A component of type '%s' disappeared! This usually means that it didn't save its node.".format(name))
|
||||
OpenComputers.log.fine(s"A component of type '$name' disappeared ($address)! This usually means that it didn't save its node.")
|
||||
OpenComputers.log.fine("If this was a file system provided by a ComputerCraft peripheral, this is normal.")
|
||||
}
|
||||
else OpenComputers.log.warning("A component of type '%s' disappeared! This usually means that it didn't save its node.".format(name))
|
||||
else OpenComputers.log.warning(s"A component of type '$name' disappeared ($address)! This usually means that it didn't save its node.")
|
||||
signal("component_removed", address, name)
|
||||
invalid += address
|
||||
}
|
||||
|
@ -596,10 +596,18 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
|
||||
// on. First, clear the stack, meaning the current kernel.
|
||||
lua.setTop(0)
|
||||
|
||||
// Since we have no world yet, we rely on the dimension we were saved in.
|
||||
// Same goes for the chunk. This also works around issues with computers
|
||||
// being moved (e.g. Redstone in Motion).
|
||||
val dimension = nbt.getInteger("dimension")
|
||||
val chunk =
|
||||
if (nbt.hasKey("chunkX") && nbt.hasKey("chunkZ"))
|
||||
new ChunkCoordIntPair(nbt.getInteger("chunkX"), nbt.getInteger("chunkZ"))
|
||||
else
|
||||
new ChunkCoordIntPair(machine.owner.x >> 4, machine.owner.z >> 4)
|
||||
val kernel =
|
||||
if (nbt.hasKey("kernel")) nbt.getByteArray("kernel")
|
||||
else SaveHandler.load(dimension, new ChunkCoordIntPair(machine.owner.x >> 4, machine.owner.z >> 4), node.address + "_kernel")
|
||||
else SaveHandler.load(dimension, chunk, node.address + "_kernel")
|
||||
unpersist(kernel)
|
||||
if (!lua.isThread(1)) {
|
||||
// This shouldn't really happen, but there's a chance it does if
|
||||
@ -609,7 +617,7 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
|
||||
if (state.contains(Machine.State.SynchronizedCall) || state.contains(Machine.State.SynchronizedReturn)) {
|
||||
val stack =
|
||||
if (nbt.hasKey("stack")) nbt.getByteArray("stack")
|
||||
else SaveHandler.load(dimension, new ChunkCoordIntPair(machine.owner.x >> 4, machine.owner.z >> 4), node.address + "_stack")
|
||||
else SaveHandler.load(dimension, chunk, node.address + "_stack")
|
||||
unpersist(stack)
|
||||
if (!(if (state.contains(Machine.State.SynchronizedCall)) lua.isFunction(2) else lua.isTable(2))) {
|
||||
// Same as with the above, should not really happen normally, but
|
||||
@ -637,14 +645,20 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
|
||||
// Try persisting Lua, because that's what all of the rest depends on.
|
||||
// Save the kernel state (which is always at stack index one).
|
||||
assert(lua.isThread(1))
|
||||
|
||||
// We have to save the dimension and chunk coordinates, because they are
|
||||
// not available on load / may have changed if the computer was moved.
|
||||
val dimension = machine.owner.world.provider.dimensionId
|
||||
val chunk = new ChunkCoordIntPair(machine.owner.x >> 4, machine.owner.z >> 4)
|
||||
nbt.setInteger("dimension", dimension)
|
||||
SaveHandler.scheduleSave(dimension, new ChunkCoordIntPair(machine.owner.x >> 4, machine.owner.z >> 4), node.address + "_kernel", persist(1))
|
||||
nbt.setInteger("chunkX", chunk.chunkXPos)
|
||||
nbt.setInteger("chunkZ", chunk.chunkZPos)
|
||||
SaveHandler.scheduleSave(dimension, chunk, node.address + "_kernel", persist(1))
|
||||
// While in a driver call we have one object on the global stack: either
|
||||
// the function to call the driver with, or the result of the call.
|
||||
if (state.contains(Machine.State.SynchronizedCall) || state.contains(Machine.State.SynchronizedReturn)) {
|
||||
assert(if (state.contains(Machine.State.SynchronizedCall)) lua.isFunction(2) else lua.isTable(2))
|
||||
SaveHandler.scheduleSave(dimension, new ChunkCoordIntPair(machine.owner.x >> 4, machine.owner.z >> 4), node.address + "_stack", persist(2))
|
||||
SaveHandler.scheduleSave(dimension, chunk, node.address + "_stack", persist(2))
|
||||
}
|
||||
|
||||
nbt.setInteger("kernelMemory", math.ceil(kernelMemory / ramScale).toInt)
|
||||
|
Loading…
x
Reference in New Issue
Block a user