mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-06-25 22:53:22 +00:00
![Daniel Ratcliffe](/assets/img/avatar_default.png)
Added the complete source code to ComputerCraft 1.79 for Minecraft 1.8.9, plus newly written README and LICENSE files for the open source release.
371 lines
8.4 KiB
Java
371 lines
8.4 KiB
Java
/**
|
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
|
|
* Send enquiries to dratcliffe@gmail.com
|
|
*/
|
|
|
|
package dan200.computercraft.core.apis;
|
|
|
|
import dan200.computercraft.api.lua.ILuaContext;
|
|
import dan200.computercraft.api.lua.LuaException;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.Map;
|
|
|
|
public class OSAPI implements ILuaAPI
|
|
{
|
|
private IAPIEnvironment m_apiEnvironment;
|
|
|
|
private final Map<Integer, Timer> m_timers;
|
|
private final Map<Integer, Alarm> m_alarms;
|
|
private int m_clock;
|
|
private double m_time;
|
|
private int m_day;
|
|
|
|
private int m_nextTimerToken;
|
|
private int m_nextAlarmToken;
|
|
|
|
private static class Timer
|
|
{
|
|
public int m_ticksLeft;
|
|
|
|
public Timer( int ticksLeft )
|
|
{
|
|
m_ticksLeft = ticksLeft;
|
|
}
|
|
}
|
|
|
|
private class Alarm implements Comparable<Alarm>
|
|
{
|
|
public final double m_time;
|
|
public final int m_day;
|
|
|
|
public Alarm( double time, int day )
|
|
{
|
|
m_time = time;
|
|
m_day = day;
|
|
}
|
|
|
|
@Override
|
|
public int compareTo( Alarm o )
|
|
{
|
|
double t = (double)m_day * 24.0 + m_time;
|
|
double ot = (double)m_day * 24.0 + m_time;
|
|
if( t < ot ) {
|
|
return -1;
|
|
} else if( t > ot ) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
public OSAPI( IAPIEnvironment environment )
|
|
{
|
|
m_apiEnvironment = environment;
|
|
m_nextTimerToken = 0;
|
|
m_nextAlarmToken = 0;
|
|
m_timers = new HashMap<Integer, Timer>();
|
|
m_alarms = new HashMap<Integer, Alarm>();
|
|
}
|
|
|
|
// ILuaAPI implementation
|
|
|
|
@Override
|
|
public String[] getNames()
|
|
{
|
|
return new String[] {
|
|
"os"
|
|
};
|
|
}
|
|
|
|
@Override
|
|
public void startup()
|
|
{
|
|
m_time = m_apiEnvironment.getComputerEnvironment().getTimeOfDay();
|
|
m_day = m_apiEnvironment.getComputerEnvironment().getDay();
|
|
m_clock = 0;
|
|
|
|
synchronized( m_timers )
|
|
{
|
|
m_timers.clear();
|
|
}
|
|
|
|
synchronized( m_alarms )
|
|
{
|
|
m_alarms.clear();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void advance( double dt )
|
|
{
|
|
synchronized( m_timers )
|
|
{
|
|
// Update the clock
|
|
m_clock++;
|
|
|
|
// Countdown all of our active timers
|
|
Iterator<Map.Entry<Integer, Timer>> it = m_timers.entrySet().iterator();
|
|
while( it.hasNext() )
|
|
{
|
|
Map.Entry<Integer, Timer> entry = it.next();
|
|
Timer timer = entry.getValue();
|
|
timer.m_ticksLeft = timer.m_ticksLeft - 1;
|
|
if( timer.m_ticksLeft <= 0 )
|
|
{
|
|
// Queue the "timer" event
|
|
queueLuaEvent( "timer", new Object[] { entry.getKey() } );
|
|
it.remove();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Wait for all of our alarms
|
|
synchronized( m_alarms )
|
|
{
|
|
double previousTime = m_time;
|
|
int previousDay = m_day;
|
|
double time = m_apiEnvironment.getComputerEnvironment().getTimeOfDay();
|
|
int day = m_apiEnvironment.getComputerEnvironment().getDay();
|
|
|
|
if( time > previousTime || day > previousDay )
|
|
{
|
|
double now = (double)m_day * 24.0 + m_time;
|
|
Iterator<Map.Entry<Integer, Alarm>> it = m_alarms.entrySet().iterator();
|
|
while( it.hasNext() )
|
|
{
|
|
Map.Entry<Integer, Alarm> entry = it.next();
|
|
Alarm alarm = entry.getValue();
|
|
double t = (double)alarm.m_day * 24.0 + alarm.m_time;
|
|
if( now >= t )
|
|
{
|
|
queueLuaEvent( "alarm", new Object[]{ entry.getKey() } );
|
|
it.remove();
|
|
}
|
|
}
|
|
}
|
|
|
|
m_time = time;
|
|
m_day = day;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void shutdown( )
|
|
{
|
|
synchronized( m_timers )
|
|
{
|
|
m_timers.clear();
|
|
}
|
|
|
|
synchronized( m_alarms )
|
|
{
|
|
m_alarms.clear();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String[] getMethodNames()
|
|
{
|
|
return new String[] {
|
|
"queueEvent",
|
|
"startTimer",
|
|
"setAlarm",
|
|
"shutdown",
|
|
"reboot",
|
|
"computerID",
|
|
"getComputerID",
|
|
"setComputerLabel",
|
|
"computerLabel",
|
|
"getComputerLabel",
|
|
"clock",
|
|
"time",
|
|
"day",
|
|
"cancelTimer",
|
|
"cancelAlarm",
|
|
};
|
|
}
|
|
|
|
@Override
|
|
public Object[] callMethod( ILuaContext context, int method, Object[] args ) throws LuaException
|
|
{
|
|
switch( method )
|
|
{
|
|
case 0:
|
|
{
|
|
// queueEvent
|
|
if( args.length == 0 || args[0] == null || !(args[0] instanceof String) )
|
|
{
|
|
throw new LuaException( "Expected string" );
|
|
}
|
|
queueLuaEvent( (String)args[0], trimArray( args, 1 ) );
|
|
return null;
|
|
}
|
|
case 1:
|
|
{
|
|
// startTimer
|
|
if( args.length < 1 || args[0] == null || !(args[0] instanceof Number) )
|
|
{
|
|
throw new LuaException( "Expected number" );
|
|
}
|
|
double timer = ((Number)args[0]).doubleValue();
|
|
synchronized( m_timers )
|
|
{
|
|
m_timers.put( m_nextTimerToken, new Timer( (int)Math.round( timer / 0.05 ) ) );
|
|
return new Object[] { m_nextTimerToken++ };
|
|
}
|
|
}
|
|
case 2:
|
|
{
|
|
// setAlarm
|
|
if( args.length < 1 || args[0] == null || !(args[0] instanceof Number) )
|
|
{
|
|
throw new LuaException( "Expected number" );
|
|
}
|
|
double time = ((Number)args[0]).doubleValue();
|
|
if( time < 0.0 || time >= 24.0 )
|
|
{
|
|
throw new LuaException( "Number out of range" );
|
|
}
|
|
synchronized( m_alarms )
|
|
{
|
|
int day = (time > m_time) ? m_day : (m_day + 1);
|
|
m_alarms.put( m_nextAlarmToken, new Alarm( time, day ) );
|
|
return new Object[] { m_nextAlarmToken++ };
|
|
}
|
|
}
|
|
case 3:
|
|
{
|
|
// shutdown
|
|
m_apiEnvironment.shutdown();
|
|
return null;
|
|
}
|
|
case 4:
|
|
{
|
|
// reboot
|
|
m_apiEnvironment.reboot();
|
|
return null;
|
|
}
|
|
case 5:
|
|
case 6:
|
|
{
|
|
// computerID/getComputerID
|
|
return new Object[] { getComputerID() };
|
|
}
|
|
case 7:
|
|
{
|
|
// setComputerLabel
|
|
String label = null;
|
|
if( args.length > 0 && args[0] != null )
|
|
{
|
|
if(!(args[0] instanceof String))
|
|
{
|
|
throw new LuaException( "Expected string or nil" );
|
|
}
|
|
label = (String)args[0];
|
|
if( label.length() > 32 )
|
|
{
|
|
label = label.substring( 0, 32 );
|
|
}
|
|
}
|
|
m_apiEnvironment.setLabel( label );
|
|
return null;
|
|
}
|
|
case 8:
|
|
case 9:
|
|
{
|
|
// computerLabel/getComputerLabel
|
|
String label = m_apiEnvironment.getLabel();
|
|
if( label != null )
|
|
{
|
|
return new Object[] { label };
|
|
}
|
|
return null;
|
|
}
|
|
case 10:
|
|
{
|
|
// clock
|
|
synchronized( m_timers )
|
|
{
|
|
return new Object[] { (double)m_clock * 0.05 };
|
|
}
|
|
}
|
|
case 11:
|
|
{
|
|
// m_time
|
|
synchronized( m_alarms )
|
|
{
|
|
return new Object[] { m_time };
|
|
}
|
|
}
|
|
case 12:
|
|
{
|
|
// day
|
|
synchronized( m_alarms )
|
|
{
|
|
return new Object[] { m_day };
|
|
}
|
|
}
|
|
case 13:
|
|
{
|
|
// cancelTimer
|
|
if( args.length < 1 || args[0] == null || !(args[0] instanceof Number) )
|
|
{
|
|
throw new LuaException( "Expected number" );
|
|
}
|
|
int token = ((Number)args[0]).intValue();
|
|
synchronized( m_timers )
|
|
{
|
|
if( m_timers.containsKey( token ) )
|
|
{
|
|
m_timers.remove( token );
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
case 14:
|
|
{
|
|
// cancelAlarm
|
|
if( args.length < 1 || args[0] == null || !(args[0] instanceof Number) )
|
|
{
|
|
throw new LuaException( "Expected number" );
|
|
}
|
|
int token = ((Number)args[0]).intValue();
|
|
synchronized( m_alarms )
|
|
{
|
|
if( m_alarms.containsKey( token ) )
|
|
{
|
|
m_alarms.remove( token );
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
default:
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Private methods
|
|
|
|
private void queueLuaEvent( String event, Object[] args )
|
|
{
|
|
m_apiEnvironment.queueEvent( event, args );
|
|
}
|
|
|
|
private Object[] trimArray( Object[] array, int skip )
|
|
{
|
|
return Arrays.copyOfRange( array, skip, array.length );
|
|
}
|
|
|
|
private int getComputerID()
|
|
{
|
|
return m_apiEnvironment.getComputerID();
|
|
}
|
|
}
|