C# modding

Exeton

Terrarian
Due to my lack of interest in making tutorials, I've decided just to make and show pieces of code here instead.
It's come to my attention that a lot of people are asking basic c# questions on the tModLoader form and that no such tutorial answers these questions.Also, I've only created this thread because It's typed up, so please tell me if there are any grammatical or coding errors.

1.Setting up your mod
Before you even start your mod, you'll need visual studios which can be found here.
An instillation guide I recommend you use can be found here.

-You can access you mod files at C:\Users\Your User Name\Documents\My Games\Terraria\ModLoader\Mod Sources

-You can also get here by opening tmodloader, going to the build mod menu, and clicking open sources
P1.PNG p2.PNG

2. Basic c#
C# is mainly made up of classes, which have methods and variables.

A few things you should know/General tips:
- If you don't have c# or can't get c#, you can open .cs files and modify them with word/notepad/any other word editing program.(Credit to @Temmie can be found at the first post)
-Statements end in a semicolon(;).

Now let's get started. In this lesson, you'll be learning about basic methods and classes.


Code:
using System;//These are using statements which are needed for methods to do things programmed into c# i.e(use Thread.Stop(1000); (stops game for 1000 milliseconds.))
using System.IO;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace Commands//This is a namespace, it is where all your project/mod's data goes.
{
     public class Comands : Mod//This is a class, or something which holds data
     {

     }
}
This goes inside an empty .cs file
Code:
    public override void SetModInfo(out string name, ref ModProperties properties)//This is a method. Make sure to add the override part unless you're calling it. We'll get into that later
    {//For every curly bracket goto hi;
        name = "Comands";//YOUR MOD NAME
        properties.Autoload = true;
        properties.AutoloadGores = true;
        properties.AutoloadSounds = true;
    }hi://There's a closing bracket

Key Points:
-Voids must go inside classes
-You only need this stuff once per mod
Finished Code:

Code:
using System;
using System.IO;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace Commands//YOUR MOD NAME
{
     public class Comands : Mod
     {

         public override void SetModInfo(out string name, ref ModProperties properties)
          {
               name = "Comands";//YOUR MOD NAME
               properties.Autoload = true;
               properties.AutoloadGores = true;
               properties.AutoloadSounds = true;
          }
     }
}
After this, create a .txt file named build(build.txt)
a.PNG

It should have the author, version, and name.
3. Data structures
Data structures are anything that stores data pretty simple. Data structures are different sizes, and making a data structure the right is proper technique. What do they store. They store numbers letters and objects(we'll discuss that later).
Here's a basic chart of what you can use them for.

NOTE:This is not my work and can be found here.
Code:
string : stores letters

bool : stores a value which can be true or false
Number Data structures:
sbyte -128 to 127
byte 0 to 255
short -32,768 to 32,767
ushort 0 to 65,535
int -2,147,483,648 to 2,147,483,647
uint 0 to 4,294,967,295
long -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
ulong 0 to 18,446,744,073,709,551,615
NOTE:This is not my work and can be found here.

These numbers allow you to use less data, but will cause errors if used incorrectly. When you try to move data from one type to another, be careful.
When converting data of different types use a cast.
For example
Code:
int a;

byte b;
a = 0;
b = (byte/*This comment can go inside code*/)(a);//Using the cast
///Side note:you can make comments in all these ways
More examples:
Type this code inside
Code:
public override void SetModInfo(out string name, ref ModProperties properties)
's curly brackets


This Code:
Code:
int x = 0;//Creates a number called x which is equal to 0
int y;//Creates a number called y
short A;//Creates a number called A
short C;//Creates a number called C

y = 5; //Sets y equal to 5
x = y;// Makes x equal to 5
A = x;
Did you get an error?
This is because a short and an int aren't the same. Imagine someone gives you a big cup which is full of water and tells you to stick it in a smaller cup. The computer has the same dilemma. To prevent any problems like this, the computer requires you to cast data. To do this replace A = x; with A = (short)(x);
This tells the computer x is smaller than a shorts' size(A's max size). Do not do this if x can be bigger than the size of a short. Also, random numbers are ints so if you are getting a random number, you must add a cast.
Example
Code:
byte y = 0;
Random r = new Random();
y = (byte)(r.Next(1, 240));//Gives you a value between 1 and 239
When would I use this?
-When generating ores. This generates them at a random place.
-When choosing a boss attack from a list of attacks
-Many more reasons

Another example
Code:
Random r = new Random()
byte A;
A = r.Next(1, 220);//Generates a number from 1 to 119
Main.NewText(A.ToString());
Where should I put this?
This can go in any hook for example in the chat input.
4.Loops, Statements, and advanced data structures
Now, we're going to use our knowledge to create some commands.
Start by using this code(Not my code - from the example mod)
Code:
public override void ChatInput(string text)

[SIZE=5]{

}
This code is called when chat is entered and is called a hook.
Commands, execute code i.e. Main.NewText("Hello, how are you"); can be put in here.
But what if you want to add commands? Here is some more code from the example mod which allows this.
Code:
        if(text[0] != '/')//!= means does not equal
        {
            return;//Means no more code will be executed after this
        }
        text = text.Substring(1);//makes text not have the first charter(based off number in parenthesis)
        int index = text.IndexOf(' ');//Set's an number(index) equal to the amount of the charters before a space(based off the charter in the parenthesis.)
        string command;//Creates a data structure which holds letters
        string[] args;//This is an array. This means it stores multiple strings. These strings can be referenced with args[Number in the array]
        if(index < 0)//Checks if there are more than zero spaces
        {
            command = text;
            args = new string[0];//Makes args hold 0 strings
        }
        else//If there are multiple spaces
        {
            command = text.Substring(0, index);//makes command equal to all the text before the first space
            args = text.Substring(index + 1).Split(' ');//Makes args have a new string for each space and puts that part of the text in the array
        }
Now that you have split up the command into arguments, you can use it.
Now we are going to be using an if statment. This statement does something if the criteria in the parenthesis is true.
Code:
if (command == "buff")
{
if (args.Length != 0)//Makes sure the array args has multiple arguments. This is important and prevents the computer from giving null reference exceptions.
        {
            Player player = Main.player[Main.myPlayer];//Creates an object, we'll go into this later
            for (int i = 0; i < 22; i++)//22 is max buffs // This is a for loop we'll go over this soon.
            {
                if (player.buffType[i] == 0)//Checks if a buff is active
                {
                    int j = 0;
                    if (Int32.TryParse(args[0], out j))//Checks if the players input is a number.
                    {
                        player.buffType[i] = j;//Sets the players buff type equal to the inputed number
                        player.buffTime[i] = 21384000;//Gives the buff for 99 hours
                 
                        return;
                    }
                    else
                    {
                        Main.NewText("Invalid buff Id");
                        return;
                    }
                }
         
            }
            Main.NewText("You cannot have any more buffs");
        }
Main.NewText("Invalid argument");
}
Now let's look at loops. We'll start with a for loop.
Pretend you want to create a hole in the ground. All you have to do is use WorldGen.KillTile(x, y);
Now pretend you had to make a hole 2 by 4. You would have to type...
Code:
WorldGen.KillTile(x, y);
WorldGen.KillTile(x + 1, y);
WorldGen.KillTile(x + 2, y);
WorldGen.KillTile(x + 3, y);
WorldGen.KillTile(x, y+ 1);
WorldGen.KillTile(x + 1, y+ 1);
WorldGen.KillTile(x + 2, y+ 1);
WorldGen.KillTile(x + 3, y+ 1);
Now let's pretend you needed to make a 5 by 300 size hole like I do in my mod.
To do this, you'll have to type in that command 1500 times. Sounds like fun!
Instead of this, you can use something called a for loop which does all that work for you. Add this to your method - inside public override void ChatInput(string text)
Code:
for (int i = 0; i < 2000; i++)//Counts from 0 to 1999
{
Main.NewText(i);//Displays i
}
Open tModLoader, build your mod, and run it. Type in a some text. If you put this above if(text[0] != '/'){...} anything you type will cause it to write the numbers. If you put it below, you have to type '/'. Give it a shot.

More code:
As you may be able to tell, I'm getting a bit bored making this tutorial, so I'm just going to show you how to code stuff and you can follow along as you wish.
[ /spoiler]
[/SIZE]
 
Last edited:
It's come to my attention that a lot of people are asking basic c# questions on the tModLoader form and that no such tutorial answers these questions.Also, I've only created this thread because It's typed up, so please tell me if there are any grammatical or coding errors.

1.Setting up your mod
Before you even start your mod, you'll need visual studios which can be found here
After you've installed visual studios, go to C:\Users\Your User Name\Documents\My Games\Terraria\ModLoader\Mod Sources and create a folder with your mod's name. Inside, create a new c# file. You can do this by creating a text file and changing its' extension to .cs or by copying an existing c# file. This file should be titled with your mod's name.
2. Inside c#
Open your .cs file. Before we start editing, there are a couple things you should know about c# 1. Using statements(located at the top of the file) allow you to use features from that namespace(Resources other people coded that you want to use). 2. c# statements(when you tell c# do execute code) MUST end with a semicolon[;].

For this .cs file, we are going to be using the following statements. Put these at the top of your .cs file.

Code:
using System;
using System.IO;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
Next, we need to add the name space. EVERY File you create needs this. It should have the same name as your mod's folder and this .cs file.
Also, add an open and closed curly brackets and a class with the same name(which inherits Mod). It should look like this
Code:
using System;
using System.IO;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace Commands
{
     public class Comands : Mod
     {
  
     }
}
Now, we need to add this inside our .cs file
Code:
    public override void SetModInfo(out string name, ref ModProperties properties)
    {
        name = "Comands";//YOUR MOD NAME
        properties.Autoload = true;
        properties.AutoloadGores = true;
        properties.AutoloadSounds = true;
    }
Please note, this uses an override void. This MUST HAVE override void, and anything with the title override void must be the same as the method copied. We'll go into more detail about that later. Please also keep in mind that voids must ALWAYS be inside a classes curly brackets.
Key Points:
-Voids must go inside classes
-You only need this stuff once
Finished Code:

Code:
using System;
using System.IO;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace Commands
{
     public class Comands : Mod
     {
  
         public override void SetModInfo(out string name, ref ModProperties properties)
          {
               name = "Comands";//YOUR MOD NAME
               properties.Autoload = true;
               properties.AutoloadGores = true;
               properties.AutoloadSounds = true;
          }
     }
}
3. Data structures
Data structures are anything that stores data pretty simple. Data structures are different sizes, and making a data structure the right size can help make your mod run slightly(Not noticeably faster), but is proper technique. What do they store. They store numbers letters and objects(we'll discuss that later).
Here's a basic chart of what you can use them for.

NOTE:This is not my work and can be found here.
Code:
string : stores letters

bool : stores a value which can be true or false
Number Data structures:
sbyte -128 to 127
byte 0 to 255
short -32,768 to 32,767
ushort 0 to 65,535
int -2,147,483,648 to 2,147,483,647
uint 0 to 4,294,967,295
long -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
ulong 0 to 18,446,744,073,709,551,615
NOTE:This is not my work and can be found here.

These numbers allow you to use less data, but will cause errors if used incorrectly. When you try to move data from one type to another, be careful.


Type this code inside
Code:
public override void SetModInfo(out string name, ref ModProperties properties)
's curly brackets


This Code:
Code:
int x = 0;//Creates a number called x which is equal to 0
int y;//Creates a number called y
short A;//Creates a number called A
short C;//Creates a number called C

y = 5; //Sets y equal to 5
x = y;// Makes x equal to 5
A = x;
Did you get an error?
This is because a short and an int aren't the same. Imagine someone gives you a big cup which is full of water and tells you to stick it in a smaller cup. The computer has the same dilemma. To prevent any problems like this, the computer requires you to cast data. To do this replace A = x; with A = (short)(x);
This tells the computer x is smaller than a shorts' size(A's max size). Do not do this if x can be bigger than the size of a short. Also, random numbers are ints so if you are getting a random number, you must add a cast.
Example
Code:
byte y = 0;
Random r = new Random();
y = (byte)(r.Next(1, 240));//Gives you a value between 1 and 239
When would I use this?
-When generating ores. This generates them at a random place.
-When choosing a boss attack from a list of attacks
-Many more reasons

Another example
Code:
Random r = new Random()
byte A;
A = r.Next(1, 220);//Generates a number from 1 to 119
Main.NewText(A.ToString());
Where should I put this?
This can go in any hook for example in the chat input.
More Info Coming Tomorrow :)
Also, I've only created this thread because It's typed up, so please tell me if there are any grammatical or coding errors.
Visual Studios isnt needed... It just helps
 
Due to my lack of interest in making tutorials, I've decided just to make and show pieces of code here instead.
It's come to my attention that a lot of people are asking basic c# questions on the tModLoader form and that no such tutorial answers these questions.Also, I've only created this thread because It's typed up, so please tell me if there are any grammatical or coding errors.

1.Setting up your mod
Before you even start your mod, you'll need visual studios which can be found here.
An instillation guide I recommend you use can be found here.

-You can access you mod files at C:\Users\Your User Name\Documents\My Games\Terraria\ModLoader\Mod Sources

-You can also get here by opening tmodloader, going to the build mod menu, and clicking open sources
View attachment 81636 View attachment 81637

2. Basic c#
C# is mainly made up of classes, which have methods and variables.

A few things you should know/General tips:
- If you don't have c# or can't get c#, you can open .cs files and modify them with word/notepad/any other word editing program.(Credit to @Temmie can be found at the first post)
-Statements end in a semicolon(;).

Now let's get started. In this lesson, you'll be learning about basic methods and classes.


Code:
using System;//These are using statements which are needed for methods to do things programmed into c# i.e(use Thread.Stop(1000); (stops game for 1000 milliseconds.))
using System.IO;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace Commands//This is a namespace, it is where all your project/mod's data goes.
{
     public class Comands : Mod//This is a class, or something which holds data
     {

     }
}
This goes inside an empty .cs file
Code:
    public override void SetModInfo(out string name, ref ModProperties properties)//This is a method. Make sure to add the override part unless you're calling it. We'll get into that later
    {//For every curly bracket goto hi;
        name = "Comands";//YOUR MOD NAME
        properties.Autoload = true;
        properties.AutoloadGores = true;
        properties.AutoloadSounds = true;
    }hi://There's a closing bracket

Key Points:
-Voids must go inside classes
-You only need this stuff once per mod
Finished Code:

Code:
using System;
using System.IO;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace Commands//YOUR MOD NAME
{
     public class Comands : Mod
     {

         public override void SetModInfo(out string name, ref ModProperties properties)
          {
               name = "Comands";//YOUR MOD NAME
               properties.Autoload = true;
               properties.AutoloadGores = true;
               properties.AutoloadSounds = true;
          }
     }
}
After this, create a .txt file named build(build.txt)
View attachment 81638
It should have the author, version, and name.
3. Data structures
Data structures are anything that stores data pretty simple. Data structures are different sizes, and making a data structure the right is proper technique. What do they store. They store numbers letters and objects(we'll discuss that later).
Here's a basic chart of what you can use them for.

NOTE:This is not my work and can be found here.
Code:
string : stores letters

bool : stores a value which can be true or false
Number Data structures:
sbyte -128 to 127
byte 0 to 255
short -32,768 to 32,767
ushort 0 to 65,535
int -2,147,483,648 to 2,147,483,647
uint 0 to 4,294,967,295
long -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
ulong 0 to 18,446,744,073,709,551,615
NOTE:This is not my work and can be found here.

These numbers allow you to use less data, but will cause errors if used incorrectly. When you try to move data from one type to another, be careful.
When converting data of different types use a cast.
For example
Code:
int a;

byte b;
a = 0;
b = (byte/*This comment can go inside code*/)(a);//Using the cast
///Side note:you can make comments in all these ways
More examples:
Type this code inside
Code:
public override void SetModInfo(out string name, ref ModProperties properties)
's curly brackets


This Code:
Code:
int x = 0;//Creates a number called x which is equal to 0
int y;//Creates a number called y
short A;//Creates a number called A
short C;//Creates a number called C

y = 5; //Sets y equal to 5
x = y;// Makes x equal to 5
A = x;
Did you get an error?
This is because a short and an int aren't the same. Imagine someone gives you a big cup which is full of water and tells you to stick it in a smaller cup. The computer has the same dilemma. To prevent any problems like this, the computer requires you to cast data. To do this replace A = x; with A = (short)(x);
This tells the computer x is smaller than a shorts' size(A's max size). Do not do this if x can be bigger than the size of a short. Also, random numbers are ints so if you are getting a random number, you must add a cast.
Example
Code:
byte y = 0;
Random r = new Random();
y = (byte)(r.Next(1, 240));//Gives you a value between 1 and 239
When would I use this?
-When generating ores. This generates them at a random place.
-When choosing a boss attack from a list of attacks
-Many more reasons

Another example
Code:
Random r = new Random()
byte A;
A = r.Next(1, 220);//Generates a number from 1 to 119
Main.NewText(A.ToString());
Where should I put this?
This can go in any hook for example in the chat input.
4.Loops, Statements, and advanced data structures
Now, we're going to use our knowledge to create some commands.
Start by using this code(Not my code - from the example mod)
Code:
public override void ChatInput(string text)

[SIZE=5]{

}
This code is called when chat is entered and is called a hook.
Commands, execute code i.e. Main.NewText("Hello, how are you"); can be put in here.
But what if you want to add commands? Here is some more code from the example mod which allows this.
Code:
        if(text[0] != '/')//!= means does not equal
        {
            return;//Means no more code will be executed after this
        }
        text = text.Substring(1);//makes text not have the first charter(based off number in parenthesis)
        int index = text.IndexOf(' ');//Set's an number(index) equal to the amount of the charters before a space(based off the charter in the parenthesis.)
        string command;//Creates a data structure which holds letters
        string[] args;//This is an array. This means it stores multiple strings. These strings can be referenced with args[Number in the array]
        if(index < 0)//Checks if there are more than zero spaces
        {
            command = text;
            args = new string[0];//Makes args hold 0 strings
        }
        else//If there are multiple spaces
        {
            command = text.Substring(0, index);//makes command equal to all the text before the first space
            args = text.Substring(index + 1).Split(' ');//Makes args have a new string for each space and puts that part of the text in the array
        }
Now that you have split up the command into arguments, you can use it.
Now we are going to be using an if statment. This statement does something if the criteria in the parenthesis is true.
Code:
if (command == "buff")
{
if (args.Length != 0)//Makes sure the array args has multiple arguments. This is important and prevents the computer from giving null reference exceptions.
        {
            Player player = Main.player[Main.myPlayer];//Creates an object, we'll go into this later
            for (int i = 0; i < 22; i++)//22 is max buffs // This is a for loop we'll go over this soon.
            {
                if (player.buffType[i] == 0)//Checks if a buff is active
                {
                    int j = 0;
                    if (Int32.TryParse(args[0], out j))//Checks if the players input is a number.
                    {
                        player.buffType[i] = j;//Sets the players buff type equal to the inputed number
                        player.buffTime[i] = 21384000;//Gives the buff for 99 hours
                
                        return;
                    }
                    else
                    {
                        Main.NewText("Invalid buff Id");
                        return;
                    }
                }
        
            }
            Main.NewText("You cannot have any more buffs");
        }
Main.NewText("Invalid argument");
}
Now let's look at loops. We'll start with a for loop.
Pretend you want to create a hole in the ground. All you have to do is use WorldGen.KillTile(x, y);
Now pretend you had to make a hole 2 by 4. You would have to type...
Code:
WorldGen.KillTile(x, y);
WorldGen.KillTile(x + 1, y);
WorldGen.KillTile(x + 2, y);
WorldGen.KillTile(x + 3, y);
WorldGen.KillTile(x, y+ 1);
WorldGen.KillTile(x + 1, y+ 1);
WorldGen.KillTile(x + 2, y+ 1);
WorldGen.KillTile(x + 3, y+ 1);
Now let's pretend you needed to make a 5 by 300 size hole like I do in my mod.
To do this, you'll have to type in that command 1500 times. Sounds like fun!
Instead of this, you can use something called a for loop which does all that work for you. Add this to your method - inside public override void ChatInput(string text)
Code:
for (int i = 0; i < 2000; i++)//Counts from 0 to 1999
{
Main.NewText(i);//Displays i
}
Open tModLoader, build your mod, and run it. Type in a some text. If you put this above if(text[0] != '/'){...} anything you type will cause it to write the numbers. If you put it below, you have to type '/'. Give it a shot.

More code:
As you may be able to tell, I'm getting a bit bored making this tutorial, so I'm just going to show you how to code stuff and you can follow along as you wish.
[ /spoiler]
[/SIZE]
I find this actually pretty neat, as I have already done something like this in my tutorial, which sadly is never read. Some recommendations though, you might want to add spoiler tags for your code that way it would make it less jumbled, also, check out my tutorial thing and maybe use some of it to your thingy. The things you refer to as data structures are actually just primitive data types, data structures would be something more complex such as Queues, Stacks, etc. Otherwise, I like the detail and thought put into this, I hope to see more.
 
Back
Top Bottom