Arbitrary XML\DLL definitions

Started by RawCode, August 21, 2014, 04:44:12 AM

Previous topic - Next topic

RawCode

This is extended answer to:
http://ludeon.com/forums/index.php?topic=5610.0

My original answer was ignored:
Quote
You must extend thing def in your code with fields you like and define your thing def, not basic type.
for no good reason.

1) If you want to have arbitrary define type, you MUST extend Def.
Classes not extending Def are ignored by database assembler.
Extending ThingDef or any other "second level" defs require to use "Class" modifier, or base type constructor will be used.

2) You dont need to nest your type inside "ThingDefs" - you must define separate category, format is type name + s.
(note, ALL CAPS names will fail)
In other case database assembler will fail to find your def.

In case of "Class" modifier - def must be hosted in "base" folder, if Class points to type not accessable due to any reason - default type will be used, any additional fields will be ignored

Test type:

    [EventListener("instance", "entry")]
    public class typez : Def
    {
        public string testvalue = "NOT DEFINED";
        public static typez instance;

        public typez()
        {
            instance = this;
        }

        public static void entry()
        {
        }

        [EventHandler(EventPriorityEnum.LOW)]
        public void testa(GameStartedEvent e)
        {
            Log.Warning(testvalue);
        }

    }

do require Rimgazer API to work.

Def folder will be Defs\typezs\arbitraryname.xml

3) XML def follow same rules as folders do:


<?xml version="1.0" encoding="utf-8" ?>
<typezs>
<typez>
<testvalue>REPLACED BY DEFINE</testvalue>
</typez>
</typezs>


Running such mod will show "REPLACED BY DEFINE" on game start.

In order to test code without running game and without usage of API - static initializer may be used.
It will be invoked early (or not invoked if something is wrong).

Haplo

Quote from: RawCode on August 21, 2014, 04:44:12 AM
...
My original answer was ignored:
Quote
You must extend thing def in your code with fields you like and define your thing def, not basic type.
for no good reason.

I think the reason was, that noone really understood what you meant there. ;)
This one is much more understandable :)

But personally, I am not that big of a fan of the API, as you use a bit of 'hacking' to insert your code into the program code and watch the events. I honestly don't really understand all of how it works and what you do there, but from my point of view it allows too deep access without the possibility for some checks of harmful code. So I most likely won't use it until I know from a second source, that it is save to use.
But as so often, that is just my personal oppinion and it is most likely based on my missing knowledge of what you can and can not do this way.

You write really good code, but for now, it isn't something for me.
Maybe later, when I know more about all the stuff you do with it :)

Neurotoxin

Quote from: Haplo on August 21, 2014, 06:18:26 AM
Quote from: RawCode on August 21, 2014, 04:44:12 AM
...
My original answer was ignored:
Quote
You must extend thing def in your code with fields you like and define your thing def, not basic type.
for no good reason.

I think the reason was, that noone really understood what you meant there. ;)
This one is much more understandable :)

But personally, I am not that big of a fan of the API, as you use a bit of 'hacking' to insert your code into the program code and watch the events. I honestly don't really understand all of how it works and what you do there, but from my point of view it allows too deep access without the possibility for some checks of harmful code. So I most likely won't use it until I know from a second source, that it is save to use.
But as so often, that is just my personal oppinion and it is most likely based on my missing knowledge of what you can and can not do this way.

You write really good code, but for now, it isn't something for me.
Maybe later, when I know more about all the stuff you do with it :)

Well as it stands now, Harmful code could be executed by the game itself.

It all comes down to how it's used obviously but what he's doing with his API, to put it VERY simpily (not that I think you don't understand but for anyone else) is the same concept as Forge for Minecraft except that java makes it easy with it's reflection API whereas C#'s reflection is a lot more strict.

The benefits of an event system are innumerable but as an example, Colonist Creation Mod would be able to work again, fairly easily, by registering a listener for say a GameLoaded event, intercepting the randomized pawns and replacing them, without having to make a new pawn class.

Balancing patches would be possible by registering for an IncidentFired event (I'm making up the names for events as I go but they're possible) checking the number of pawns it's trying to spawn and maybe making adjustments to the number based on say, sq footage of your base, number of turrets, number of colonists and type of gear they have, to present constant challenges while not destroying your game with massive numbers of pawns.

Of course Malicious code could be inserted but the way assemblies are currently loaded now, there's nothing to stop you from doing that already as all the assemblies run in the same appdomain and even then there'd be ways to get around it.

@RawCode, Like Haplo said, some of your answers are difficult to understand but they are good answers. I think the reason for that is the language barrier but I and I'm sure others appreciate the effort you are putting out trying to get the answers out there.

MonkeyWithAWrench

Haplo and Neurotoxin are indeed correct in that I didn't understand your answer at the time. Hence my response about not "seeing" what I was doing wrong from you said. Thank you for expanding your answer however.

MonkeyWithAWrench

I'd like to add that upon further thought, perhaps my saying that I wasn't "seeing what I was missing" was a poor choice of words. Because I didn't really understand what you meant I had thought you were probably saying that I had just made a mistake in a line or two somewhere. Written a command wrong or made a wrong call or something. So I had just been trying to say that I wasn't seeing where those wrong lines were.

I apologize for that, I definitely didn't mean to make you think that I was ignoring what you were saying.

RawCode

Its possible to protect mods from harmful code:
1) Byte code parsed before loading by "border guard".
2) If references to forbidden types or forbidden methods are found - loading is rejected.
3) Trusted mods marked with digital signature.
4) Keys embedded into game and checked online for revocation (if network connection is present). (if network connection not present - all embedded keys are "valid")
(player can inject his own key to his own game and sign his own mods if needed, this will allow anyone to test any code, but not to distribute it to public)

5) This will allow trusted persons to sign mods after check and if such persons "gone rogue" key simply revoked.
Such system have very low cost and will provide solid protection as long as nobody gone rogue.

As for API and how it works:
http://ludeon.com/forums/index.php?topic=5549.0

        [EventHandler(EventPriorityEnum.LOW)]
        public void disableFrendlyFire(UnitDamagedEvent e)
        {
            //Log.Warning(e.damageMeta.Instigator.ToString());
            //Log.Warning(e.damageMeta.Source.ToString());

            if (e.damageMeta.Instigator == null)
                return;

            Pawn source = e.damageMeta.Instigator as Pawn;

            if (source == null)
                return;

            if (source.MindState.Sanity != Verse.AI.SanityState.Normal)
                return;

            if (e.pawn.Faction == source.Faction)
            {
                //Log.Warning("Disabled frendly fire event");
                e.suppressed = true;
            }
        }


Lets imagine that our "damage event" is list of paper.
Mods that do not know about each other may write to same line of that list.

If line 1 filled by mod A, then mod B may fill same line with other data.
This will erase any changes done by mod A without any trace and any warning.

If later mod A will attempt to read line 1 and perform actions based on that line - it will fail.

In case of API it will tell mod B "don't write to line 1 it already used, use line 87 instead"
When mod B try to read line 1 API will tell "line is belong to mod A, real line 87 instead"

Both mods will do what they planned without conflict, this is why API is essential.
In other case nobody will resolve conflicts.

Language barrier is issue, but instead of "get angry on entire world" i simply explained my post, i hope this thread will help community.