Skip to content

Instantly share code, notes, and snippets.

@tylerjwatson
Created May 11, 2015 05:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tylerjwatson/779dc4587d52d2d99b89 to your computer and use it in GitHub Desktop.
Save tylerjwatson/779dc4587d52d2d99b89 to your computer and use it in GitHub Desktop.
Jist2 JS Environment
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using V8.Net;
namespace Jist2.Libraries {
[ScriptObject("Sealed_Object", ScriptMemberSecurity.Permanent)]
public class JistJSLibrary : IV8NativeObject {
protected Random rnd = new Random();
/// <summary>
/// Runs a javascript function pointed to by `func` after the period
/// defined by DelayMS.
/// </summary>
public void RunAfter(int DelayMS, InternalHandle func)
{
/*
* Because the Task mechanism will halt this method when it
* encounters an awaiter and the GC will clean up the function
* before the task returns to ContinueWith, it must be locally
* cloned so it survives GC.
*/
InternalHandle _func = func.Clone();
if (_func.IsFunction == false) {
throw new Exception("Provided callback must be a function.");
}
Task.Delay(DelayMS).ContinueWith((task) => {
_func.StaticCall();
});
}
/// <summary>
/// Returns a random number between the from and to values
/// specified.
/// </summary>
public int Random(int from, int to)
{
lock (rnd) {
return rnd.Next(from, to);
}
}
public void Initialize(V8NativeObject owner, bool isConstructCall, params InternalHandle[] args)
{
}
public void Dispose()
{
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using TShockAPI;
using V8.Net;
using Jist2.Extensions;
namespace Jist2.Libraries {
public class JistTaskLibrary : IDisposable {
protected Timer oneSecondTimer;
protected Timer highPrecisionTimer;
private List<RecurringFunction> recurList;
private List<RunAt> runAtList;
private List<System.Threading.CancellationTokenSource> runAfterList;
/*
* Lock on this to prevent enumerator errors writing to
* an enumerated object.
*/
private readonly object __recurringLock = new object();
private readonly object __runAtLock = new object();
public JistTaskLibrary()
{
this.highPrecisionTimer = new Timer(100);
this.oneSecondTimer = new Timer(1000);
this.oneSecondTimer.Elapsed += oneSecondTimer_Elapsed;
this.highPrecisionTimer.Elapsed += highPrecisionTimer_Elapsed;
this.oneSecondTimer.Start();
this.recurList = new List<RecurringFunction>();
this.runAtList = new List<RunAt>();
this.runAfterList = new List<System.Threading.CancellationTokenSource>();
this.highPrecisionTimer.Start();
}
public string[] List()
{
return recurList.OrderByDescending(i => i.NextRunTime).Select(i => i.ToString()).ToArray();
}
public System.Threading.CancellationTokenSource[] RunAfters
{
get
{
return runAfterList.ToArray();
}
}
private void highPrecisionTimer_Elapsed(object sender, ElapsedEventArgs e)
{
double time = 0;
System.Threading.Interlocked.Exchange(ref time, Terraria.Main.time);
if (time > 0 && time < 200) {
for (int i = 0; i < runAtList.Count; i++) {
RunAt at;
lock (__runAtLock) {
at = runAtList.ElementAtOrDefault(i);
if (at == null) {
continue;
}
at.ExecutedInIteration = false;
}
}
// TShockAPI.Log.ConsoleInfo("* Execution iterators reset.");
}
}
protected void oneSecondTimer_Elapsed(object sender, ElapsedEventArgs e)
{
for (int i = 0; i < recurList.Count; i++) {
RecurringFunction func;
lock (__recurringLock) {
func = recurList.ElementAtOrDefault(i);
}
if (func == null) {
continue;
}
try {
func.ExecuteAndRecur();
} catch (Exception ex) {
TShock.Log.ConsoleError("jist recurring: Error on recurring rule: " + ex.Message);
}
}
for (int i = 0; i < runAtList.Count; i++) {
RunAt at;
lock (__runAtLock) {
at = runAtList.ElementAtOrDefault(i);
}
if (at == null
|| Jist2Plugin.Environment == null
|| Terraria.Main.time <= at.AtTime
|| at.ExecutedInIteration == true) {
continue;
}
try {
InternalHandle h = Jist2Plugin.Environment.Engine.CreateValue(at);
at.Func.StaticCall(h);
} catch (Exception ex) {
TShock.Log.ConsoleError("jist recurring: Error on recurring rule: " + ex.Message);
} finally {
at.ExecutedInIteration = true;
}
}
}
/// <summary>
/// Runs a javascript function after waiting. Similar to setTimeout()
/// </summary>
//[JavascriptFunction("run_after", "jist_run_after")]
public void RunAfterAsync(int AfterMilliseconds, InternalHandle Func, params object[] args)
{
System.Threading.CancellationTokenSource source;
InternalHandle _func = InternalHandle.Empty;
_func.Set(Func);
lock (runAfterList) {
source = new System.Threading.CancellationTokenSource();
runAfterList.Add(source);
}
Action runAfterFunc = async () => {
try {
await Task.Delay(AfterMilliseconds, source.Token);
} catch (TaskCanceledException) {
return;
}
if (source.Token.IsCancellationRequested == true) {
return;
}
try {
//args.ToInternalHandleArray(Jist2Plugin.Environment.Engine)
InternalHandle value = _func.StaticCall();
value.Dispose();
} catch (TaskCanceledException) {
} finally {
if (source.Token.IsCancellationRequested == false) {
lock (runAfterList) {
runAfterList.Remove(source);
}
}
_func.Dispose();
}
};
Task.Factory.StartNew(runAfterFunc, source.Token);
}
/// <summary>
/// Adds a javascript function to be run every hours minutes and seconds specified.
/// </summary>
//[JavascriptFunction("run_at", "jist_run_at")]
public void AddAt(int Hours, int Minutes, InternalHandle Func)
{
/*
* Note: The constructor of the RunAt handles clone of the
* internal handle. No need to increment the ref counter
* here.
*/
lock (__runAtLock) {
runAtList.Add(new RunAt(Hours, Minutes, Func));
}
}
/// <summary>
/// Adds a javascript function to be run every hours minutes and seconds specified.
/// </summary>
//[JavascriptFunction("add_recurring", "jist_task_queue")]
public void AddRecurring(int Hours, int Minutes, int Seconds, InternalHandle Func)
{
return;
/*
* Note: The constructor of the RecurringFunction handles
* clone of the internal handle. No need to increment the
* ref counter here.
*/
lock (__recurringLock) {
recurList.Add(new RecurringFunction(Hours, Minutes, Seconds, Func));
}
}
internal void CancelRunAfters()
{
lock (runAfterList) {
foreach (var source in runAfterList) {
source.Cancel();
}
runAfterList.Clear();
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (disposing == true) {
lock (__recurringLock) {
this.recurList.Clear();
}
this.oneSecondTimer.Stop();
this.oneSecondTimer.Dispose();
this.highPrecisionTimer.Stop();
this.highPrecisionTimer.Dispose();
this.CancelRunAfters();
}
}
}
class RecurringFunction {
/// <summary>
/// Gets the Recurrence ID of this recurrence rule, so that it may
/// be removed at a later time
/// </summary>
public Guid RecurrenceID { get; private set; }
/// <summary>
/// Returns the total number of seconds between recurring intervals
/// </summary>
public int Seconds { get; private set; }
/// <summary>
/// Returns the Javascript function that this recurring rule should
/// execute.
/// </summary>
public ObjectHandle Function { get; private set; }
/// <summary>
/// Gets the next date and time that this rule is due to run at.
/// </summary>
public DateTime NextRunTime { get; private set; }
/// <summary>
/// Creates a JavaScript recurring function, with the specified
/// hours minutes and seconds which runs the supplied function.
/// </summary>
public RecurringFunction(int Hours, int Minutes, int Seconds, InternalHandle Func)
{
this.RecurrenceID = Guid.NewGuid();
this.Function = Func;
this.Seconds += Hours * 3600;
this.Seconds += Minutes * 60;
this.Seconds += Seconds;
this.NextRunTime = DateTime.UtcNow.Add(TimeSpan.FromSeconds(this.Seconds));
//Console.WriteLine("jist recurring: Recurring Func {0}: next run time {1}", this.RecurrenceID, this.NextRunTime);
}
/// <summary>
/// Executes the function in this recurring rule if it's
/// time to, and updates the next run time to the next
/// recurance.
/// </summary>
public void ExecuteAndRecur()
{
if (DateTime.UtcNow < this.NextRunTime
|| Jist2Plugin.Environment == null) {
return;
}
try {
InternalHandle thisHandle = Jist2Plugin.Environment.Engine.CreateValue(this);
Function.Call(thisHandle);
thisHandle.Dispose();
} catch (Exception ex) {
TShockAPI.TShock.Log.ConsoleError("Error occured on a recurring task function: " + ex.Message);
} finally {
Recur();
}
}
/// <summary>
/// Causes this recurring function to update it's next
/// run time to the next interval it was created with.
/// </summary>
protected void Recur()
{
this.NextRunTime = DateTime.UtcNow.Add(TimeSpan.FromSeconds(this.Seconds));
}
public override string ToString()
{
TimeSpan nextRunTime = this.NextRunTime.Subtract(DateTime.UtcNow);
return string.Format("Task {0}: {1} secs, next in {2}", this.RecurrenceID, this.Seconds, nextRunTime.ToString(@"hh\:mm\:ss"));
}
}
/// <summary>
/// Holds a javascript function to be run every time
/// the game hits a certain time in the terraria world.
/// </summary>
class RunAt {
public Guid RunAtID { get; set; }
public double AtTime { get; set; }
public InternalHandle Func { get; set; }
public bool Enabled { get; set; }
public bool ExecutedInIteration { get; set; }
public static double GetRawTime(int hours, int minutes)
{
decimal time = hours + minutes / 60.0m;
time -= 4.50m;
if (time < 0.00m)
time += 24.00m;
if (time >= 15.00m) {
return (double)((time - 15.00m) * 3600.0m);
} else {
return (double)(time * 3600.0m);
}
}
public RunAt(double AtTime, InternalHandle func)
{
this.RunAtID = new Guid();
this.AtTime = AtTime;
this.Func = func.Clone();
this.Enabled = true;
}
public RunAt(int hours, int minutes, InternalHandle func)
{
this.RunAtID = new Guid();
this.AtTime = GetRawTime(hours, minutes);
this.Func = func.Clone();
this.Enabled = true;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using TShockAPI.DB;
using TShockAPI;
using Jist2.Extensions;
using V8.Net;
namespace Jist2.Libraries {
/// <summary>
/// Tshock standard library.
///
/// Provides scripting API into the various mechanisms of TShock.
/// </summary>
public partial class JistTSLibrary {
protected readonly Regex htmlColourRegex = new Regex(@"#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])", RegexOptions.IgnoreCase);
protected readonly Regex htmlColourRegexShort = new Regex(@"#([0-9a-f])([0-9a-f])([0-9a-f])", RegexOptions.IgnoreCase);
protected readonly Regex rgbColourRegex = new Regex(@"((\d*),(\d*),(\d*))", RegexOptions.IgnoreCase);
/// <summary>
/// Gets a TShock region by its name.
/// </summary>
//[JavascriptFunction("tshock_get_region")]
public TShockAPI.DB.Region GetRegion(object region)
{
TShockAPI.DB.Region reg = null;
if (region == null) {
return null;
}
if (region is TShockAPI.DB.Region) {
return region as TShockAPI.DB.Region;
}
if (region is string) {
try {
return TShockAPI.TShock.Regions.GetRegionByName(region as string);
} catch {
return null;
}
}
return null;
}
//[JavascriptFunction("tshock_player_regions")]
public Region[] PlayerInRegions(object PlayerRef)
{
TShockAPI.TSPlayer player;
List<Region> regionList = new List<Region>();
if ((player = GetPlayer(PlayerRef)) == null) {
return null;
}
foreach (Region region in TShockAPI.TShock.Regions.ListAllRegions(Terraria.Main.worldID.ToString())) {
if (IsPlayerInRegion(player, region) == false) {
continue;
}
regionList.Add(region);
}
return regionList.Count == 0 ? null : regionList.ToArray();
}
//[JavascriptFunction("tshock_player_in_region")]
public bool IsPlayerInRegion(object playerRef, object regionRef)
{
TShockAPI.TSPlayer player;
Region region;
if (playerRef == null
|| regionRef == null
|| (player = GetPlayer(playerRef)) == null
|| (region = GetRegion(regionRef)) == null) {
return false;
}
return region.InArea(player.TileX, player.TileY);
}
/// <summary>
/// JS function: tshock_get_player(player) : TSPlayer
///
/// Retrieves a TShock player for use in scripts.
/// </summary>
//[JavascriptFunction("get_player", "tshock_get_player")]
public TShockAPI.TSPlayer GetPlayer(object PlayerRef)
{
TShockAPI.TSPlayer player;
if (PlayerRef == null) {
return null;
}
if (PlayerRef is TShockAPI.TSPlayer) {
return PlayerRef as TShockAPI.TSPlayer;
}
if (PlayerRef is string) {
string playerString = PlayerRef as string;
if (playerString.Equals("server", StringComparison.CurrentCultureIgnoreCase)) {
return TShockAPI.TSPlayer.Server;
}
if ((player = TShockAPI.TShock.Players.FirstOrDefault(i => i != null && i.Name == playerString.ToString())) != null) {
return player;
}
return TShockAPI.TShock.Players.FirstOrDefault(i => i != null && i.UserAccountName == PlayerRef.ToString());
}
return null;
}
public TShockAPI.TSPlayer GetServerPlayer()
{
return TSPlayer.Server;
}
/// <summary>
/// JS function: tshock_has_permission(player, permission) : boolean
///
/// Returns if a specified player has a specified permission based
/// on their current TShock group.
/// </summary>
//[JavascriptFunction("tshock_has_permission")]
public bool PlayerHasPermission(object PlayerRef, object GroupName)
{
TShockAPI.TSPlayer returnPlayer = null;
if ((returnPlayer = GetPlayer(PlayerRef)) == null || GroupName == null) {
return false;
}
return returnPlayer.Group.HasPermission(GroupName.ToString());
}
/// <summary>
/// JS function: tshock_group_exists(group) : boolean
///
/// Returns true if the TShock group exists in the TShock
/// database and is available for use.
/// </summary>
//[JavascriptFunction("group_exists", "tshock_group_exists")]
public bool TShockGroupExists(object GroupName)
{
return TShockAPI.TShock.Groups.Count(i => i.Name.Equals(GroupName.ToString(), StringComparison.CurrentCultureIgnoreCase)) > 0;
}
/// <summary>
/// JS function: tshock_group(groupName) : Group
///
/// Returns a TShock group object by it's name, or
/// null if the group does not exist or there is a
/// database error.
/// </summary>
//[JavascriptFunction("tshock_group")]
public TShockAPI.Group TShockGroup(object Group)
{
TShockAPI.Group g = null;
if (Group == null) {
return null;
}
g = TShockAPI.TShock.Groups.FirstOrDefault(i => i.Name.Equals(Group.ToString(), StringComparison.CurrentCultureIgnoreCase));
return g;
}
/// <summary>
/// Javsacript function: tshock_exec(player, command) : boolean
///
/// Impersonates a player and executes the specified command
/// as if it was comming from them, and returns true if the
/// invoke of the command was successful, false if there was an
/// error or an exception.
///
/// There are no permission checks on this method, so the command
/// will unconditionally be executed, think of this as a super-
/// admin mechanism.
/// </summary>
//[JavascriptFunction("execute_command", "tshock_exec")]
public void ExecuteCommand(object Player, object Command)
{
TShockAPI.TSPlayer p = null;
string commandToExecute = "";
if ((p = GetPlayer(Player)) == null) {
//return false;
return;
}
try {
if (Command is List<string>) {
List<string> cmdList = Command as List<string>;
foreach (var param in cmdList.Skip(1)) {
commandToExecute += " " + param;
}
} else if (Command is string) {
commandToExecute = Command.ToString();
}
if (string.IsNullOrEmpty((commandToExecute = commandToExecute.Trim())) == true) {
return;
//return false;
}
p.PermissionlessInvoke(commandToExecute);
//return true;
} catch (Exception) {
//return false;
}
}
/// <summary>
/// Javsacript function: tshock_exec_silent(player, command) : boolean
///
/// Impersonates a player and executes the specified command
/// as if it was comming from them, and returns true if the
/// invoke of the command was successful, false if there was an
/// error or an exception.
///
/// There are no permission checks on this method, so the command
/// will unconditionally be executed, think of this as a super-
/// admin mechanism.
/// </summary>
//[JavascriptFunction("tshock_exec_silent")]
public bool ExecuteCommandSilent(object Player, object Command)
{
TShockAPI.TSPlayer p = null;
string commandToExecute = "";
if ((p = GetPlayer(Player)) == null) {
return false;
}
try {
if (Command is List<string>) {
List<string> cmdList = Command as List<string>;
foreach (var param in cmdList.Skip(1)) {
commandToExecute += " " + param;
}
} else if (Command is string) {
commandToExecute = Command.ToString();
}
if (string.IsNullOrEmpty((commandToExecute = commandToExecute.Trim())) == true) {
return false;
}
p.PermissionlessInvoke(commandToExecute, true);
return true;
} catch (Exception) {
return false;
}
}
/// <summary>
/// Javascript function: tshock_change_group(player, group) : boolean
///
/// Changes the provided player's group to the new group specified, and
/// returns true if the operation succeeded, or false if there was an
/// error.
/// </summary>
//[JavascriptFunction("change_group", "tshock_change_group")]
public bool ChangeGroup(object Player, object Group)
{
TShockAPI.TSPlayer p = null;
TShockAPI.DB.User u = new TShockAPI.DB.User();
string g = "";
if ((p = GetPlayer(Player)) == null) {
return false;
}
if (Group is string) {
g = Group as string;
} else if (Group is TShockAPI.Group) {
g = (Group as TShockAPI.Group).Name;
}
if (string.IsNullOrEmpty(g) == true) {
return false;
}
u.Name = p.UserAccountName;
TShockAPI.TShock.Users.SetUserGroup(u, g);
return true;
}
/// <summary>
/// Javscript function: tshock_msg(player, msg)
///
/// Sends a message to a specified player.
/// </summary>
//[JavascriptFunction("msg", "tshock_msg")]
public void Message(object PlayerRef, object Message)
{
TShockAPI.TSPlayer player;
string msg = null;
if ((player = GetPlayer(PlayerRef)) == null) {
return;
}
msg = Message.ToString();
if (string.IsNullOrEmpty(msg) == true) {
return;
}
player.SendInfoMessage("{0}", Message);
}
/// <summary>
/// Javascript function: tshock_msg_colour(colour, player, msg)
///
/// Sends a message to a specified player with the specified colour.
///
/// Colours may be in R,G,B or #html format.
/// </summary>
//[JavascriptFunction("msg_colour", "tshock_msg_colour")]
public void MessageWithColour(object Colour, object Player, object Message)
{
TShockAPI.TSPlayer ply = null;
string msg = Message.ToString();
Color c = ParseColour(Colour);
if ((ply = GetPlayer(Player)) == null
|| string.IsNullOrEmpty(msg) == true) {
return;
}
ply.SendMessage(string.Format("{0}", Message), c);
}
/// <summary>
/// Javascript function: tshock_broadcast_colour(colour, msg)
///
/// Broadcasts a message to all players in the server with the specified
/// colour.
/// </summary>
//[JavascriptFunction("broadcast_colour", "tshock_broadcast_colour")]
public void BroadcastWithColour(object Colour, object Message)
{
Color c = ParseColour(Colour);
if (Message != null) {
TShockAPI.TShock.Utils.Broadcast(Message.ToString(), c);
}
}
/// <summary>
/// Javascript function: tshock_broadcast(colour, msg)
///
/// Broadcasts a message top all players in the server.
/// </summary>
//[JavascriptFunction("broadcast", "tshock_broadcast")]
public void Broadcast(object Message)
{
BroadcastWithColour("#f00", Message);
}
/// <summary>
/// javascript function: tshock_server()
///
/// Returns an instance of the tshock server
/// player object.
/// </summary>
//[JavascriptFunction("tshock_server")]
public TShockAPI.TSPlayer ServerPlayer()
{
return TShockAPI.TSPlayer.Server;
}
//[JavascriptFunction("tshock_create_npc")]
public KeyValuePair<int, Terraria.NPC> CreateNPC(int x, int y, int type)
{
int index = Terraria.NPC.NewNPC(x, y, type);
Terraria.NPC npc;
if ((npc = Terraria.Main.npc.ElementAtOrDefault(index)) == null) {
return new KeyValuePair<int, Terraria.NPC>(-1, null);
}
//Terraria.Main.npc[index].SetDefaults(npc.type, -1f);
Terraria.Main.npc[index].SetDefaults(npc.name);
//Terraria.Main.npcLifeBytes[index] = 4;
return new KeyValuePair<int, Terraria.NPC>(index, npc);
}
//[JavascriptFunction("tshock_clear_tile_in_range")]
public Point ClearTileInRange(int x, int y, int rx, int ry)
{
Point p = new Point();
TShock.Utils.GetRandomClearTileWithInRange(x, y, rx, ry, out p.X, out p.Y);
return p;
}
//[JavascriptFunction("tshock_set_team")]
public void SetTeam(object player, int team)
{
TSPlayer p = GetPlayer(player);
p.SetTeam(team);
}
//[JavascriptFunction("tshock_warp_find")]
public Warp FindWarp(string warp)
{
return TShock.Warps.Find(warp);
}
//[JavascriptFunction("tshock_teleport_player")]
public void WarpPlayer(object player, float x, float y)
{
TSPlayer p = GetPlayer(player);
p.Teleport(x, y);
}
//[JavascriptFunction("tshock_warp_player")]
public void WarpPlayer(object player, Warp warp)
{
TSPlayer p = GetPlayer(player);
p.Teleport(warp.Position.X * 16, warp.Position.Y * 16);
}
/// <summary>
/// Parses colour from a range of input types and returns a strongly-
/// typed Color structure if the conversion succeeded, false otherwise.
/// </summary>
protected Color ParseColour(object colour)
{
Color returnColor = Color.Yellow;
if (colour != null) {
if (colour is Color) {
returnColor = (Color)colour;
} else if (colour is string) {
int r = 0, g = 0, b = 0;
string colourString = colour as string;
if (rgbColourRegex.IsMatch(colourString)) {
Match rgbMatch = rgbColourRegex.Match(colourString);
Int32.TryParse(rgbMatch.Groups[2].Value, out r);
Int32.TryParse(rgbMatch.Groups[3].Value, out g);
Int32.TryParse(rgbMatch.Groups[4].Value, out b);
} else if (htmlColourRegex.IsMatch(colourString)) {
Match htmlMatch = htmlColourRegex.Match(colourString);
r = Convert.ToInt32(htmlMatch.Groups[1].Value, 16);
g = Convert.ToInt32(htmlMatch.Groups[2].Value, 16);
b = Convert.ToInt32(htmlMatch.Groups[3].Value, 16);
} else if (htmlColourRegexShort.IsMatch(colourString)) {
Match htmlMatch = htmlColourRegexShort.Match(colourString);
r = Convert.ToInt32(htmlMatch.Groups[1].Value + htmlMatch.Groups[1].Value, 16);
g = Convert.ToInt32(htmlMatch.Groups[2].Value + htmlMatch.Groups[2].Value, 16);
b = Convert.ToInt32(htmlMatch.Groups[3].Value + htmlMatch.Groups[3].Value, 16);
}
returnColor = new Color(r, g, b);
}
}
return returnColor;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TShockAPI;
using V8.Net;
namespace Jist2 {
public class JSEnvironment : IDisposable {
protected V8Engine _engine;
protected Jist2Plugin _plugin;
public JSEnvironment(Jist2Plugin plugin)
{
this._engine = new V8Engine();
this._plugin = plugin;
this.JistLibrary = new Libraries.JistJSLibrary();
this.TaskLibrary = new Libraries.JistTaskLibrary();
this.TShockLibrary = new Libraries.JistTSLibrary();
BindEngine();
}
public V8Engine Engine
{
get
{
return _engine;
}
}
public Libraries.JistJSLibrary JistLibrary { get; protected set; }
public Libraries.JistTaskLibrary TaskLibrary { get; protected set; }
public Libraries.JistTSLibrary TShockLibrary { get; protected set; }
protected void BindEngine()
{
_engine.RegisterType(typeof(Object), "Object", true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(Type), "Type", true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(String), "String", true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(Boolean), "Boolean", true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(Array), "Array", true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(System.Collections.ArrayList), null, true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(char), null, true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(int), null, true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(Int16), null, true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(Int32), null, true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(Int64), null, true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(UInt16), null, true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(UInt32), null, true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(UInt64), null, true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(Byte), null, true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(Enumerable), null, true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(System.IO.File), null, true, ScriptMemberSecurity.Locked);
_engine.RegisterType(typeof(System.Drawing.Color), null, true, ScriptMemberSecurity.Locked);
//_engine.GlobalObject.SetProperty(typeof(Console), V8PropertyAttributes.Locked, null, true, ScriptMemberSecurity.Locked);
ObjectHandle hSystem = _engine.CreateObject();
_engine.DynamicGlobalObject.System = hSystem;
hSystem.SetProperty(typeof(Object)); // (Note: No optional parameters used, so this will simply lookup and apply the existing registered type details above.)
hSystem.SetProperty(typeof(String));
hSystem.SetProperty(typeof(Boolean));
hSystem.SetProperty(typeof(Array));
_engine.GlobalObject.SetProperty(typeof(Type));
_engine.GlobalObject.SetProperty(typeof(System.Collections.ArrayList));
_engine.GlobalObject.SetProperty(typeof(char));
_engine.GlobalObject.SetProperty(typeof(int));
_engine.GlobalObject.SetProperty(typeof(Int16));
_engine.GlobalObject.SetProperty(typeof(Byte));
_engine.GlobalObject.SetProperty(typeof(Int32));
_engine.GlobalObject.SetProperty(typeof(Int64));
_engine.GlobalObject.SetProperty(typeof(UInt16));
_engine.GlobalObject.SetProperty(typeof(UInt32));
_engine.GlobalObject.SetProperty(typeof(UInt64));
_engine.GlobalObject.SetProperty(typeof(Enumerable));
_engine.GlobalObject.SetProperty(typeof(Environment));
_engine.GlobalObject.SetProperty(typeof(System.IO.File));
_engine.GlobalObject.SetProperty(typeof(Libraries.JistJSLibrary));
//_engine.RegisterType<Terraria.Main>("main", true, ScriptMemberSecurity.Permanent);
//_engine.RegisterType<TShock>("tshock", true, ScriptMemberSecurity.Permanent);
//_engine.GlobalObject.SetProperty("terraria", _plugin._game, "__main", true, ScriptMemberSecurity.Permanent);
//_engine.GlobalObject.SetProperty(typeof(Terraria.Main), V8PropertyAttributes.Locked, "main", true, ScriptMemberSecurity.Permanent);
//_engine.GlobalObject.SetProperty(typeof(TShock), V8PropertyAttributes.Locked, "tshock", true, ScriptMemberSecurity.Permanent);
//_engine.GlobalObject.SetProperty(typeof(TSPlayer), V8PropertyAttributes.Locked, "tsplayer", true, ScriptMemberSecurity.Permanent);
//_engine.GlobalObject.SetProperty(typeof(System.Drawing.Color), V8PropertyAttributes.Locked, "color", true, ScriptMemberSecurity.Permanent);
_engine.GlobalObject.SetProperty("jist", JistLibrary, null, true, ScriptMemberSecurity.Locked);
_engine.GlobalObject.SetProperty("jist_tshock", TShockLibrary, "jist_tshock", true, ScriptMemberSecurity.Permanent);
_engine.GlobalObject.SetProperty("task", TaskLibrary, "task", true, ScriptMemberSecurity.Permanent);
_engine.Execute(ScriptResources._environment, "_environment", false);
}
public void CreateFunctions()
{
_engine.Execute(ScriptResources.jist1compat, "jist1shim", false);
}
~JSEnvironment()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public string ExecuteSnippet(string scriptName, string snippet)
{
Handle result = _engine.Execute(snippet, scriptName, false);
string r = result.AsString;
result.Dispose();
return r;
}
public Handle Execute(Handle h)
{
return _engine.Execute(h, true);
}
public void LoadScript(string scriptFilePath)
{
_engine.LoadScript(scriptFilePath, System.IO.Path.GetFileNameWithoutExtension(scriptFilePath), true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing) {
}
_engine.Dispose();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment