Unity3d - Putting player code safely in jail.



  • As requested, a short description: I am looking to allow players to write c# code to control things, using a selective subset of variables and methods that I can control, and make sure (or as sure as possible) they can't get out and fuck up the rest of the game.

    Example 1: Robot Wars - giving players the ability to define the behaviour of a robot with a few simple properties.
    Example 2: Programmable weapons - letting players script how the projectiles from their weapons work, e.g. enemy seeking, or clustering or something.

    Since I have been mulling over a few things following the "What is a good game idea that hasn't been made yet" I have been thinking about different possibilities for incorporating programming into games. Obviously since I am the worst I want to use Unity. Obviously, sine I am the worst of the worst, I dont understand the whole pipes thing people were talking about previously and am happy playing in my unity sandpit and designing things in the editor. If you wish to shoot me, join the queue forming in an orderly fashion over by the vending machines.

    I am just wondering about how I could go about achieving this. The obvious first approach is just taking some code from the user and putting it into an EVAL, which unityscript supports, but that seems like the worst of the worst of the worst of the worst, and although I am the worst of the worst, I want to stick to C#. Obviously a player who knows what engine the game is made in could royally fuck things up, and if I had any advertising stuff potentially dump out sensitive information and cause all kinds of havoc.

    So I am a little bit stumped about the best way to do this. I really don't want to define my own language, and I used LUA for my final year project at University, so would rather eat my own shit than use that (is there any difference?).

    So, ladies and gentlemen, after you establish I am TRWTF, would you be able to move past that revelation and posit any ideas for solving the problem? are there any solutions for getting custom C# code from the user, plugging it into a class or something, and then acting on it?



  • I might be blind, but I can't actually find what you're asking. But based on your topic title, and your short blub about eval, you want to allow for player provided code to be run directly by your game engine?

    Can you give a short one liner as the first sentence about exactly what you're trying to do?



  • Edited for clarity (hopefully)



  • Not really much better...

    But controlling a variable is as easy as

    var someitem = GUI.Textbox.text;

    scripting is a little harder, but I would recommend using javascript that unity supports since it has syntax validation (so you can verify it's valid and error if it's not) - and can be safely tucked away into a known object model (something like newtonsoft JSON to C# class)

    Then you can still control when, where, and how it's used, but you can allow for dynamic objects that can be fairly complex.



  • So I guess we are saying UnityScript eval = the best solution?

    in which case, does code in an eval have the same level of visibility of other code as the location where eval is called? (I dont want them being able to call GetGameObject type methods and start messing with shenanigans, or access any unity code for that matter, just some kind of model equivalent object(s) I give it to work with)



  • That's not what I said.

    I said take data from the user, ideally tokenify it using javascript/json, and convert it into a usable object.

    Don't eval random input. Ever.

    So if your goal is something like:

    class RandomShit()
    {
        Player CustomMobs;
        Player CustomRooms;
        Player CustomItems;
    }
    

    the JSON populates the data using the appropriate APIs then is parsed using the appropriate API to sanitize the results.



  • @Matches said:

    I said take data from the user, ideally tokenify it using javascript/json, and convert it into a usable object.

    pretty sure I am failing to explain myself well, I will give it another try when im not late for my train



  • Get a horse!

    One with a good sound system:


  • sockdevs

    Honestly I'd go with the custom language at this point in time. The odds are you don't need all the fun of C#, just enough to offer the player the tools for the job, right?

    (or am I TRWTF for suggesting it?)


  • :belt_onion:

    If it's for coding robots... I would half-jokingly suggest LOGO.


  • sockdevs

    @Onyx said:

    If it's for coding robots... I would half-jokingly suggest LOGO.

    Only the turtle subset, doesn't need the full power of teh awesomez LOGO.



  • Depends entirely on what you want to do. I'm working on a project that's a 2d game engine for others to build worlds on. (Basically remaking a game I used to play, and it's features. Mostly for learning purposes but also to bring it into today's technology)

    There are valid use cases depending on your project, but it's also something that's very easy to go too far over the top with and spend a lot of time creating things that will never be used.

    But let me repeat, as I feel it's VERY important: NEVER directly eval user code. Ever. Put it in a sandbox and only allow access through targeted APIs. Use discourse as an example of doing it wrong, and all the XSS fun we've had with it.


  • sockdevs

    Exactly my point .Having an abstract language does mean you avoid all the joys of XSS and yes it's quite possible to go overboard, but if you start suitably minimalist and play, you can begin to see what you're missing. At least that's been my experience, YMMV.


  • :belt_onion:

    @Arantor said:

    Only the turtle subset, doesn't need the full power of teh awesomez LOGO.

    Still pissed at myself for not copying the source... Found an honest to $DEITY topdown racer written in LOGO on a school computer once. AI and everything. No idea if someone there wrote it, or just got it from somewhere, but it blew my mind at the time.


  • Discourse touched me in a no-no place

    @Matches said:

    NEVER directly eval user code.

    That's true, unless you can prove that it's safe.

    Protip: if you think you can, either you're really good (it is possible! For limited subsets) or you're an idiot. The probabilities are strongly skewed to the latter, and as the long, sorry history of compilers shows, that's true even of people who should know better. (The hard bit is when dealing with features which are safe in isolation but unsafe in combination, and there are many ways that things can be abused; safety is a global property, not a local one, and that makes it a PITA to get right.)


  • :belt_onion:

    When even your IDE knows it's stupid...



  • [Obsolete("Do not use 'eval'")]
    Eval()

    ?


  • :belt_onion:

    @Matches said:

    [Obsolete("Do not use 'eval'")]

    That seems useful, if not abused that is. Had to look it up first though since I don't C#.



  • This was what I kinda expected tbh, and it's what I wanted to avoid.

    I literally wanted something like this:

    //in some class far away which has no references to external unity engine resources
    public void Shoot()
    {
    //USER CODE GOEZ HERE TO DEFINE SHOT BEHAVIOUR , PROJECTILE COUNT, OTHER FUNNY BUSINESS
    }
    

    I know from my compilers course that writing a language is the worst. Even with fancypants tools there is a lot of heavy lifting involved, and I know enough to know that I am not the best person to do it.

    I might have to just eat my own shit and use Lua.

    fuck.


  • sockdevs

    Here's the thing, do you need it to be Turing-complete? Do you actually need a full language?



  • I feel like I need it to be, I would ideally like for people to do a really wide range of things, including zany stuff like summoning one of the creatures in the game to defend them or stuff like that. My thinking was along the lines of "if the code fails or throws an exception, damage the player for their stupidity" but I knew it was going to be more complicated than that.

    I know im not going to do a good job of writing a parser, I had one written for me at university (in the shape of javacc I believe it was called, based on something else with some Ys in the name I think) and it did a remarkable job of tokenizing text, but we were never particularly taught the next step. Or maybe that was taught after I stopped attending lectures. Something like that.

    I wasn't the best of students.


  • Discourse touched me in a no-no place

    @Arantor said:

    Here's the thing, do you need it to be Turing-complete? Do you actually need a full language?

    If you want even simple data (numbers!) and a while loop (or recursive functions) you've already got Turing-complete. You deal with that sort of thing by running a monitor as well that kills anything that takes too long to answer.

    In practice though, it turns out to be more important to control access to the OS rather than to stop complicated mathematical computations…


  • :belt_onion:

    I don't know how much actual control you want to give to them but... Some kind of visual programming tool? Something like a simplified version of Kismet maybe?

    You could just map nodes to your own C# methods and call that. Gives the players freedom without being dangerous (as long as you don't eval their input).

    Unless using actual code is the point. In that case, disregard.



  • Use itonpython



  • I might end up doing something like that, It will probably have to wait until the new GUI set up is introduced in 4.6 though (I don't know if you have worked with the gui as it stands, but it's fucking terrible)



  • @algorythmics said:

    I might have to just eat my own shit and use Lua.

    FWIW, there is some information around on how to sandbox Lua code.

    E.g. this both limits the execution time for a Lua script, and what APIs the code can use.



    1. Your most straightforward options for evaling clr code appear to be: Mono.CSharp.Evaluator, Roslyn scripting api, or the Dynamic Language Runtime, in that order.
    2. You can run code within a different AppDomain to prevent access to data within your own AppDomain, but might not be able to reliably restrict user code (prevent it from accessing the internet/file system etc.) beyond that, since mono doesn't fully support Code Access Security.


  • Hi algorythmics,

    Sounds like you're trying to achieve a similar thing to myself. I'm building a god-sim-type-game (www.ungods.com) and have had an eye on extensibility from the outset. The scripting environment I'm trying to create allows the users scripts to react to game events, query world data, and perform predefined manipulations (using a specific scripting API). I wanted to avoid reinventing the wheel so have gone with a simple C# based scheme. Basically it goes as:

    Script files are saved as files with the extension .ugscript and have to define two methods at a minimum:

    // Called when the script starts
    void Start()
    {
    }
    // Called when the script stops
    void Stop()
    {
    }
    

    This script is loaded, tweaked a little to produce a class definition that looks like:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using UnityEngine;
    using Ungods.Scripting;
    using NetRandom = System.Random;
    using UnityRandom = UnityEngine.Random;
    namespace Ungods.Scripting.Scripts
    {
        public class SayHello : ScriptBase
        {
            // Called when the script starts
            protected override void Start()
            {   
            }
            // Called when the script stops
            protected override void Stop()
            {
            }
        }
    }
    

    This type is compiled into a .NET type that inherits from ScriptBase. The ScriptBase type defines some protected properties that are essentially the scripting API:

    protected IScriptedGod Me { get; private set; }
    protected IScriptedWorld World { get; private set; }
    protected IScriptedUI UI { get; private set; }
    protected CommandConsole CommandConsole { get; private set; }
    

    As well as some methods for registering event handlers:

    protected void RegisterEventHandler<T>(Action<T, IScriptedGameObject> handler) where T : GameEventArgs
    protected void RegisterEventHandlerWithPredicate<T>(Func<T, IScriptedGameObject, bool> predicate, Action<T, IScriptedGameObject> handler) where T : GameEventArgs
    

    So typical interactions with the API look like:

    // Register to handle ALL living thing died events
    RegisterEventHandler<LivingThingDiedEventArgs>((e,o)=>HandleLivingThingDied(e,o));
    
    // explode the object
    Me.Manipulate.Explode(id);
    
    // stop it eating
    Me.Toggle.CanEat.Off(id);
    
    // selects the object
    Me.Select(id);
    
    // Write a line to the command console
    CommandConsole.WriteLineOk(text);
    
    // Animate a text label in the UI
    UI.SmallAnimatedText(text);
    
    // Find a game object
    World.FindGameObjectById(id);
    

    The problems with this approach (as you've identified) is that you're giving away the keys to your kingdom in that any script has (eventual) access to all parts of your game. Even with a well designed API, the little buggers have access to all your internals through reflection - But then again they already do... the process is already running on their hardware and under their OS - by providing the scripting environment we've not really given them anything new, just made it easier.

    I've got a mind to try and isolate the loaded scripts in their own appdomain, and have it communicate back to the main game through the defined API - but that's something I'm putting on the back burner for now.

    To get to where I am has taken a couple of weeks and a fair amount of effort, and this is with the luxury of a language I already know, an existing compiler, type system / etc. I hate to imagine how long it would take to roll your own, you're going to end up re-inventing a whole series of wheels along the way.


  • :belt_onion:

    @null_loop said:

    Hi algorythmics,

    Sounds like you're trying to


  • sockdevs

    @algorythmics said:

    I might end up doing something like that, It will probably have to wait until the new GUI set up is introduced in 4.6 though (I don't know if you have worked with the gui as it stands, but it's fucking terrible)

    The new GUI in 4.6 is fucking awesome, btw, if you ever used NGUI it's like NGUI but more awesome. (Sat through a presentation from one of the Evangelists about it, highly impressed)



  • @algorythmics said:

    This was what I kinda expected tbh, and it's what I wanted to avoid.

    I literally wanted something like this:

    //in some class far away which has no references to external unity engine resources
    public void Shoot()
    {
    //USER CODE GOEZ HERE TO DEFINE SHOT BEHAVIOUR , PROJECTILE COUNT, OTHER FUNNY BUSINESS
    }
    

    I know from my compilers course that writing a language is the worst. Even with fancypants tools there is a lot of heavy lifting involved, and I know enough to know that I am not the best person to do it.

    I might have to just eat my own shit and use Lua.

    fuck.

    Again, I ask:

    Why are you not using JSON passed user data to populate this? Define your Shoot() default class, and allow it to be overriden by the UserDefinedShoot() JSON object. Newtonsoft allows you to read/write directly to class objects, which means that you can dynamically, on the fly, with basically NO EXTRA EFFORT allow users to define their variables, and see the changes IN REAL TIME using a sandboxed allowed variables that YOU ALREADY USE in your game engine!

    It prevents meltdowns from bad code, and 100% customization within the realm of the game engine.



  • @Matches said:

    Why are you not using JSON passed user data to populate this? Define your Shoot() default class, and allow it to be overriden by the UserDefinedShoot() JSON object. Newtonsoft allows you to read/write directly to class objects, which means that you can dynamically, on the fly, with basically NO EXTRA EFFORT allow users to define their variables, and see the changes IN REAL TIME using a sandboxed allowed variables that YOU ALREADY USE in your game engine!

    I think you are describing functionality of JSON and Newtonsoft I was not aware of. JSON allows passing of code in objects? I thought it was a data definition only type of deal. Are you saying you can define essentially javascript methods in JSON and I could hence just use that? if so, that's pretty handy, any outlines/examples anywhere you can point me to?



  • Sample section, serialize/deserialize

    Serialize:

    1public class Account
    2{
    3    public string Email { get; set; }
    4    public bool Active { get; set; }
    5    public DateTime CreatedDate { get; set; }
    6    public IList<string> Roles { get; set; }
    7}
    
    1Account account = new Account
     2{
     3    Email = "james@example.com",
     4    Active = true,
     5    CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc),
     6    Roles = new List<string>
     7    {
     8        "User",
     9        "Admin"
    10    }
    11};
    12
    13string json = JsonConvert.SerializeObject(account, Formatting.Indented);
    14// {
    15//   "Email": "james@example.com",
    16//   "Active": true,
    17//   "CreatedDate": "2013-01-20T00:00:00Z",
    18//   "Roles": [
    19//     "User",
    20//     "Admin"
    21//   ]
    22// }
    23
    24Console.WriteLine(json);
    

    Deserialize:

    10
    11Account account = JsonConvert.DeserializeObject<Account>(json);
    12
    13Console.WriteLine(account.Email);
    14// james@example.com
    


  • Sorry, that was the bit of JSON I already understood, the bit I don't understand is defining code within JSON, rather than just letting them change variables.

    or have we gotten wires crossed?



  • 1string json = @"{
     2  'Email': 'james@example.com',
     3  'Active': true,
     4  'CreatedDate': '2013-01-20T00:00:00Z',
     5  'Roles': [
     6    'User',
     7    'Admin'
     8  ]
     9}";
    10
    

    You have the user pass in via GUI or text editor or w/e your interface is the above. You can preformat it for them to be kind. You then serialze to <Account> object.



  • That's still just defining values, not behaviour.

    What if I want to let one user do

    Projectile.Weight = 50;
    Projectile.Fire(500)//initial force
    Wait(5)//seconds
    Projectile.Explode()
    

    (defining a simple grenade launcher type thing)

    and another to do

    Projectile.Weight = 0.1
    Projectile.Damage = 0
    Projectile.Fire(5000)
    for(int i = 0; i < 20; i++)
    {
      Projectile.Spawn(new MetroidTypeBeasty())
      Wait(0.05)
    }
    

    to define a projectile that just spews forth a mass of beasties without damaging anything it hits along the way.

    I don't see anything in the examples (or know anything from my recollection of JSON functionality) that would allow someone to define something like that.



  • As part of shoot, you would have a Spawn class, and you would pass in something like a list of values (number of spawns) plus the number of delay between each spawn.

    You as the engine owner define what is possible, your users define what they want to do.

    Or, more succinctly:
    list<float> SpawnProjectile

    foreach(var projectile in SpawnProjectile) { Projectile.spawn(new whatever()); wait(projectile.wait)}

    Terrible pseudocode, but it's close enough as an example IMO.



  • Ok, so what we have gotten to is "you can just let your user set variables, and just assume you are smart enough to figure out every combination of possible actions your user might want to do, and account for them" I don't think that works, I pretty much end up with a ridiculously long shoot method trying to foresee every possible desire (what if the player wants to spawn in bursts of 3?), and players constantly complaining "oh why didn't you forsee this, go rewrite your shoot method so I can do this really cool thing".

    I don't think a setting variables only solution works, there has to be SOME element of scripting there.



  • Your other option is to create your own entire scripting language, which essentially does the same thing, and enabled potentially rogue elements in to your game.

    Your game isn't that special. I'm sorry. There's a limited number of things a users will consider doing, and most will complain about missing features which you should patch in. If you design YOUR world using your own api, you will stumble across 99% of the normal user complaints that you will get about missing functionality.

    There's absolutely no reason to allow unrestricted access to your application, as users who want that will be designing their own games. Your job is to provide a user interface and some customization.



  • @Matches said:

    There's absolutely no reason to allow unrestricted access to your application, as users who want that will be designing their own games.

    That's true, but only setting variables is pretty restrictive, too, and a large burden on the developer. The best thing is to be able to have some sort of language that you can sandbox and give it integration points into your code. I'm not sure why you're so against Lua, but it was pretty much built for this purpose.



  • I'm not against LUA, the OP is (which I assume is who you meant to target that response at)

    But given the constraints the OP is providing, I'm trying to give sane options.

    Unless you're defining entirely new functionality via user script, you've already defined your objects somewhere. Just expose those objects.



  • @Matches said:

    I'm not against LUA, the OP is (which I assume is who you meant to target that response at)

    Yes, sorry.

    @Matches said:

    Unless you're defining entirely new functionality via user script, you've already defined your objects somewhere. Just expose those objects.

    Yes, new functionality in terms of combining and executing things using the objects in an application.



  • I've said several times now that I was pretty sure I would just have to bite the bullet and go with LUA, but your response seemed to be "why aren't you just using JSON?"

    Removing that constraint, would you say Lua was the best solution then?



  • Lua is a good option, or since you're using unity3d, why not use unityscript?

    You use JSON to populate object data, and in that object, create a string field with custom command behavior that contains unityscript. That way you're still boxing the data and implementing restrictions on how it gets set, retrieved, and executed and you have at least moderate more control over how its' parsed and validation events against the data.



  • Why are you even still discussing this after someone has shown how to do precisely the thing that was requested in the op?



  • @boomzilla said:

    Matches said:
    I'm not against LUA, the OP is (which I assume is who you meant to target that response at)

    Yes, sorry.

    But you quoted @Matches, don't you know it means you're replying to him?



  • @Maciejasjmj said:

    But you quoted @Matches, don't you know it means you're replying to him?

    Yes, I did know that, but I just got a little careless in writing the reply (yeah, I'm aware of the stuff you pointed out on meta.d, too).


Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.