Lua:Narwhal
From GMod Wiki
Go to: Narwhal |
This page needs to be edited as it contains information that is unclear or incorrect. Improvement can be discussed on the talk page. Find more pages that need work here. Details: None given. |
Lua: Narwhal Tutorial |
Description: | Details the steps to create a Narwhal Gamemode |
Original Author: | by Grea$eMonkey |
Created: | October 6, 2010 |
This tutorial requires the basic understanding of Lua.
Contents |
Tutorial #1: The basics of Narwhal
Getting Started
Narwhal is a gamemode base, so you would use it just as you would when deriving from sandbox, fretta, or base. If you have no experience in creating gamemodes, you may want to learn that before starting this tutorial.
Understanding Derivatives
If you have no understanding of gamemode derivation, this will might be very confusing to you. When you start a gamemode, you always want to set the DeriveGamemode. Deriving means that the Gamemode table of your gamemode will inherit the Gamemode table of your DeriveGamemode. So, if you derive your gamemode from sandbox, your gamemode will have the spawn menu any everything. If you derive from fretta, you will have the rounds and classes system.
One of the key benefits of Narwhal is that it can literally derive from anything. You don't even need to directly edit Narwhal. Narwhal derives from base, but some people may want to have the features from sandbox as well. That's what the NARWHAL_DERIVATIVE variable is for. It allows you to dynamically change what Narwhal derives from. This can be incredibly useful when Porting gamemodes to Narwhal. The limited number of gamemode hooks in Narwhal makes it compatible with nearly any gamemode.
Example: You have been working on an RP gamemode, but you want to use Narwhal for it's networking system. Unfortunately, you've been using sandbox as your base.
Before:
GM.Name = "My BuildRP Gamemode" GM.Author = "Grea$eMonkey" GM.Email = "[email protected]" GM.Website = "mywebsite.tld" GM.TeamBased = true DeriveGamemode( "sandbox" )
After:
NARWHAL_DERIVATIVE = "sandbox" GM.Name = "My BuildRP Gamemode" GM.Author = "Grea$eMonkey" GM.Email = "[email protected]" GM.Website = "mywebsite.tld" GM.TeamBased = true DeriveGamemode( "narwhal" )
Now you are deriving your RP gamemode from Narwhal, and Narwhal is deriving from sandbox, thus keeping all your previous sandbox-related features in addition to Narwhal's networking.
Porting
In the case that you've already started a gamemode with a gamemode base other than 'base', you'll want to read this.
There are three main things you'll want to think about when porting to Narwhal.
- Changing the derivative
- Changing to Narwhal networking
- Changing certain features to Narwhal modules
Read about porting to Narwhal here for more information.
Starting from Scratch
Congratulations, you've chosen Narwhal as your base. This means you probably won't be porting any networking or features.
First thing to think about is whether you want to set the NARWHAL_DERIVATIVE. Do you want features from Sandbox, Fretta, or some other gamemode? If you know what you're doing and you just want to derive from base, forget about NARWHAL_DERIVATIVE. Narwhal will derive from base by default.
The rest is up to you. Narwhal's key features are the optimized Networking utilities, and the Module structure.
- The networking system allows you to network more data without needing to worry about server lag. You also have more abstract datatypes that can be sent via Narwhal's Networking.
- The module system allows you to insert new features and libraries into you gamemode easily without needing to worry about conflict. It also makes team collaboration easier when used effectively.
Configuration
Now lets look at Configuring Narwhal. Narwhal comes with a table for Configuration.
This is the NARWHAL.Config table. These are the default values. They should be created in a shared setting.
Basic Configuration
These are present in all Narwhal based gamemodes.
NARWHAL.Config["UseModules"] = true -- Toggle Module Loading. NARWHAL.Config["UseThemes"] = true -- Toggle Theme Loading NARWHAL.Config["UseAnims"] = true -- Toggle the player NPC animations. NARWHAL.Config["UseMySQL"] = true -- Toggle MySQL Interfaces. NARWHAL.Config["UseCurrency"] = false -- Toggle the money system. NARWHAL.Config["UseStore"] = false -- Toggle the gobal store platform. NARWHAL.Config["UseAwards"] = false -- Toggle the achievements system.
Module Configuration
Let's say we made a module with a name of "some_module" (MODULE.Name = "some_module").
Now let's say we defined a custom configuration for it (MODULE.Config.SomeCustomVariable = true).
We can change this configuration when the module is loaded by doing this:
NARWHAL.Config.Modules["some_module"].SomeCustomVariable = false
Read about Narwhal Variables for more information.
Tutorial #2: Networking with Narwhal
Porting
Porting to Narwhal's networking is pretty simple. The main difference is the name of the entity methods.
Here's the Quick-And-Dirty way:
- Replace "SetNetworked" and "SetNW" with "SendNetworked" and "SendNW".
- Replace "GetNetworked" and "GetNW" with "FetchNetworked" and "FetchNW".
Important: You'll need to make sure you replace all pairs of Set/Get in your gamemode.
For instance, if you change from this:
Player:SetNetworkedInt( "MyInt", 1 )
To this:
Player:SendNetworkedInt( "MyInt", 1 )
But you forget to replace this:
Player:GetNetworkedInt( "MyInt" )
With this:
Player:FetchNetworkedInt( "MyInt" )
Then what happens is you send the variable with Narwhal's networking, but you try to retrieve it with GMod's networking. That will not work. Likewise, if you replace your Get's with Fetch's and forget to replace your Set's with Send's, you'll end up retrieving a variable that has not been sent yet, and probably will never be sent.
You also need to remember that Narwhal's networking utilities come with the ability to set a filter for who has access to the var. It can be a player, a table of players, a function (possibly with extra arguments) that returns a table of players, or a network enumeration that defines a function.
Read about Networking in Narwhal for more information.
Basic Sending and Fetching
Network Configurations
Tutorial #3: Module Creation
Porting
Basic Variables
There are some basic variables used to define modules. The most essential one is MODULE.Name. Your module will not register without a name. The second most important variable is MODULE.Author. The author is used to differentiate between modules in the case that one is overwriting the other. The others are just info for personal use. This info is also displayed when using the narwhal_module command.
MODULE.Name = "example_module" -- The reference name MODULE.Title = "Example Module" -- The display name MODULE.Author = "Grea$eMonkey" -- The author MODULE.Contact = "[email protected]" -- The author's contact MODULE.Purpose = "An Example." -- The purpose
Advanced Variables
MODULE.ConfigName = "UseExampleModule" -- If you add this, you can disable the module from being loaded on startup by changing NARWHAL.Config["UseExampleModule"] to false. This must be unique! MODULE.Protect = true -- Change to false if you don't want module functions pcall'd. It is recommended to not touch this. MODULE.AutoHook = true -- Change to false if you don't want your module methods with gamemode hook names to be hooked. MODULE.ManualHook = false -- Change to true if you don't want your module hooks to be automatically hooked on load.
Module Configurations
Dependencies
Dependencies allow you to encapsulate data from other modules inside your own. This lets your module interface with other modules.
To add a dependency, just add a line like these after defining your variables.
MODULE.Require( "some_module_1" ) MODULE.Require( "some_module_2" )
Sadly, due to technical limitations, it cannot use a form such as this:
local modname1 = MODULE.Require( "some_module_1" )
To get the data from your dependencies, you use MODULE:GetDependency( modName ).
function MODULE:Init() local modname1 = self:GetDependency( "some_module_1" ) modname1:DoSomething() end
Dependencies are important because they let the module loader know what needs to be in place for a module to work. If a dependency fails, the module fails.
Methods
Hooks
There are three ways to add hooks in modules. It's important to note that the hook library is invalid in Narwhal modules.
Method #1: Hooking a Function
The first way is to hook a function as you would with hook.Add
function MyInit() print("Printing in a module Initialize hook!") end MODULE:Hook( "Initialize", "MyInitHook", MyInit )
Method #2: Hooking a Method
The second method is hooking a MODULE method. This gives you access to the MODULE's self argument.
function MODULE:MyInit() print("Printing in "..self.Name.."'s Initialize hook!") end MODULE:Hook( "Initialize", "MyInitHook", MODULE.MyInit )
Method #3: Auto-Hooking
The third method is by using the autohook feature. When MODULE.AutoHook is true (it is by default), any MODULE methods that have the name of a Gamemode Hook will be automatically hooked to that gamemode hook. You also will have access to the MODULE'S self argument.
function MODULE:Initialize() print("Printing in "..self.Name.."'s Initialize AutoHook!") end