# 🎒 Examples

***

### Creating a new class

Let's create a new class that inherits from [**BaseClass**](https://timmy.gitbook.io/classlib-1/scripting-reference/baseclass)

{% code fullWidth="false" %}

```lua
-- Creates a new Class called "Person" inheriting from BaseClass
-- and stores it in the global variable Person
Person = BaseClass.Inherit("Person")

-- You can also create a new class that inherits from an inherited class
-- Let's create an Employee class, which will inherit from Person and BaseClass
Employee = Person.Inherit("Employee") 

-- Spawn an instance of this class using the default constructor
local my_employee = Employee()

-- Destroy an instance by using the default destructor
my_employee:Destroy()
```

{% endcode %}

***

### Constructor/Destructor override

You can create your own [Constructor](https://timmy.gitbook.io/classlib-1/scripting-reference/baseclass#constructor)/[Destructor ](https://timmy.gitbook.io/classlib-1/scripting-reference/baseclass#destructor)for your classes, that will allow to control the behaviour of your class when an instance is created or destroyed

```lua
-- Here we add the class constructor, called when a new instance is created
-- We also add 2 parameters which will be used when spawning the instance
function Person:Constructor(sName, iAge)
    self:SetName(sName or "John Doe")
    self:SetAge(iAge or 18)
end

-- We can now call the constructor with the following syntax
local my_person = Person("Jane Doe", 19)

-- Here we add the class destructor
-- It'll  be called when an instance is destroyed with `my_object:Destroy()`
function Person:Destructor()
    print("Person ["..self:GetName().."] `Destructor` called")
end

-- We can also call the constructor of another class in the new class
function Employee:Constructor(sName, iAge, sJob)
    Person.Constructor(self, sName, iAge)
    self:SetJob(sJob)
end

-- `instance:Super` will return the class from which the instance class inherits
-- The example above could've been done by calling `self:Super` instead of `Person`
function Employee:Constructor(sName, iAge, sJob)
    self:Super().Constructor(self, sName, iAge)
    self:SetJob(sJob)
end
```

***

### Storing Data

You can store data on any instance, either in a classic key/value indexation\
You can also use the [`:SetValue`](https://timmy.gitbook.io/classlib-1/scripting-reference/baseclass#setvalue) and [`:GetValue`](https://timmy.gitbook.io/classlib-1/scripting-reference/baseclass#getvalue) methods, which triggers ["ValueChange"](https://timmy.gitbook.io/classlib-1/scripting-reference/baseclass#valuechange) events on the class and on the instance it's called on

```lua
local my_person = Person()

-- Let's add a value on an instance of the class
my_person.foo = "bar"

-- Accessing the key "foo" will return the value "bar
print(my_person.foo)

-- We can also use `instance:SetValue` to store the key/value
-- This will trigger "ValueChange" event on the class, and on the instance
my_person:SetValue("foo", "bar")

-- To get value assoaciated to a key, we use `instance:GetValue`
print(my_person:GetValue("foo"))
```

***

### Adding new Methods <a href="#adding-new-methods" id="adding-new-methods"></a>

Adding or overriding methods to your classes is easy, let's say we want to add a new method for **Person**, we just do that:

```lua
function Person:SetName(sName)
    if (type(sName) ~= "string") then return end
    self:SetValue("name", sName)
end
```

{% hint style="info" %}
Within your methods, you can access the called instance with `self`.
{% endhint %}

Then you can call your cool method!

```lua
local my_person = GetPersonSomehow()
my_person:SetName("John Doe")
```

***

### Local Events

It's possible to trigger local events on a class or an instance, example:

<pre class="language-lua"><code class="lang-lua">-- Subscribe and call local events on instances
local my_instance = GetInstanceSomehow()
my_instance:Subscribe("SomeEvent", function(...)
    print("Event fired!")

    -- Optionally we can return false to unsubscribe to the event after being fired
    return false
end)

my_instance:Call("SomeEvent")

-- You can also subscribe to or call events on the class itself
-- It will only be triggered on the class and won't be dispatched to instances
<strong>local callback = MyClass.ClassSubscribe("SomeEvent", function(...)
</strong>    print("Event fired!")
end)

MyClass.ClassCall("SomeEvent", ...)
MyClass.Unsubscribe("SomeEvent", callback)
</code></pre>

***

### Synchronized Classes

To synchronize instance creation/destruction on a class, you must follow these simple steps

* Define your class on the shared side, and pass `true` on the sync parameter of [Inherit](#inherit)

```lua
-- Shared
MySyncClass = BaseClass.Inherit("MySyncClass", true)
```

* After that, spawn/destroy your instances on the 🟦 [Server](https://docs.nanos.world/docs/next/core-concepts/scripting/authority-concepts) side

```lua
-- Server
local new_instance = MySyncClass()

-- Client
MySyncClass.ClassSubscribe("Spawn", function(self)
    print("New instance of the class spawned by the server!")
end)
```

***

### Network Events

It is also possible to trigger custom events on instances of your Class, using the methods [`CallRemote`](https://timmy.gitbook.io/classlib-1/scripting-reference/baseclass#callremote) or [`BroadcastRemote`](https://timmy.gitbook.io/classlib-1/scripting-reference/baseclass#broadcastremote) like in the examples above:

{% hint style="info" %}
Network events requires you to setup a synchronized class first\
Check the [Synchronized Classes ](#synchronized-classes)example before
{% endhint %}

* From Server to Client

```lua
-- Server
local my_instance = GetInstanceSomehow()
my_instance:CallRemote("CoolEvent", "foo", "bar")

-- Client
function MyClass:OnCoolEvent(arg1, arg2)
    print(arg1) -- output: "foo"
    print(arg2) -- output: "bar
end
MyClass.SubscribeRemote("CoolEvent", MyClass.OnCoolEvent)

-- or
MyClass.SubscribeRemote("CoolEvent", function(self, arg1, arg2)
end)
```

{% hint style="info" %}
When sending remote events, the first parameter will always be the instance on which the remote event is sent
{% endhint %}

* Or from Client to Server

```lua
-- Client
local my_instance = GetInstanceSomehow()
my_instance:CallRemote("CoolEvent", "foo", "bar")

-- Server
function MyClass:OnCoolEvent(player, arg1, arg2)
    print(player) -- The player who sent the event
    print(arg1) -- output: "foo"
    print(arg2) -- output: "bar
end
MyClass.SubscribeRemote("CoolEvent", MyClass.OnCoolEvent)
```

{% hint style="info" %}
When receiving network events on the server, the 2nd parameter in the callback will always be the player sending the packet
{% endhint %}

***

### Cloning Instances

You can clone instances very easily, it's doable with the [`:Clone()`](https://timmy.gitbook.io/classlib-1/scripting-reference/baseclass#clone) method

```lua
local my_instance = GetInstanceSomehow()
local new_instance = my_instance:Clone()
```

To filter the key/values that will be cloned, you can use the ignored keys parameter of [`:Clone()`](https://timmy.gitbook.io/classlib-1/scripting-reference/baseclass#clone), like how it's done in the following example:

```lua
local my_instance = GetInstanceSomehow()

-- By using the filter argument, we make the cloned instance ignore some keys to copy
local new_instance = my_instance:Clone({"health", "armor"})
```

{% hint style="info" %}
Cloning an instance will copy all the key/values of the cloned instance into the new instance, except the filtered ones, and it's ID
{% endhint %}
