mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-13 01:10:19 -04:00
fixed timers firing continuously after setting the time to a future date; fixed date stuff after realizing /time set sets world time absolutely (too used to nei by far...); added proper os.date implementation;
This commit is contained in:
parent
eb3a8e1ff8
commit
2a48cb28d9
@ -214,7 +214,11 @@ sandbox = {
|
|||||||
|
|
||||||
os = {
|
os = {
|
||||||
clock = os.clock,
|
clock = os.clock,
|
||||||
date = os.date,
|
date = function(format, time)
|
||||||
|
checkArg(1, format, "string", "nil")
|
||||||
|
checkArg(2, time, "number", "nil")
|
||||||
|
return os.date(format, time)
|
||||||
|
end,
|
||||||
difftime = function(t2, t1)
|
difftime = function(t2, t1)
|
||||||
return t2 - t1
|
return t2 - t1
|
||||||
end,
|
end,
|
||||||
|
1
assets/opencomputers/lua/rom/bin/time.lua
Normal file
1
assets/opencomputers/lua/rom/bin/time.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
print(os.date("%F %T"))
|
@ -45,7 +45,7 @@ local function tick()
|
|||||||
if timer.times <= 0 then
|
if timer.times <= 0 then
|
||||||
timers[id] = nil
|
timers[id] = nil
|
||||||
else
|
else
|
||||||
timer.after = timer.after + timer.interval
|
timer.after = os.uptime() + timer.interval
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -72,6 +72,7 @@ class Computer(isClient: Boolean) extends Rotatable with ComputerEnvironment wit
|
|||||||
super.updateEntity()
|
super.updateEntity()
|
||||||
if (node != null && node.network == null) {
|
if (node != null && node.network == null) {
|
||||||
Network.joinOrCreateNetwork(worldObj, xCoord, yCoord, zCoord)
|
Network.joinOrCreateNetwork(worldObj, xCoord, yCoord, zCoord)
|
||||||
|
this.synchronized(powerConsumed = 0.0)
|
||||||
}
|
}
|
||||||
else if (!worldObj.isRemote) {
|
else if (!worldObj.isRemote) {
|
||||||
// If we just joined a network we were just loaded from disk. We skip the
|
// If we just joined a network we were just loaded from disk. We skip the
|
||||||
|
@ -13,7 +13,7 @@ import li.cil.oc.api.network._
|
|||||||
import li.cil.oc.common.tileentity
|
import li.cil.oc.common.tileentity
|
||||||
import li.cil.oc.server
|
import li.cil.oc.server
|
||||||
import li.cil.oc.util.ExtendedLuaState.extendLuaState
|
import li.cil.oc.util.ExtendedLuaState.extendLuaState
|
||||||
import li.cil.oc.util.LuaStateFactory
|
import li.cil.oc.util.{GameTimeFormatter, LuaStateFactory}
|
||||||
import li.cil.oc.{OpenComputers, Config}
|
import li.cil.oc.{OpenComputers, Config}
|
||||||
import net.minecraft.nbt._
|
import net.minecraft.nbt._
|
||||||
import net.minecraft.tileentity.TileEntity
|
import net.minecraft.tileentity.TileEntity
|
||||||
@ -112,7 +112,7 @@ class Computer(val owner: Computer.Environment) extends Persistable with Runnabl
|
|||||||
switchTo(Computer.State.Starting)
|
switchTo(Computer.State.Starting)
|
||||||
|
|
||||||
// Remember when we started, for os.clock().
|
// Remember when we started, for os.clock().
|
||||||
timeStarted = owner.world.getWorldInfo.getWorldTotalTime
|
timeStarted = owner.world.getWorldTime
|
||||||
|
|
||||||
// Mark state change in owner, to send it to clients.
|
// Mark state change in owner, to send it to clients.
|
||||||
owner.markAsChanged(8) // Initial power required to start.
|
owner.markAsChanged(8) // Initial power required to start.
|
||||||
@ -214,12 +214,12 @@ class Computer(val owner: Computer.Environment) extends Persistable with Runnabl
|
|||||||
// pause.
|
// pause.
|
||||||
lastUpdate = System.currentTimeMillis
|
lastUpdate = System.currentTimeMillis
|
||||||
|
|
||||||
// TODO This seems to be the "run time", not the elapsed ingame time. For example, when doing /time set 0 the game
|
// Update world time for time().
|
||||||
// should jump to the next day, but this value does not jump. Is this just Forge or do we have to find some other
|
worldTime = owner.world.getWorldTime
|
||||||
// way around this? CC seems to use getWorldTime, which is really odd, since that should be only within the range
|
if (isRunning) {
|
||||||
// of a single day (0 to 24000), which it *is*... perhaps vanilla Minecraft (not re-compiled) behaves different?
|
// We can have rollbacks from '/time set'. Avoid getting negative uptimes.
|
||||||
// Update world time for computer threads.
|
timeStarted = timeStarted min worldTime
|
||||||
worldTime = owner.world.getWorldInfo.getWorldTotalTime
|
}
|
||||||
|
|
||||||
// Check if we should switch states.
|
// Check if we should switch states.
|
||||||
state.synchronized(state.top match {
|
state.synchronized(state.top match {
|
||||||
@ -231,7 +231,6 @@ class Computer(val owner: Computer.Environment) extends Persistable with Runnabl
|
|||||||
// Resuming after being loaded.
|
// Resuming after being loaded.
|
||||||
case Computer.State.Resuming if System.currentTimeMillis() >= sleepUntil => {
|
case Computer.State.Resuming if System.currentTimeMillis() >= sleepUntil => {
|
||||||
verifyComponents()
|
verifyComponents()
|
||||||
owner.markAsChanged(Double.NegativeInfinity)
|
|
||||||
state.pop()
|
state.pop()
|
||||||
switchTo(state.top) // Trigger execution if necessary.
|
switchTo(state.top) // Trigger execution if necessary.
|
||||||
}
|
}
|
||||||
@ -622,13 +621,57 @@ class Computer(val owner: Computer.Environment) extends Persistable with Runnabl
|
|||||||
})
|
})
|
||||||
lua.setField(-2, "clock")
|
lua.setField(-2, "clock")
|
||||||
|
|
||||||
|
// Date formatting function.
|
||||||
|
lua.pushScalaFunction(lua => {
|
||||||
|
val format =
|
||||||
|
if (lua.getTop > 0 && lua.isString(1)) lua.toString(1)
|
||||||
|
else "%d/%m/%y %H:%M:%S"
|
||||||
|
val time =
|
||||||
|
if (lua.getTop > 1 && lua.isNumber(2)) lua.toNumber(2) * 1000 / 60 / 60
|
||||||
|
else worldTime + 6000
|
||||||
|
|
||||||
|
val dt = GameTimeFormatter.parse(time)
|
||||||
|
def fmt(format: String) {
|
||||||
|
if (format == "*t") {
|
||||||
|
lua.newTable(0, 8)
|
||||||
|
lua.pushInteger(dt.year)
|
||||||
|
lua.setField(-2, "year")
|
||||||
|
lua.pushInteger(dt.month)
|
||||||
|
lua.setField(-2, "month")
|
||||||
|
lua.pushInteger(dt.day)
|
||||||
|
lua.setField(-2, "day")
|
||||||
|
lua.pushInteger(dt.hour)
|
||||||
|
lua.setField(-2, "hour")
|
||||||
|
lua.pushInteger(dt.minute)
|
||||||
|
lua.setField(-2, "min")
|
||||||
|
lua.pushInteger(dt.second)
|
||||||
|
lua.setField(-2, "sec")
|
||||||
|
lua.pushInteger(dt.weekDay)
|
||||||
|
lua.setField(-2, "wday")
|
||||||
|
lua.pushInteger(dt.yearDay)
|
||||||
|
lua.setField(-2, "yday")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lua.pushString(GameTimeFormatter.format(format, dt))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just ignore the allowed leading '!', Minecraft has no time zones...
|
||||||
|
if (format.startsWith("!"))
|
||||||
|
fmt(format.substring(1))
|
||||||
|
else
|
||||||
|
fmt(format)
|
||||||
|
1
|
||||||
|
})
|
||||||
|
lua.setField(-2, "date")
|
||||||
|
|
||||||
// Return ingame time for os.time().
|
// Return ingame time for os.time().
|
||||||
lua.pushScalaFunction(lua => {
|
lua.pushScalaFunction(lua => {
|
||||||
// Game time is in ticks, so that each day has 24000 ticks, meaning
|
// Game time is in ticks, so that each day has 24000 ticks, meaning
|
||||||
// one hour is game time divided by one thousand. Also, Minecraft
|
// one hour is game time divided by one thousand. Also, Minecraft
|
||||||
// starts days at 6 o'clock, so we add those six hours. Thus:
|
// starts days at 6 o'clock, so we add those six hours. Thus:
|
||||||
// timestamp = (time + 6000) / 1000[h] * 60[m] * 60[s] * 1000[ms]
|
// timestamp = (time + 6000) * 60[kh] * 60[km] / 1000[s]
|
||||||
lua.pushNumber((worldTime + 6000) * 60 * 60)
|
lua.pushNumber((worldTime + 6000) * 60 * 60 / 1000)
|
||||||
1
|
1
|
||||||
})
|
})
|
||||||
lua.setField(-2, "time")
|
lua.setField(-2, "time")
|
||||||
|
@ -33,7 +33,7 @@ class RedstoneCard extends ManagedComponent {
|
|||||||
@LuaCallback("setOutput")
|
@LuaCallback("setOutput")
|
||||||
def setOutput(context: Context, args: Arguments): Array[AnyRef] = {
|
def setOutput(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
val side = checkSide(args, 0)
|
val side = checkSide(args, 0)
|
||||||
val value = args.checkInteger(1) max 0 min 15
|
val value = args.checkInteger(1) max 0 min 255
|
||||||
node.network.node(context.address).host match {
|
node.network.node(context.address).host match {
|
||||||
case redstone: Redstone =>
|
case redstone: Redstone =>
|
||||||
redstone.output(ForgeDirection.getOrientation(side), value.toShort)
|
redstone.output(ForgeDirection.getOrientation(side), value.toShort)
|
||||||
|
100
li/cil/oc/util/GameTimeFormatter.scala
Normal file
100
li/cil/oc/util/GameTimeFormatter.scala
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package li.cil.oc.util
|
||||||
|
|
||||||
|
import scala.collection.mutable
|
||||||
|
|
||||||
|
object GameTimeFormatter {
|
||||||
|
// Locale? What locale? Seriously though, since this would depend on the
|
||||||
|
// server's locale I think it makes more sense to keep it English always.
|
||||||
|
private val weekDays = Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
|
||||||
|
private val shortWeekDays = Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")
|
||||||
|
private val months = Array("January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December")
|
||||||
|
private val shortMonths = Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
|
||||||
|
private val amPm = Array("AM", "PM")
|
||||||
|
|
||||||
|
class DateTime(val year: Int, val month: Int, val day: Int,
|
||||||
|
val weekDay: Int, val yearDay: Int,
|
||||||
|
val hour: Int, val minute: Int, val second: Int)
|
||||||
|
|
||||||
|
// See http://www.cplusplus.com/reference/ctime/strftime/
|
||||||
|
private val specifiers: Map[Char, (DateTime) => String] = Map(
|
||||||
|
'a' -> (t => shortWeekDays(t.weekDay)),
|
||||||
|
'A' -> (t => weekDays(t.weekDay)),
|
||||||
|
'b' -> (t => shortMonths(t.month)),
|
||||||
|
'B' -> (t => months(t.month)),
|
||||||
|
'c' -> (t => format("%a %b %d %H:%M:%S %Y", t)),
|
||||||
|
'C' -> (t => "%02d".format(t.year / 100)),
|
||||||
|
'd' -> (t => "%02d".format(t.day + 1)),
|
||||||
|
'D' -> (t => format("%m/%d/%y", t)),
|
||||||
|
'e' -> (t => "% 2d".format(t.day + 1)),
|
||||||
|
'F' -> (t => format("%Y-%m-%d", t)),
|
||||||
|
//'g' -> (t => ""),
|
||||||
|
//'G' -> (t => ""),
|
||||||
|
'h' -> (t => format("%b", t)),
|
||||||
|
'H' -> (t => "%02d".format(t.hour)),
|
||||||
|
'I' -> (t => "%02d".format(t.hour % 12 + 1)),
|
||||||
|
'j' -> (t => "%03d".format(t.yearDay)),
|
||||||
|
'm' -> (t => "%02d".format(t.month + 1)),
|
||||||
|
'M' -> (t => "%02d".format(t.minute)),
|
||||||
|
'n' -> (t => "\n"),
|
||||||
|
'p' -> (t => amPm(if (t.hour < 12) 0 else 1)),
|
||||||
|
'r' -> (t => format("%I:%M:%S %p", t)),
|
||||||
|
'R' -> (t => format("%H:%M", t)),
|
||||||
|
'S' -> (t => "%02d".format(t.second)),
|
||||||
|
't' -> (t => "\t"),
|
||||||
|
'T' -> (t => format("%H:%M:%S", t)),
|
||||||
|
'u' -> (t => ""),
|
||||||
|
//'U' -> (t => ""),
|
||||||
|
//'V' -> (t => ""),
|
||||||
|
'w' -> (t => "%d".format(t.weekDay)),
|
||||||
|
//'W' -> (t => ""),
|
||||||
|
'x' -> (t => format("%D", t)),
|
||||||
|
'X' -> (t => format("%T", t)),
|
||||||
|
'y' -> (t => "%02d".format(t.year % 100)),
|
||||||
|
'Y' -> (t => "%04d".format(t.year)),
|
||||||
|
//'z' -> (t => ""),
|
||||||
|
//'Z' -> (t => ""),
|
||||||
|
'%' -> (t => "%")
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
day = yearDay
|
||||||
|
val monthLengths =
|
||||||
|
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
|
||||||
|
Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||||
|
else
|
||||||
|
Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||||
|
var month = 0
|
||||||
|
while (day > monthLengths(month)) {
|
||||||
|
day = day - monthLengths(month)
|
||||||
|
month = month + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var seconds = ((time % 24000) * 60 * 60 / 1000).toInt
|
||||||
|
var minutes = seconds / 60
|
||||||
|
seconds = seconds % 60
|
||||||
|
val hours = (minutes / 60) % 24
|
||||||
|
minutes = minutes % 60
|
||||||
|
|
||||||
|
new DateTime(year, month, day.toInt, weekDay, yearDay, hours, minutes, seconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
def format(format: String, time: DateTime) = {
|
||||||
|
val result = new mutable.StringBuilder()
|
||||||
|
val iterator = format.iterator
|
||||||
|
while (iterator.hasNext) {
|
||||||
|
iterator.next() match {
|
||||||
|
case '%' if iterator.hasNext =>
|
||||||
|
specifiers.get(iterator.next()) match {
|
||||||
|
case Some(specifier) => result.append(specifier(time))
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
case c => result.append(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.toString()
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,6 @@ import com.naef.jnlua.{LuaState, NativeSupport}
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.nio.channels.Channels
|
import java.nio.channels.Channels
|
||||||
import java.util.{Locale, Calendar}
|
|
||||||
import li.cil.oc.server.component.Computer
|
import li.cil.oc.server.component.Computer
|
||||||
import li.cil.oc.util.ExtendedLuaState._
|
import li.cil.oc.util.ExtendedLuaState._
|
||||||
import li.cil.oc.{OpenComputers, Config}
|
import li.cil.oc.{OpenComputers, Config}
|
||||||
@ -154,15 +153,6 @@ object LuaStateFactory {
|
|||||||
})
|
})
|
||||||
state.setField(-2, "realTime")
|
state.setField(-2, "realTime")
|
||||||
|
|
||||||
// Date-time formatting using Java's formatting capabilities.
|
|
||||||
state.pushScalaFunction(lua => {
|
|
||||||
val calendar = Calendar.getInstance(Locale.ENGLISH)
|
|
||||||
calendar.setTimeInMillis(lua.checkInteger(1))
|
|
||||||
// TODO
|
|
||||||
1
|
|
||||||
})
|
|
||||||
state.setField(-2, "date")
|
|
||||||
|
|
||||||
// Pop the os table.
|
// Pop the os table.
|
||||||
state.pop(1)
|
state.pop(1)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user