1. Check out the Store if you're looking to Buy HL2RP or other schemas for your server. You can click Buy Schemas on the very top navigation bar to visit the store.
  2. Use the Plugin Center to easily subscribe to and auto-install Clockwork plugins to your server, or submit and share plugins you have developed.
  3. Having trouble setting up or developing with Clockwork? Check out the Wiki or post in the Support Forum for advice from fellow users.
Dismiss Notice
Hi Guest, you need a Steam account to register and post on these forums. Login with Steam at the top of the forums to get started!
Dismiss Notice
Hi Guest, do you want to buy HL2RP or another Clockwork schema? Visit the Cloud Sixteen Store to get started!

Important How to Make a Plugin

Discussion in 'Development' started by Vortix, Jun 23, 2015.

Thread Status:
Not open for further replies.
  1. Vortix

    Vortix Active Member

    How to make Clockwork/schema plugins
    "What do I need to get started?"
    You don't need anything to get started, except for Clockwork/a related schema. I do, however, highly recommend the Sublime Text text editor. You can download it here: http://www.sublimetext.com/. You can also download the GLua syntax highlights here: https://github.com/FPtje/Sublime-GLua-Highlight. I highly recommend it as, firstly, you can download the GLua syntax highlights, and secondly because you can use it to search multiple files at once for a bit of code, meaning you can find a function easily using it. Finally, because you can use "Find All" to select all text matching your search, and then you can replace all of those values easily, at the same time.

    "Where do I put the plugin?"
    A commonly asked question is "How do I tell whether I should put my plugin in the Clockwork plugins folder, or in the schema's plugins folder?". The answer is quite simple really: If it does anything schema specific, then put it in the schema folder. This is because Clockwork functions are different than schema functions. An example of a Clockwork function is Clockwork.player:Notify(). This can be used in any schema as it is a function that comes with the Clockwork framework. An example of a schema specific function is Schema:PlayerIsCombine(). This is schema specific as the Combine do not exist outside of the Half Life universe, meaning the function doesn't belong in the Clockwork framework.

    "How am I meant to lay out this plugin?"
    The next step is to learn how organise the plugin. For this, you should refer to @duck's guide, here: http://forums.cloudsixteen.com/threads/how-to-create-a-plugin.2114/. To simplify the whole process, you can use @RJ's plugin creator, located here: http://forums.cloudsixteen.com/threads/plugin-constructor.2765/.

    "Okay, I've read the guide, but I have some questions about it."

    So, time to answer some questions that may have arisen from @duck's guide. You may be thinking: "Why does the plugin folder's name have to be in lowercase?". The answer to this is that Linux/Unix systems do not like uppercase letters in folder/file names. If you have tried installing Valence, you will have noticed that it has an uppercase "V" in its folder name. This has been the cause of it not working on aforementioned systems if the server owner doesn't rename it to use a lowercase "v".

    Next you may be thinking: "Why do the file names start in 'sh_', 'sv_' and 'cl_'?". That is because "sh" means "shared", "sv" means "server" and "cl" means "client". Different bits of code are run in one of these three things. Shared code is run both client-side and server-side (those connected to the server are the clients). An example of client-side code is the displaying of HUDs. The server doesn't need to see the HUD, only the client does, therefore the code is ran client-side. An example of server-side code is the Clockwork.player:SetFactionRank() function. The faction rank is data that only needs to be stored server-side, as ranks are handled server-side primarily.

    Now you might be thinking "Why do I need to have a line saying 'local PLUGIN = PLUGIN;', surely all that's doing is setting PLUGIN to itself?". Well, that's what I thought initially, however the reason why it is needed is best explained by @duck: "The reason that's there is because the PLUGIN variable will be destroyed and recreated for another plugin. After all plugins have loaded, the PLUGIN variable no longer even exists, so if you don't add the code at the top, Lua will think you're trying to get a global variable called PLUGIN, but since it doesn't exist, you'll get errors. If you don't want to have to save a local copy of the PLUGIN variable, you can just do this in sh_plugin:"
    "And now you can use EXAMPLE instead of PLUGIN, and you don't need to make a local copy, as it is in the global table. Additionally, the reason why you see some plugins have only that one line in sh_plugin is because if a file is empty, it will say it doesn't exist." -duck.

    Finally, you may be wondering "Why do I have to do 'PLUGIN:PostPlayerSpawn', why can't I just use 'Schema:PostPlayerSpawn' or 'Clockwork:PostPlayerSpawn'?". Well, the reason for this is that Clockwork:PostPlayerSpawn and Schema:PostPlayerSpawn already exist, therefore by using one of those you'll override the function that already exists, which is bad as it will mean code that should run won't, and will be replaced by your code. "Okay, but the Clockwork function is stopping my code from working! Should I override it and put all the code from the Clockwork function after my code?". Well, here's another quote from @duck: "You could just do:"
    local PlayerIsCombine = Schema.PlayerIsCombine;
    function Schema:PlayerIsCombine(player)
        if (player:GetCharacterData("PhantomUndercover")) then
             return false;
        return PlayerIsCombine(Schema, player);
    "and it can interact with plugins".
    What's happening here is that you've saved the Schema's PlayerIsCombine function in the PlayerIsCombine variable before you've overridden the function. Therefore, when you override the function and put your code in, you don't need to paste all of the old code back in, you just need to put in a call to the old function - stored in the PlayerIsCombine variable.

    "Okay, I think I've gotten my head around working with plugins. One issue, though... I don't know any Lua, or GLua."

    Everyone starts somewhere. There are a few ways you can approach learning: You can use Google. Search up and learn how to code in Lua. Otherwise, you could start downloading other peoples' plugins and try to learn from what they do. You can visit this page for a list of all things GLua: http://wiki.garrysmod.com/. If you took my advice at the start of the guide, you will have Sublime Text with which you can search up different functions quickly and see how they work - however I will go more into learning about Clockwork functions in the next section.


    Now you might be thinking: "Okay, I've learnt how to use Lua and GLua, but how do I get started learning how to use Clockwork?". Well, as well as learning from others, you can use libraries. Libraries are sort of like sections where you can find all code relating to a certain thing. So, if you're looking for specific functions relating to voices, then take a look at the voices library. Functions relating to players? Player library. The libraries folder is also split up: Inside it there are files, as well as a "server" and "client" directory. The files directly inside the "libraries" folder are shared. There are sometimes multiple instances of a library, where there is some client-side code, some server-side code, and some shared code. Libraries follow a pattern, so all functions from the player library will be named Clockwork.player:FunctionName

    You may now be thinking "Where are the panels, then, and how to I make/modify one?". First of all, we refer to these panels as derma. If you're looking for the derma, then you simply have to check the derma folder in the Clockwork framework directory! There you can see all the files for the derma, such as the business menu.

    As you may have noticed, the files run clientside. This is true for all derma. This means that if you want the derma to be opened through a serverside trigger, you'll have to use something called the Net/Datastream library

    Net/Datastream library
    So what is this, and why is it relevant? Well, in Garry's Mod the Net library is what you can use to send data between the client and server, and vice versa. It is incredibly useful for plenty of things, such as triggering a derma menu to open through a serverside trigger, despite the fact that derma is clientside. The Datastream library is Clockwork's use of the Net library. You can read up on these things outside of this guide, however I felt it was important to know about this and how useful it can be.

    "self" is quite simple to get your head around. "self" only works in functions, and it represents where the function is coming from. By this I mean that if you have the following:
    function Clockwork:Intialize() end;
    Then in this instance "self" within the function would represent "Clockwork". In Clockwork.player:GetFactionRank() then "self" would represent Clockwork.player. It is basically what comes before the colon in the function.


    Metatables are extremely useful. They're what allow you to do something like "player:GetCharacterData()", where part of the input is before the colon. You can't, however, just decide to do:
    function playerMeta:GetCharacterData(data)
    First of all you need to make playerMeta mean something, so first do:
    local playerMeta = FindMetaTable("Player");
    You might be thinking: Okay, so the input is before the colon, but how do I get the input? Well, if you're thinking that, re-read the last section! In my above example of a playerMeta function, "self" would represent the player input.

    So, there's my best attempt at teaching those interested how to get started. Feel free to add me if you want help with anything: http://steamcommunity.com/id/tka-vortix. PM me on the forums before adding me so I know you're from here.
    • Winner Winner x 4
    • Informative Informative x 1
    Last edited: Aug 8, 2015

Previous Readers (Total: 0)

Thread Status:
Not open for further replies.