1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-25 22:53:22 +00:00
CC-Tweaked/src/main/java/dan200/computercraft/core/apis/OSAPI.java
Daniel Ratcliffe e85cdacbc5 ComputerCraft 1.79 initial upload
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.
2017-05-01 14:32:39 +01:00

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();
}
}