-
-
Save tylerjwatson/779dc4587d52d2d99b89 to your computer and use it in GitHub Desktop.
Jist2 JS Environment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
{ | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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