 So, we're going to talk about typescript.net very, very, very, very early stage for game modding. But, you know, you can do whatever you want with it. My name is Andrea Gaitham. I am the editor tools tech lead at GitHub and formally I was at Unity and Novel and Xamarin doing monostaff. So, it's been five years since I've been here. So, this is fun for them. Okay, so let's get started. There are a lot of contents and I'm hoping to get through all of it, so it's fun for you. Languages and game development. So, games are like all other software built on tech stacks on layers. You usually have foremost software, one language, maybe two, maybe three, you might have some shell scripts for your build system. You use one language to do your app. You might have some data languages formatting like, you know, whatever, Jason, other languages that are accessory, but you do it all on one language. Games are slightly different because of the way of the disciplines that building games brings in. The game engine is usually on languages that have facilities for aligning data and memory so that you can optimize putting pixels on the screen, basically. Not that these languages are better or worse than anything else. It's just like, you can control how the memory is arranged, so the memory is layouted. You can send things to your graphics card at the fastest rate possible. So, you pick those languages, they're optimized for this. But, you're making a game and you're making it with there's game engine programmers, but then there's the gameplay developers, and then there's the game designers, level designers, scene designers, they are technical artists, everybody else building content on the game. They might have worked on the engine, they might not, they might not even own the engine. The engine is doing some things, and these people have to build content on top of it. Which means the language that gets used in these, in the scenarios is not necessarily the language of the game engine. You want to pick a language that is appropriate for the task that they're doing, right? It's not about data alignment anymore in memory. It's not about the most performance and most tasks. It's the one that's most expressive for describing what's happening in your game. And a lot of these people in these teams are not programmers at all. They don't come from a programming context. So, they don't even know how to code. But they can code. They need tools that they can use to express what they're doing with the game without having a full CS degree. So in the game industry, this is very common. You have multiple languages building on top of each other to provide the best tool for each job, right? And while C and C++ is very often on the game engine, C sharp, Luobasic, Scheme, F sharp, all of these languages that are expressive or functional or data oriented or have some other type of thing going for them is the language that everybody else is going to use to build the game with, right? So, here's the game. So, I got interested in this topic back when I saw some slides from a talk about, from Naughty Dog, about how they build Uncharted. If anyone has played Uncharted here, hopefully some, it's a game. It's a bunch of games. So, Naughty Dog is a Lisp house. They're very, very heavy Lisp pens. And they really didn't want to give their designers C to script their game. It's not efficient. So, because Lisp pens, they built a variant of Lisp, a scheme, a simple scheme language to give their designers so that the designers could just focus on making the game, reactive to events, talking to the engine, but not touching the engine. There's all of these advantages to having a completely separate scripting language that's running in a VM in your game engine. Like the engineering team doesn't have to directly be involved. And when we talk about engineering, we're talking about people maintaining the engine. Doesn't have to be directly involved with the content creation for the game. Code is data. It's easy to just change what's going on without touching the game engine itself, that the game engine becomes more generic. It empowers game creators and side effect. It empowers modding communities. Because when you have a language that's completely separate, that you used to build your game on, you can give that language to someone else to build things on your game. Because that's what you're doing, you're modding the engine. So, it's just the side effect that it just becomes very easy to provide tools for modding communities to build their own content for the game. This is the example that they have for their language that they gave. And I was very curious about this. So I emailed the person that gave this talk, asking how do designers have never coded before handle this? And it was like, they handle it just fine. They have no problems with this. They don't have a background in programming. So for them, this is just, it's easy. There's no side effects. They just react to things, trigger things, stop and play. Things happen, and they script, literally script the sequence of events that needs to happen whenever something else happens. They put things on screen, they attach scripts to things on screen. And for them, this is just a lot of parenthesis, but it's fine. They don't consider this programming. It's just scripting. So that was interesting. And sometime later, Neverwinter Nights. Not that Neverwinter Nights came later. I just looked at it later after I entered it. Neverwinter Nights came out in 2000 something. And Neverwinter Nights is an RPG based on D&D 30 editions. You usually multiplayer RPG, but it has one key difference. This is Neverwinter Nights. It is fully moddable as a lot of games are, but back then, not a lot of them were. And it has a full editor shipped with the game. So now, this is available for the people that are running the game, not the people that are building the game. The people that build the game also use this to build the game. But this is shipped with the game. The thing with Neverwinter Nights is when you're running the game, you can fire up the editor, create your whole campaign with all of the things that Neverwinter Nights ships, like all of the assets. They give you a license for all the assets, as long as you're not making money with the assets. You have all of the assets, like all of the characters and all of the tiles for terrain, everything. You have all of these things. So you can create a completely empty space. And you can build your own campaign to put all the scenarios together in the editor. And then you can script everything. So you can basically go into any of these objects that are in this area. And you can attach scripts to them. And the script is a C-like language, basically, that they have. Which allows you to make these things interactable. And then anything can interact with anything else, and anything can do anything. Which means you can just basically, you have a game and you just make a new game out of it at runtime. Let's just say this, right? You're not compiling the game. You're just building this content out of a shipped game. It also has all of these things that you can edit. Because if they have the tools, they had the scripting language and they had all of these tools that they built to make their game, it's free for them to just give this to the users. There's no overhead for them. There's no support that they need. It either works or doesn't work. The interesting thing about Neverwinter Nights, and I'll get to TypeScript and AL at some point, this is background for why I'm doing this, is that not only can you do all of this scripting at runtime, but the admin that's running the game. While the game is running, because this is a multiplayer game. So you can invite your friends to go into your server and play with you. Unlike the same way that you play multiplayer, but this time you're hosting the server, you control what comes in and comes out, it's your game. The admin that's running the game can go into the game while it's running and take over an NPC while another play is interacting with that NPC. Just override the entire dialogue tree of that NPC and start interacting with the player directly. And it's the ghost in the machine, right? And they can make quests, like on the fly. Like, yeah, we're gonna make a quest for you right now, cuz I'm bored and I'm gonna run a quest for you, but I'm an NPC. And this got me really interested, because there's not a lot of games that do this. In fact, there's none. Neverwinter Nights is 20 years old. There's still people running Neverwinter Nights servers. Because when you can do that, it's fun. It's a community, right? And we all know the popularity of Minecraft and other type of environments. It's about how you can modify the environment and interact with other people. This goes to a slightly next level, but it's an obvious next level. If you can control all the content and you're doing this at runtime, why not do it at runtime and control, literally override the system whenever you want. But Neverwinter Nights looks like, you know, old. So a few months ago, because of that, it was like, they would be so much fun. We could do something like this with better graphics and nicer engine, right? And just side effect, but it turns out that most D&D data, like all the monster descriptions and all the levels and all of these things, is about open source. Wizards of the Coast open sourced D&D 3.5 and D&D 5.0. Not the names of the characters, like the name characters, the bosses that you fight, but every single other data set from magic spells to names of creatures, like everything that you can find in the D&D book, all of it is under a license called OGL. Open given license. So it's all open source. Anyone can take that content and make things, which is how, forgetting the name, what the company that builds out of that content is. There's a company that builds entire contents out of this because it's open. So it's like, we have all this data and we can make this. And then we have Unity, which is a game engine that runs on C-sharp and Mono. So, we already have a VM that can compile things at runtime and reload because that's what it does. We have a game engine that runs on top of this VM. So we can put all of this together and recreate whatever winter nights did with a modern engine, modern language, modern everything. So, we come into scripting system. At this point, I'm still thinking I'm gonna use C-sharp for this because C-sharp is there. I know C-sharp, I worked on Mono, I know that part is easy. Doing a reloadable, recompilable system runtime is easy, loading all the data is hard. So, but then I had this problem, it's just Y type script. So, I'm gonna show you the little silly prototype of the system running. So you can understand my problem. So this is a very silly prototype of a thing that moves around. That cube is a trigger right there and this script is attached to it. This is the default content, it's not compiled yet. But if I compile it, I've compiled the script, I've reloaded all the data. Now, if my thing goes there, there's a bug. I don't know why it says activate instead of yay. But in any case, it now activates because the script is now attached. I recompiled it and did all of this. This is cool, and I mean it's nice, it's a one liner, I can just do it. Anyone can go in and write code, but code is not one liners. When you're writing games, it's never one liner. It's get this object and do some math on it and do something or other and update this state or react. It's multiple one liners, it gets complicated. And the problem with C sharp is that the code that gets generated is actually this. And that's why it doesn't stay longer, it didn't actually generate the right code. It's this, for that line to run, which should be in here, right? For that line to run, I have to have all of this scaffolding. Because C sharp requires it, this is what C sharp looks like, right? And now I have a new problem. If I just provide the users with an interface to type a one liner, they can't do more than one liner scripts. If I give them all of this because they will actually need to define some helper methods or to pull in other things. And all of these facilities that the language actually has, they can break everything, they're very easy to set themselves in the foot. Like method signatures become complicated, like what do I override? It's no longer the language that I give a designer so that they can quickly react to events, right? But if I go back and just give them, hide all this scaffolding, I'll figure it out somehow. If you take all of the code that you're writing in the little editor, put it somewhere else in an IDE, it's not valid C sharp code. Valid C sharp code needs this. So I don't get co-completion anywhere else. For co-completion, I need all of it. I don't need syntax highlighting all of these facilities. That is the reason why we use C sharp, because we have all of these things. So C sharp is not the best language for this. And I looked at Lua and I looked at other languages, but I didn't want to. We have that net, like unity runs mono and dot net. Like I have this, and then I looked at TypeScript. And it turns out it's perfect because TypeScript is a fully typed. It can look just like C sharp in a fully typed mode. There's all type information, but it's flexible enough. That doesn't require all of this scaffolding. So when you copy paste entire code into a VS code, you'll get the type completion. And the language actually allows you to just go like, you know what, ignore type completion, but don't give me errors, because I don't know what this thing looks like. Because it's JavaScript in the bottom. It types in TypeScript are a super set of what the thing actually is. And so it's flexible enough to be used for people, anyone. There's a lot of resources online for people to use it. It is typed enough for me to take it and throw it in IEL. Because I have all the types that I need to do this. So then it comes to the things that then people, these are the things that the designers and people that are making code need to do. Like integrated VM check. Like all of these things both C sharp and TypeScript can do. But defining types is the thing. In C sharp when you define types, you have to know what you're defining. You define classes and structs and there's a logic. And if you don't define them up front, nothing will work or compile until you do. There's no flexibility in the type system at all. It's type first and then script. And TypeScript, it's script first and then type. You can go like, trust me, it'll work at some point. It's fine. Which is, I mean, if the type is not defined at some point, it's not fine. But the IDEs will work. The IDEs will be very flexible, people not knowing exactly what they're doing until the point where you run it. But at least when you're prototyping and building, the ID is not getting in your way. It's helping you. And it's helping you learn. Because if you type one thing, it goes like, oh, I've seen this before. Sure, I'll help you again, even though it doesn't exist. But I trust you will always exist. So I saw all these things and thought, eh, TypeScript. I'm going to skip that all of that. So these are the things that I ended up with for TypeScript. TypeScript is transpiler-friendly. It's not a real language. It's a facade on top of another language. That means it comes with full tooling for IDEs, for figuring out what the code is, building ASTs, because that's what it does. And since we only have 10 minutes and I don't want to bore you more with talk, I'm going to leave you with the turtles and I'm going to show you some code. So that was my motivation for all of this stuff. So basically, actually, I have another slide that I can put up. So basically, what TypeScript gives you a TypeScript namespace? TS. That's the namespace for the ASTs, compilers, parsers, type checkers, and all of the stuff that's built into TypeScript. Like, this is built in. You don't need to pull in anything else. To actually get any code to be parsed by TypeScript, literally, this is what you need to do. You just do create source file, give it some name, throw in some code. You can read it off of disk, whatever. Throw in some code and then tell it to transform. You implement a little visitor pattern that will get called for every note that the TypeScript finds. TypeScript will build this AST. For those two lines up there, this is what TypeScript automatically gives you. It will give you calls for every single one of these notes. This is a little treat. The source file has all of these nodes, and then you can go down and you can decide whether to go down or not. I just recursively go down by doing that, visit each child. This is the visitor implementation that I have. I log what the node is, and I visit each child, and then this is what I get. And that's literally what you have. So you can see this is not valid TypeScript, or is it? This TypeScript actually care. Does the IDE actually care about this? It doesn't, because it actually thinks this is a property exit expression. It doesn't say this is gibberish. It actually says, hey, this is an object that has a property, and that is another property. If you provide TypeScript with more context about what these objects are, TypeScript will give you better information about what they are. So TypeScript doesn't care. They will still think that this code and it identifies the syntax, which is perfect. Because now we can write a class library access for .NET that TypeScript has no idea what it is. It won't complain, and it will give us type information on all of these things. And then what we get is, in this case, this simple line that TypeScript has no knowledge of, if I compile it into IL, you can see the tree that it provided. I'm not sure if you can see that in the back, hopefully. Those are all the nodes that I parsed. And I generate IL, and now we have .NET. And the IL that I generate is literally this, which is the equivalent IL for the TypeScript. So five lines of code, TypeScript Compiler. It's a bit more than that, but it's a good start. It was a good proof of concept. And this is where I started from to proof of concept, like is this viable? Does TypeScript have enough type information that I can take this and produce a viable IL from it? Turns out, yes, because JavaScript, there's only two types, string and number. And the TypeScript JavaScript model is literally containers of key value pairs. It's a dictionary. Every time you access a property, it's literally going in and look at the table and see if the thing exists. If it does, it won't complain at you. So putting TypeScript on top of JavaScript, you can do, because you can just build on top of the very simple string and number model, which is what they do with types. Taking that to C sharp is literally just deciding. It's transforming the syntax into IL, taking TypeScript.net is transforming the syntax into IL, and then deciding what is useful from the environment. Like TypeScript and JavaScript are not just the language, but they're also the ecosystem, JSON.parse, and all of those methods that you just take for granted. They're not actually part of the language. They're a part of the ecosystem that happens to come with a runtime that you're running in, in this case v8. When you're running TypeScript in .net, you're running in the .net runtime. So you get the environment that .net gives you, which is system console system, all of these things. And now you just get to decide what TypeScript it makes sense in this kind of environment. It is just like literal .net calls directly into it, or do you do some node facades to make it look like the normal JavaScript that you would see, but under the hood, you just call into .net to do these things, which are helpful libraries that once built, they're there, and you never see them. These are the questions that I'm considering now, and then handling any. When you have a type that is not a type, where TypeScript just goes like me, whatever. How do you transform that into IL? Do you just do JavaScript and just make a dictionary or keel-value pairs? Whenever you see property access to an any type, you just go and look up. You just create IL that goes look up into the dictionary. That's an option. You could use the DLR. That's another option for end-use dynamic, as you would in C-shark. So these are the questions that I have around TypeScript to .net right now, and then for game-specific step to actually pass data around, but that's for the game. So this was, this is the very last minute talk, so the code is not up yet. Well, it is up, but it's not ready for consumption. But ping me, email me, because I really want to start fleshing out this thing, because I actually want, I need this for the game. So, you know, and if you're interested, ping me on Twitter or email me or whatever, and I'll see about putting the thing that I'm calling T-S-I-L for now up in public. And we got, yeah, a few minutes for questions. We're going to set up while you folks have questions. Yes. Questions, please. Yes or not? What? Many people will just come up with questions. If they have them, yes.