add sborka
This commit is contained in:
BIN
garrysmod/gamemodes/helix/docs/banner.gif
Normal file
BIN
garrysmod/gamemodes/helix/docs/banner.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 515 KiB |
96
garrysmod/gamemodes/helix/docs/css/highlight.css
Normal file
96
garrysmod/gamemodes/helix/docs/css/highlight.css
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
|
||||
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #535346;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-subst {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-literal,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-tag .hljs-attr {
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-doctag {
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-section,
|
||||
.hljs-selector-id {
|
||||
color: #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-subst {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-type,
|
||||
.hljs-class .hljs-title {
|
||||
color: #458;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-attribute {
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-regexp,
|
||||
.hljs-link {
|
||||
color: #009926;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #990073;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-meta {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background: #fdd;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background: #dfd;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
522
garrysmod/gamemodes/helix/docs/css/ldoc.css
Normal file
522
garrysmod/gamemodes/helix/docs/css/ldoc.css
Normal file
@@ -0,0 +1,522 @@
|
||||
|
||||
:root {
|
||||
--content-width: 1200px;
|
||||
--sidebar-width: 330px;
|
||||
|
||||
--padding-big: 48px;
|
||||
--padding-normal: 24px;
|
||||
--padding-small: 16px;
|
||||
--padding-tiny: 10px;
|
||||
|
||||
--font-massive: 32px;
|
||||
--font-huge: 24px;
|
||||
--font-big: 18px;
|
||||
--font-normal: 16px;
|
||||
--font-tiny: 12px;
|
||||
|
||||
--font-style-normal: Segoe UI, Helvetica, Arial, sans-serif;
|
||||
--font-style-code: Consolas, monospace;
|
||||
|
||||
--color-accent: rgb(115, 53, 142);
|
||||
--color-accent-dark: rgb(85, 39, 105);
|
||||
--color-white: rgb(255, 255, 255);
|
||||
--color-offwhite: rgb(200, 200, 200);
|
||||
--color-white-accent: rgb(203, 190, 209);
|
||||
--color-black: rgb(0, 0, 0);
|
||||
--color-lightgrey: rgb(160, 160, 160);
|
||||
--color-background-light: rgb(240, 240, 240);
|
||||
--color-background-dark: rgb(33, 33, 33);
|
||||
}
|
||||
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--color-background-light);
|
||||
font-family: var(--font-style-normal);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
ul li {
|
||||
margin-left: var(--padding-small);
|
||||
}
|
||||
|
||||
/* landing */
|
||||
.landing {
|
||||
background-color: var(--color-accent);
|
||||
color: var(--color-white);
|
||||
|
||||
padding: 128px 0 128px 0;
|
||||
}
|
||||
|
||||
.landing h1 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
|
||||
font-weight: 100;
|
||||
font-size: var(--font-massive);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
padding: var(--padding-small);
|
||||
}
|
||||
|
||||
details {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
details summary {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: "Source Code Pro", monospace;
|
||||
font-size: 85%;
|
||||
white-space: pre;
|
||||
tab-size: 4;
|
||||
-moz-tab-size: 4;
|
||||
padding: 2px 4px;
|
||||
background-color: rgb(33, 33, 33, 0.1);
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: rgb(33, 33, 33, 0.1);
|
||||
margin-top: var(--padding-small);
|
||||
padding: var(--padding-tiny);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
pre code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
span.realm {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 3px;
|
||||
display: inline-block;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
span.realm.shared {
|
||||
background: linear-gradient(45deg, #f80 0%, #f80 50%, #08f 51%, #08f 100%);
|
||||
}
|
||||
|
||||
span.realm.client {
|
||||
background-color: #f80;
|
||||
}
|
||||
|
||||
span.realm.server {
|
||||
background-color: #08f;
|
||||
}
|
||||
|
||||
/* wrapper element for sidebar/content */
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
width: var(--content-width);
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
/* sidebar */
|
||||
nav {
|
||||
color: var(--color-offwhite);
|
||||
background-color: var(--color-background-dark);
|
||||
|
||||
position: fixed;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
width: var(--sidebar-width);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* sidebar header */
|
||||
nav header {
|
||||
color: var(--color-white);
|
||||
background-color: var(--color-accent);
|
||||
|
||||
padding: var(--padding-small);
|
||||
}
|
||||
|
||||
nav header h1 {
|
||||
font-size: var(--font-huge);
|
||||
font-weight: 100;
|
||||
text-align: center;
|
||||
|
||||
margin-bottom: var(--padding-small);
|
||||
}
|
||||
|
||||
#search {
|
||||
background-color: var(--color-accent-dark);
|
||||
color: var(--color-white);
|
||||
|
||||
border: none;
|
||||
font-size: var(--font-normal);
|
||||
outline: none;
|
||||
|
||||
width: 100%;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
#search::placeholder {
|
||||
color: var(--color-white-accent);
|
||||
}
|
||||
|
||||
#search::-webkit-search-cancel-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* sidebar contents */
|
||||
nav section {
|
||||
padding: var(--padding-small);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
nav section ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
nav section::-webkit-scrollbar,
|
||||
pre::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
nav section::-webkit-scrollbar-track,
|
||||
pre::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
nav section::-webkit-scrollbar-thumb {
|
||||
background-color: var(--color-lightgrey);
|
||||
}
|
||||
|
||||
pre::-webkit-scrollbar-thumb {
|
||||
background-color: var(--color-lightgrey);
|
||||
}
|
||||
|
||||
/* sidebar contents category */
|
||||
nav section details.category {
|
||||
padding-top: var(--padding-tiny);
|
||||
}
|
||||
|
||||
nav section details.category > ul > li {
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
nav section details.category > ul > li a {
|
||||
display: inline-block;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
nav section details.category:first-of-type {
|
||||
padding-top: calc(var(--padding-tiny) * -1);
|
||||
}
|
||||
|
||||
nav section details.category summary::-webkit-details-marker {
|
||||
opacity: 0.5;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
nav section details.category summary h2 {
|
||||
color: var(--color-accent);
|
||||
|
||||
font-size: var(--font-big);
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
|
||||
padding-bottom: var(--padding-tiny);
|
||||
}
|
||||
|
||||
/* content */
|
||||
article {
|
||||
background-color: rgb(255, 255, 255);
|
||||
|
||||
width: calc(100% - var(--sidebar-width));
|
||||
min-height: 100vh;
|
||||
margin-left: var(--sidebar-width);
|
||||
}
|
||||
|
||||
article .wrapper > *:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* header */
|
||||
article header {
|
||||
color: rgb(255, 255, 255);
|
||||
background-color: rgb(115, 53, 142);
|
||||
padding: var(--padding-tiny);
|
||||
}
|
||||
|
||||
article header h1 {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.25);
|
||||
padding-bottom: 8px;
|
||||
font-family: var(--font-style-code);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
article header h2 {
|
||||
padding-top: var(--padding-tiny);
|
||||
margin: 0;
|
||||
font-size: var(--font-normal);
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
article header.module a {
|
||||
color: white !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
details.category > summary {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
details.category > summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
article h1 {
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
|
||||
margin-top: 24px;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
article h2 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
article h3 {
|
||||
color: rgb(115, 53, 142);
|
||||
margin-top: var(--padding-tiny);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
article p {
|
||||
margin-top: var(--padding-small);
|
||||
}
|
||||
|
||||
article p a,
|
||||
article ul li a,
|
||||
article h1 a,
|
||||
article h2 a {
|
||||
color: rgb(115, 53, 142);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
article h1.title {
|
||||
color: rgb(255, 255, 255);
|
||||
background-color: rgb(115, 53, 142);
|
||||
margin-top: var(--padding-small);
|
||||
margin-bottom: 0;
|
||||
padding: var(--padding-tiny);
|
||||
|
||||
font-size: var(--font-big);
|
||||
font-weight: 100;
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
a.reference {
|
||||
color: rgb(115, 53, 142);
|
||||
float: right;
|
||||
margin-top: 8px;
|
||||
padding-left: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.notice {
|
||||
--color-notice-background: var(--color-accent);
|
||||
--color-notice-text: var(--color-notice-background);
|
||||
|
||||
margin-top: var(--padding-tiny);
|
||||
border: 2px solid var(--color-notice-background);
|
||||
}
|
||||
|
||||
.notice.error {
|
||||
--color-notice-background: rgb(194, 52, 130);
|
||||
}
|
||||
|
||||
.notice.warning {
|
||||
--color-notice-background: rgb(224, 169, 112);
|
||||
--color-notice-text: rgb(167, 104, 37);
|
||||
}
|
||||
|
||||
.notice .title {
|
||||
color: var(--color-white);
|
||||
background-color: var(--color-notice-background);
|
||||
|
||||
padding: var(--padding-tiny);
|
||||
font-size: var(--font-normal);
|
||||
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.notice p {
|
||||
color: var(--color-notice-text);
|
||||
|
||||
margin: 0 !important;
|
||||
padding: var(--padding-tiny);
|
||||
}
|
||||
|
||||
/* function/table */
|
||||
.method {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
background-color: rgb(230, 230, 230);
|
||||
padding: var(--padding-tiny);
|
||||
margin-top: var(--padding-small);
|
||||
}
|
||||
|
||||
.method header {
|
||||
color: rgb(0, 0, 0);
|
||||
background-color: inherit;
|
||||
padding: 0;
|
||||
order: -1;
|
||||
}
|
||||
|
||||
.method header .anchor {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.method header .anchor:target h1 {
|
||||
background-color: rgba(115, 53, 142, 0.2);
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
.method header h1 {
|
||||
font-family: "Source Code Pro", monospace;
|
||||
padding-bottom: var(--padding-tiny);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.method header p:first-of-type {
|
||||
margin-top: var(--padding-tiny);
|
||||
}
|
||||
|
||||
.method h3 {
|
||||
color: rgb(115, 53, 142);
|
||||
font-size: var(--font-normal);
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.method pre {
|
||||
margin-top: var(--padding-tiny);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1100px) {
|
||||
main nav {
|
||||
position: inherit;
|
||||
}
|
||||
|
||||
main article {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.method ul {
|
||||
margin-top: var(--padding-tiny);
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.method ul li {
|
||||
list-style: none;
|
||||
margin: 4px 0 0 var(--padding-normal);
|
||||
}
|
||||
|
||||
.method ul li:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.method ul li p {
|
||||
margin: 4px 0 0 var(--padding-normal);
|
||||
}
|
||||
|
||||
.method ul li pre {
|
||||
margin: 4px 0 0 var(--padding-normal);
|
||||
}
|
||||
|
||||
.method ul li a {
|
||||
color: rgb(115, 53, 142);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* we have to manually specify these instead of making a shared class since you cannot customize the parameter class in ldoc */
|
||||
.parameter, .type, .default {
|
||||
display: inline-block;
|
||||
color: rgb(255, 255, 255) !important;
|
||||
|
||||
padding: 4px;
|
||||
font-size: 14px;
|
||||
font-family: "Source Code Pro", monospace;
|
||||
}
|
||||
|
||||
.parameter {
|
||||
background-color: rgb(115, 53, 142);
|
||||
}
|
||||
|
||||
.type {
|
||||
background-color: rgb(31, 141, 155);
|
||||
}
|
||||
|
||||
a.type {
|
||||
font-weight: 300 !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.default {
|
||||
background-color: rgb(193, 114, 11);
|
||||
}
|
||||
|
||||
.type a {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.or {
|
||||
color: rgba(115, 53, 142, 0.5);
|
||||
background-color: inherit;
|
||||
|
||||
width: calc(100% - 32px);
|
||||
height: 8px;
|
||||
margin: 0 0 8px 32px;
|
||||
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid rgba(115, 53, 142, 0.5);
|
||||
}
|
||||
|
||||
.or span {
|
||||
background-color: inherit;
|
||||
padding: 0 8px 0 8px;
|
||||
}
|
||||
42
garrysmod/gamemodes/helix/docs/hooks/class.lua
Normal file
42
garrysmod/gamemodes/helix/docs/hooks/class.lua
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
-- luacheck: ignore 111
|
||||
|
||||
--[[--
|
||||
Class setup hooks.
|
||||
|
||||
As with `Faction`s, `Class`es get their own hooks for when players leave/join a class, etc. These hooks are only
|
||||
valid in class tables that are created in `schema/classes/sh_classname.lua`, and cannot be used like regular gamemode hooks.
|
||||
]]
|
||||
-- @hooks Class
|
||||
|
||||
--- Whether or not a player can switch to this class.
|
||||
-- @realm shared
|
||||
-- @player client Client that wants to switch to this class
|
||||
-- @treturn bool True if the player is allowed to switch to this class
|
||||
-- @usage function CLASS:CanSwitchTo(client)
|
||||
-- return client:IsAdmin() -- only admins allowed in this class!
|
||||
-- end
|
||||
function CanSwitchTo(client)
|
||||
end
|
||||
|
||||
--- Called when a character has left this class and has joined a different one. You can get the class the character has
|
||||
-- has joined by calling `character:GetClass()`.
|
||||
-- @realm server
|
||||
-- @player client Player who left this class
|
||||
function OnLeave(client)
|
||||
end
|
||||
|
||||
--- Called when a character has joined this class.
|
||||
-- @realm server
|
||||
-- @player client Player who has joined this class
|
||||
-- @usage function CLASS:OnSet(client)
|
||||
-- client:SetModel("models/police.mdl")
|
||||
-- end
|
||||
function OnSet(client)
|
||||
end
|
||||
|
||||
--- Called when a character in this class has spawned in the world.
|
||||
-- @realm server
|
||||
-- @player client Player that has just spawned
|
||||
function OnSpawn(client)
|
||||
end
|
||||
48
garrysmod/gamemodes/helix/docs/hooks/faction.lua
Normal file
48
garrysmod/gamemodes/helix/docs/hooks/faction.lua
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
-- luacheck: ignore 111
|
||||
|
||||
--[[--
|
||||
Faction setup hooks.
|
||||
|
||||
Factions get their own hooks that are called for various reasons, but the most common one is to set up a character
|
||||
once it's created and assigned to a certain faction. For example, giving a police faction character a weapon on creation.
|
||||
These hooks are used in faction tables that are created in `schema/factions/sh_factionname.lua` and cannot be used like
|
||||
regular gamemode hooks.
|
||||
]]
|
||||
-- @hooks Faction
|
||||
|
||||
--- Called when the default name for a character needs to be retrieved (i.e upon initial creation).
|
||||
-- @realm shared
|
||||
-- @player client Client to get the default name for
|
||||
-- @treturn string Default name for the newly created character
|
||||
-- @usage function FACTION:GetDefaultName(client)
|
||||
-- return "MPF-RCT." .. tostring(math.random(1, 99999))
|
||||
-- end
|
||||
function GetDefaultName(client)
|
||||
end
|
||||
|
||||
--- Called when a character has been initally created and assigned to this faction.
|
||||
-- @realm server
|
||||
-- @player client Client that owns the character
|
||||
-- @char character Character that has been created
|
||||
-- @usage function FACTION:OnCharacterCreated(client, character)
|
||||
-- local inventory = character:GetInventory()
|
||||
-- inventory:Add("pistol")
|
||||
-- end
|
||||
function OnCharacterCreated(client, character)
|
||||
end
|
||||
|
||||
--- Called when a character in this faction has spawned in the world.
|
||||
-- @realm server
|
||||
-- @player client Player that has just spawned
|
||||
function OnSpawn(client)
|
||||
end
|
||||
|
||||
--- Called when a player's character has been transferred to this faction.
|
||||
-- @realm server
|
||||
-- @char character Character that was transferred
|
||||
-- @usage function FACTION:OnTransferred(character)
|
||||
-- character:SetModel(self.models[1])
|
||||
-- end
|
||||
function OnTransferred(character)
|
||||
end
|
||||
1157
garrysmod/gamemodes/helix/docs/hooks/plugin.lua
Normal file
1157
garrysmod/gamemodes/helix/docs/hooks/plugin.lua
Normal file
File diff suppressed because it is too large
Load Diff
168
garrysmod/gamemodes/helix/docs/js/app.js
Normal file
168
garrysmod/gamemodes/helix/docs/js/app.js
Normal file
@@ -0,0 +1,168 @@
|
||||
|
||||
const skippedCategories = ["manual"];
|
||||
|
||||
class Node
|
||||
{
|
||||
constructor(name, element, expandable, noAutoCollapse, children = [])
|
||||
{
|
||||
this.name = name;
|
||||
this.element = element;
|
||||
this.expandable = expandable;
|
||||
this.noAutoCollapse = noAutoCollapse;
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
AddChild(name, element, expandable, noAutoCollapse, children)
|
||||
{
|
||||
let newNode = new Node(name, element, expandable, noAutoCollapse, children);
|
||||
this.children.push(newNode);
|
||||
|
||||
return newNode;
|
||||
}
|
||||
}
|
||||
|
||||
class SearchManager
|
||||
{
|
||||
constructor(input, contents)
|
||||
{
|
||||
this.input = input;
|
||||
this.input.addEventListener("input", event =>
|
||||
{
|
||||
this.OnInputUpdated(this.input.value.toLowerCase().replace(/:/g, "."));
|
||||
});
|
||||
|
||||
// setup search tree
|
||||
this.tree = new Node("", document.createElement("null"), true, true);
|
||||
this.entries = {};
|
||||
|
||||
const categoryElements = contents.querySelectorAll(".category");
|
||||
|
||||
// iterate each kind (hooks/libraries/classes/etc)
|
||||
for (const category of categoryElements)
|
||||
{
|
||||
const nameElement = category.querySelector(":scope > summary > h2");
|
||||
|
||||
if (!nameElement)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const categoryName = nameElement.textContent.trim().toLowerCase();
|
||||
|
||||
if (skippedCategories.includes(categoryName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let categoryNode = this.tree.AddChild(categoryName, category, true, true);
|
||||
const sectionElements = category.querySelectorAll(":scope > ul > li");
|
||||
|
||||
for (const section of sectionElements)
|
||||
{
|
||||
const entryElements = section.querySelectorAll(":scope > details > ul > li > a");
|
||||
const sectionName = section.querySelector(":scope > details > summary > a")
|
||||
.textContent
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
|
||||
let sectionNode = categoryNode.AddChild(sectionName, section.querySelector(":scope > details"), true);
|
||||
|
||||
for (let i = 0; i < entryElements.length; i++)
|
||||
{
|
||||
const entryElement = entryElements[i];
|
||||
const entryName = entryElement.textContent.trim().toLowerCase();
|
||||
|
||||
sectionNode.AddChild(sectionName + "." + entryName, entryElement.parentElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ResetVisibility(current)
|
||||
{
|
||||
current.element.style.display = "";
|
||||
|
||||
if (current.noAutoCollapse)
|
||||
{
|
||||
current.element.open = true;
|
||||
}
|
||||
else if (current.expandable)
|
||||
{
|
||||
current.element.open = false;
|
||||
}
|
||||
|
||||
for (let node of current.children)
|
||||
{
|
||||
this.ResetVisibility(node);
|
||||
}
|
||||
}
|
||||
|
||||
Search(input, current)
|
||||
{
|
||||
let matched = false;
|
||||
|
||||
if (current.name.indexOf(input) != -1)
|
||||
{
|
||||
matched = true;
|
||||
}
|
||||
|
||||
for (let node of current.children)
|
||||
{
|
||||
let childMatched = this.Search(input, node);
|
||||
matched = matched || childMatched;
|
||||
}
|
||||
|
||||
if (matched)
|
||||
{
|
||||
current.element.style.display = "";
|
||||
|
||||
if (current.expandable)
|
||||
{
|
||||
current.element.open = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
current.element.style.display = "none";
|
||||
|
||||
if (current.expandable)
|
||||
{
|
||||
current.element.open = false;
|
||||
}
|
||||
}
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
OnInputUpdated(input)
|
||||
{
|
||||
if (input.length <= 1)
|
||||
{
|
||||
this.ResetVisibility(this.tree);
|
||||
return;
|
||||
}
|
||||
|
||||
this.Search(input, this.tree);
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function()
|
||||
{
|
||||
const openDetails = document.querySelector(".category > ul > li > details[open]");
|
||||
|
||||
if (openDetails)
|
||||
{
|
||||
openDetails.scrollIntoView();
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function()
|
||||
{
|
||||
const searchInput = document.getElementById("search");
|
||||
const contents = document.querySelector("body > main > nav > section");
|
||||
|
||||
if (searchInput && contents)
|
||||
{
|
||||
new SearchManager(searchInput, contents);
|
||||
}
|
||||
});
|
||||
2
garrysmod/gamemodes/helix/docs/js/highlight.min.js
vendored
Normal file
2
garrysmod/gamemodes/helix/docs/js/highlight.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,329 @@
|
||||
# Clockwork to Helix Migration
|
||||
|
||||
If you are here, you probably want to be converting your code from another framework to Helix. Doing so should not be a difficult task. Most of the previous functions are probably within Helix in one form or another! This means all you need to do is match *x* function found in the old framework to *y* function in Helix. Some headings will contain a link - this will bring you to the documentation for Helix's equivalent library or class.
|
||||
|
||||
This tutorial assumes basic to intermediate knowledge and experience with Garry's Mod Lua.
|
||||
|
||||
**Before you start!** You will notice that Helix uses client for the variable that represents a player. Clockwork uses player for the variable instead, but this will conflict with the player library. So if you see `_player` being used in Clockwork, it means the Garry's Mod player library. This is just a preference and does not affect anything besides appear. So keep in mind throughout the tutorial, you may see player being used for Clockwork code and client being used for Helix code. They represent the same thing, just with a different name.
|
||||
|
||||
If you are converting Clockwork code to Helix, keep in mind that `_player` is not defined so you will need to either define `_player` yourself or switch it to player instead and change the variable name to client for player objects.
|
||||
|
||||
# Basics of Conversion
|
||||
|
||||
## Folders
|
||||
Clockwork code and file structure is not too different from Helix. In the schema, the plugins folder and schema folder stay in the same place. There are some minor differences in naming however:
|
||||
|
||||
- The `schema/entities` folder should be moved outside out of the schema folder.
|
||||
- The `libraries` folder needs to be renamed to `libs` to load.
|
||||
- The `commands` tab will not load as each command is now defined in a single shared file, does not matter which one.
|
||||
|
||||
## Deriving from Helix
|
||||
This is pretty important. If you want to use Helix as the base, you need to set it as the base. So, go to your Clockwork schema's `gamemode` folder. Inside should be two files: `init.lua `and `cl_init.lua`. Open both, and you should see something along the lines of `DeriveGamemode("Clockwork")`. Change this to `DeriveGamemode("helix")`.
|
||||
|
||||
# The Schema
|
||||
|
||||
## Introduction
|
||||
Inside of the `schema` folder of the actual schema, you should see a file named `sh_schema.lua`. This is the main schema file in both Clockwork and Helix. Most of your changes may actually be within this file.
|
||||
|
||||
## Including Files
|
||||
Both frameworks come with a utility function to include a file without worrying about sending them to the client and stuff. In Clockwork, this function is `Clockwork.kernel:IncludePrefixed("sh_myfile.lua")`. Change this to `ix.util.Include("sh_myfile.lua") `and save.
|
||||
|
||||
# The Plugin
|
||||
|
||||
## Introduction
|
||||
Plugins serve as a means to add on to a schema or framework without directly modifying either. This allows for easier modifications that can be added/removed with ease. It is recommended that you keep all custom modifications left to plugins rather than editing the framework or the schema if possible.
|
||||
|
||||
## Structure
|
||||
All plugins in Clockwork and Helix go into the `plugins` folder. However, there are many differences with the CW plugin structure. First of all, there are two things you see when you open a plugin folder: `plugin` again and `plugin.ini`.
|
||||
|
||||
Helix only has one file needed: `sh_plugin.lua` which acts like `sh_schema.lua` but for plugins.
|
||||
|
||||
## Conversion
|
||||
The first step is to move all of the contents from the `plugin` folder to the main folder of the plugin folder. The `sh_plugin.lua` file needs to be changed to provide basic information about the plugin.You need to define three things in `sh_plugin.lua` which can be found within the `plugin.ini` file:
|
||||
|
||||
- `PLUGIN.name = "Plugin Name"`
|
||||
- `PLUGIN.author = "Plugin Author"`
|
||||
- `PLUGIN.description = "Plugin Description"`
|
||||
|
||||
If the plugin uses a special variable (e.g. `cwPluginName`) for the plugin, change it to `PLUGIN`.
|
||||
|
||||
- Note that the `PLUGIN` table is removed after the plugin is loaded. So if you want to use `PLUGIN` after the plugin has loaded (such as in console commands, in entities, etc.), add `local PLUGIN = PLUGIN` at the top.
|
||||
- You can see if a global variable is defined for it by looking for `PLUGIN:SetGlobalAlias("cwMyPlugin")`. So, one would change `cwMyPlugin` to `PLUGIN`.
|
||||
|
||||
# The `Character` Object
|
||||
One main thing that is very notable is how the character is referenced using `client:GetCharacter()` which returns a character object. The way the object works is just like an entity you spawn. It has its own properties like the model, color, etc. that makes it unique. You can access all the characters in a table which stores loaded characters with `ix.char.loaded`.
|
||||
|
||||
The character object comes with many predefined methods. You can look at how they are defined [by clicking here](https://github.com/NebulousCloud/helix/blob/master/gamemode/core/meta/sh_character.lua). The character object makes it very simple to manager character information.
|
||||
|
||||
You will notice throughout the framework, the character object is used a lot. The use of the character object makes a large barrier between what belongs to the character and what belongs to the player. For example: flags, models, factions, data, and other things are stored on the character and can be accessed by the character object.
|
||||
|
||||
In Clockwork, there is no use of an object. Instead, the character information is intertwined with the player object. For example:
|
||||
|
||||
```
|
||||
-- in Clockwork
|
||||
player:SetCharacterData("foo", "bar")
|
||||
|
||||
-- in Helix
|
||||
client:GetCharacter():SetData("foo", "bar")
|
||||
```
|
||||
|
||||
The use of the character object allows you to access other characters a player might own without needing to have them be the active character, or even access them when the player is not on the server. Overall, the use of the character object may seem like a complex concept, but will simplify a lot of things once you get the hang of the idea.
|
||||
|
||||
# The Libraries
|
||||
|
||||
## Animations (`ix.anim`)
|
||||
Clockwork features many functions to set up animations for a specific model. Helix too has this functionality. Helix has one function instead that pairs a model to a specific "animation class" (grouping of animation types). So, all one needs to do is find the appropriate animation class to match the model with. Looking at the Clockwork function name should tell you.
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.animation:AddCivilProtectionModel("models/mymodel.mdl")
|
||||
|
||||
-- after
|
||||
ix.anim.SetModelClass("models/mymodel.mdl", "metrocop")
|
||||
```
|
||||
|
||||
## Attributes (`ix.attributes`)
|
||||
Attributes allow the player to boost certain abilities over time. Both frameworks require one to register attributes, but they are done differently. In Clockwork, the `ATTRIBUTE` table needs to be defined and registered manually. In Helix, the `ATTRIBUTE` table is automatically defined and registered for you. All you need to do is have `ATTRIBUTE.value = "value"`. The basic parts of the attribute needed is `ATTRIBUTE.name` and `ATTRIBUTE.description`.
|
||||
|
||||
One extra feature for attributes in Helix is `ATTRIBUTE:OnSetup(client, value)` which is a function that gets called on spawn to apply any effects. For example, the stamina attribute changes the player's run speed by adding the amount of stamina points the player has.
|
||||
|
||||
You can find an example at [https://github.com/NebulousCloud/helix/blob/master/plugins/stamina/attributes/sh_stm.lua](https://github.com/NebulousCloud/helix/blob/master/plugins/stamina/attributes/sh_stm.lua)
|
||||
|
||||
## Classes (`ix.class`)
|
||||
Classes are a part of the factions. They basically are a more specific form of a faction. Factions in Helix and Clockwork work similarly. For instance, all classes are placed in the `classes` folder under the schema folder and use `CLASS` as the main variable inside the file.
|
||||
|
||||
However:
|
||||
|
||||
- You do not need to use `local CLASS = Clockwork.class:New("My Class")`. Instead, `CLASS` is already defined for you and you set the name using `CLASS.name = "My Class"`
|
||||
- `CLASS.factions` is *not* a table, so `CLASS.factions = {FACTION_MYFACTION}` becomes `CLASS.faction = FACTION_MYFACTION`
|
||||
- You do not need to use `CLASS:Register()` as classes are registered for you after the file is done processing.
|
||||
- Classes are *optional* for factions rather than being required.
|
||||
|
||||
## Commands (`ix.command`)
|
||||
Commands no longer need to be in separate files. Instead, they are just placed into one large file. However, if you really wanted you can register multiple commands across multiple files or however you want. One thing you may notice is Clockwork uses a _COMMAND_ table while Helix does not always. It is simply a design preference. You can find examples at [https://github.com/NebulousCloud/helix/blob/master/gamemode/core/sh_commands.lua](https://github.com/NebulousCloud/helix/blob/master/gamemode/core/sh_commands.lua)
|
||||
|
||||
It should be noted that:
|
||||
|
||||
- `COMMAND.tip` is not used.
|
||||
- `COMMAND.text` is not used.
|
||||
- `COMMAND.flags` is not used.
|
||||
- `COMMAND.arguments` does not need to be defined if no arguments are needed but is defined as a table of argument types when needed `arguments = {ix.type.character, ix.type.number}`. See `ix.command.CommandArgumentsStructure` for details.
|
||||
- `COMMAND.access` for checking whether or not a person is a (super)admin can be replaced with `adminOnly = true` or `superAdminOnly = true` in the command table.
|
||||
|
||||
## Configurations (`ix.config`)
|
||||
In Helix, the method of adding configurations that can be changed by server owners is heavily simplified. [See an example here](https://github.com/NebulousCloud/helix/blob/master/gamemode/config/sh_config.lua).
|
||||
|
||||
Adding a configuration is as follows:
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.config:Add("run_speed", 225)
|
||||
|
||||
-- after
|
||||
ix.config.Add("runSpeed", 235, ...)
|
||||
```
|
||||
You'll notice that ellipses (...) were added at the end. This is because there are more arguments since adding configuration information has been placed into one function. Additionally:
|
||||
|
||||
- `Clockwork.config:ShareKey()` is not needed.
|
||||
- The 3rd argument for `Clockwork.config:AddToSystem(name, key, description, min, max)` is also the 3rd argument for `ix.config.Add`
|
||||
- The 4th argument for `ix.config.Add` is an optional function that is called when the configuration is changed.
|
||||
- The 5th argument for `ix.config.Add` is a table. You can specify the category for the configuration to group it with other configurations. There is also a data table inside which can be used to determine the minimum value and maximum value for numbers. Check out [an example here](https://github.com/NebulousCloud/helix/blob/master/gamemode/config/sh_config.lua). See also `ix.config`.
|
||||
|
||||
## Currency (`ix.currency`)
|
||||
Updating your currency code is simple:
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.config:SetKey("name_cash", "Tokens")
|
||||
Clockwork.config:SetKey("name_cash", "Dollars") -- another example
|
||||
|
||||
-- after
|
||||
ix.currency.Set("", "token", "tokens")
|
||||
ix.currency.Set("$", "dollar", "dollars")
|
||||
```
|
||||
|
||||
Note that you need to provide a symbol for that currency (€ for Euro, £ for Pound, ¥ for Yen, etc.) or just leave it as an empty string (`""`) and then provide the singular form of the name for the currency, then the plural form.
|
||||
|
||||
## Datastream
|
||||
Helix uses the [net library](http://wiki.garrysmod.com/page/Net_Library_Usage) whereas Clockwork uses datastream ([netstream](https://github.com/alexgrist/NetStream/blob/master/netstream2.lua)).
|
||||
|
||||
If you're unfamiliar with the net library, you can include the netstream library to your schema by downloading [netstream](https://github.com/alexgrist/NetStream/blob/master/netstream2.lua) to `schema/libs/thirdparty/sh_netstream2.lua` and adding `ix.util.Include("libs/thirdparty/sh_netstream2.lua")` to your `sh_schema.lua` file.
|
||||
|
||||
Starting a datastream:
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.datastream:Start(receiver, "MessageName", {1, 2, 3});
|
||||
|
||||
-- after
|
||||
netstream.Start(receiver, "MessageName", 1, 2, 3)
|
||||
```
|
||||
|
||||
Receiving a datastream:
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.datastream:Hook("MessageName", function(player, data)
|
||||
local a = data[1];
|
||||
local b = data[2];
|
||||
local c = data[3];
|
||||
|
||||
print(a, b, c);
|
||||
end);
|
||||
|
||||
-- after
|
||||
netstream.Hook("MessageName", function(client, a, b, c)
|
||||
print(a, b, c)
|
||||
end)
|
||||
```
|
||||
|
||||
## Factions (`ix.faction`)
|
||||
Factions, like classes, are pretty similar too. They share pretty much the same differences as classes in Clockwork and Helix do.
|
||||
|
||||
For instance:
|
||||
|
||||
- You do not need to use `local FACTION = Clockwork.faction:New("Name Here")`, instead `FACTION` is already defined for you and you set the name using `FACTION.name = "Name Here"`
|
||||
- `FACTION.whitelist = true` is changed to `FACTION.isDefault = false`
|
||||
- `FACTION.models` does not need a male and female part. Instead, all the models are combined into one big list.
|
||||
- `function FACTION:GetName(name)` becomes `function FACTION:GetDefaultName(name)`
|
||||
- `FACTION.description = "Describe me"` is added to the faction.
|
||||
- `FACTION_MYFACTION = FACTION:Register()` becomes `FACTION_MYFACTION = FACTION.index`
|
||||
|
||||
## Flags (`ix.flag`)
|
||||
Flags are functionally equivalent in Helix. To add a new flag:
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.flag:Add("x", "Name", "Description")
|
||||
|
||||
-- after
|
||||
ix.flag.Add("x", "Description")
|
||||
```
|
||||
|
||||
To check or manipulate a character's flag(s):
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.player:GiveFlags(player, flags)
|
||||
Clockwork.player:TakeFlags(player, flags)
|
||||
Clockwork.player:HasFlags(player, flags)
|
||||
|
||||
-- after
|
||||
client:GetCharacter():GiveFlags(flags)
|
||||
client:GetCharacter():TakeFlags(flags)
|
||||
client:GetCharacter():HasFlags(flags)
|
||||
```
|
||||
|
||||
## Inventories (`Inventory`)
|
||||
Inventories have also had a change in the way they work that may seem very different than Clockwork. Similar to how characters are their own objects, inventories become their own objects as well. These inventory objects belong to character objects, which belongs to players. So, this creates a chain of objects which is neat. The use of inventories as objects makes it very simple to attach inventories to anything.
|
||||
|
||||
To access a player's inventory, you need to use `client:GetCharacter():GetInventory()` which returns the main inventory object for the player's character. You can also access all loaded inventories with `ix.item.inventories` but that is not important right now.
|
||||
|
||||
## Items (`Item`)
|
||||
As discussed above, inventories contain items. Items are still used in inventories and world entities, use default class data, have callback functions, and can contain unique item data per instance.
|
||||
|
||||
### Setting up items
|
||||
Every time needs to be registered, or have information about it (such as the name, model, what it does, etc.) defined. In Clockwork, you have your items defined in schemas/plugins under the items folder.
|
||||
|
||||
So let's start with the differences in structure in the item file.
|
||||
|
||||
- `local ITEM = Clockwork.item:New();` is removed
|
||||
- `ITEM.uniqueID` is *completely* optional
|
||||
- Replace `ITEM.cost` with `ITEM.price`
|
||||
- `ITEM:Register()` is removed
|
||||
|
||||
### Item Sizes
|
||||
Helix's inventory uses a grid and utilizes width and height instead of weight as a means of inventory capacity. This means you will have to change your item's weight (`ITEM.weight`) to something that might be analagous to the item's size using `ITEM.width` and `ITEM.height`. The item's size must be at least one by one grid cell. It's up to you to balance the sizes of items in your use case - taking into account how many items a character might have at once, the default inventory size set in the config, etc.
|
||||
|
||||
### Item Functions
|
||||
Item functions are defined very differently than they are in Clockwork. For example:
|
||||
|
||||
```
|
||||
-- before
|
||||
function ITEM:OnUse(player, entity)
|
||||
print("My name is: " .. player:Name(), entity)
|
||||
end
|
||||
|
||||
-- after
|
||||
ITEM.functions.Use = {
|
||||
OnRun = function(item)
|
||||
print("My name is: " .. item.player, item.entity)
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
All item functions are defined in the `ITEM.functions` table. This allows the drop-down menus when using the item a lot easier and cleaner to generate dynamically. There is also more control of the icons used for the options, whether or not the function should be displayed, etc.
|
||||
|
||||
You can see an example of a water item here: [https://github.com/NebulousCloud/helix-hl2rp/blob/master/schema/items/sh_water.lua](https://github.com/NebulousCloud/helix-hl2rp/blob/master/schema/items/sh_water.lua)
|
||||
|
||||
Here, we can define what happens when the function is run, what the icon is, and what sound it plays when used. It is basically put into one area rather than being scattered among hooks and stuff.
|
||||
|
||||
### Giving/Taking Items
|
||||
So before we can give/take items, we need to understand what the *item instance* is. Using the analogy earlier about how the inventory system is like a forum, and inside the forum are posts (the items in this case), we can think of instancing an item as making a new post on a forum. So when we talk about an *item instance*, it is an item that has been created in the past. The reason we use an item instance (which is its own object too, neat!) is to make each item ever created unique. Each item instance can have its own data unique to itself.
|
||||
|
||||
Clockwork also uses an item instance system where you have to instance an item. So, to instance an item in Clockwork you would use:
|
||||
|
||||
```
|
||||
item = Clockwork.item:CreateInstance("item")
|
||||
```
|
||||
|
||||
And this would create a new instance of an item. Helix's instancing system is slightly different. Instead of having the function return the instance like it does in Clockwork, Helix relies on a callback to pass the instance. The reason for this is the item must be inserted into the database to get a unique number to represent that item. This is not done instantly, otherwise servers would freeze when new items are made. Clockwork uses the time and adds a number to get the numeric ID for an item, which allows the item to be returned which "solves" the issue, but I digress.
|
||||
|
||||
The Helix equivalent would be:
|
||||
|
||||
```
|
||||
ix.item.Instance(0, "item", data, x, y, function(item) end)
|
||||
```
|
||||
|
||||
Let's break down the differences:
|
||||
|
||||
- For Helix's item instance, the 1st argument (`0`) is the inventory that the item belongs to. You can specify 0 so it does not belong to any inventory.
|
||||
- The data argument is *optional* and is just a table for the item data.
|
||||
- *x* and *y* are the position of the items in inventory. You can find an available *x* and *y* with `inventory:FindEmptySlot()`.
|
||||
- The function is an *optional* argument that passes the item instance. This is where you can directly access the new item.
|
||||
|
||||
Keep in mind that Helix will simplify the item system for you when it can. Normally, you would not need to instance an item yourself unless you were doing something advanced.
|
||||
|
||||
So you might be wondering, how do I spawn an item in the map, and how do I give a player an item? In Clockwork, you would do the following:
|
||||
|
||||
```
|
||||
-- spawning an item in the map
|
||||
Clockwork.entity:CreateItem(player, Clockwork.item:CreateInstance("item"), Vector(1, 2, 3));
|
||||
|
||||
-- giving a player an item
|
||||
player:GiveItem(Clockwork.item:CreateInstance("item"));
|
||||
```
|
||||
|
||||
The equivalent in Helix would be:
|
||||
|
||||
```
|
||||
-- spawning an item in the map
|
||||
ix.item.Spawn("item", Vector(1, 2, 3))
|
||||
|
||||
-- giving a player an item
|
||||
client:GetCharacter():GetInventory():Add("test")
|
||||
```
|
||||
|
||||
So in these two examples, the whole deal of instancing items is done for you in Helix!
|
||||
|
||||
# Hooks
|
||||
You will need to modify the function name and arguments for your schema or plugin hooks.
|
||||
|
||||
```
|
||||
-- before
|
||||
function Schema:PlayerPlayPainSound(player, gender, damageInfo, hitGroup)
|
||||
-- ...
|
||||
end
|
||||
|
||||
-- after
|
||||
function Schema:GetPlayerPainSound(client)
|
||||
-- ...
|
||||
end
|
||||
```
|
||||
|
||||
You can see the documented hooks for the schema and plugins in the `Plugin` section.
|
||||
|
||||
# Conclusion
|
||||
Overall, most of the conversion from Clockwork to Helix is simply renaming a certain function and/or switching the order of arguments around. Both are frameworks so they function similarly.
|
||||
|
||||
You may want to use our HL2 RP schema example for reference which can be found at [https://github.com/NebulousCloud/helix-hl2rp](https://github.com/NebulousCloud/helix-hl2rp)
|
||||
75
garrysmod/gamemodes/helix/docs/manual/getting-started.md
Normal file
75
garrysmod/gamemodes/helix/docs/manual/getting-started.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Getting Started
|
||||
It's pretty easy to get started with creating your own schema with Helix. It requires a bit of bootstrapping if you're starting from scratch, but you should quickly be on your way to developing your schema after following one of the below sections in this guide.
|
||||
|
||||
# Installing the framework
|
||||
Before you start working on your schema, you'll need to install Helix onto your server. The exact instructions will vary based on your server provider, or if you're hosting the server yourself.
|
||||
|
||||
You'll need to download the framework from [GitHub](https://github.com/NebulousCloud/helix) into a folder called `helix`. This folder goes into your server's `gamemodes` folder at `garrysmod/gamemodes/helix`. That's it! The framework is now installed onto your server. Of course, you'll need to restart your server after installing the framework and a schema.
|
||||
|
||||
# MySQL usage
|
||||
By default, Helix will use SQLite (which is built into Garry's Mod) to store player/character data. This requires no configuration and will work "out of the box" after installing and will be fine for most server owners. However, you might want to connect your database to your website or use multiple servers with one database - this will require the usage of an external database accessible elsewhere. This will require the use of a MySQL server. Some server providers will provide you with a MySQL database for free to use with your server.
|
||||
|
||||
## Installing
|
||||
Helix uses the [MySQLOO](https://github.com/FredyH/MySQLOO) library to connect to MySQL databases. You'll need to follow the instructions for installing that library onto your server before continuing. In a nutshell, you need to make sure `gmsv_mysqloo_win32.dll` or `gmsv_mysqloo_linux.dll` (depending on your server's operating system) is in the `garrysmod/lua/bin` folder.
|
||||
|
||||
In older versions of MySQLOO, you previously required a .dll called `libmysql.dll` to place in your `root` server folder, where `srcds`/`srcds_linux` was stored. Newer versions of MySQLOO no longer require this.
|
||||
|
||||
## Configuring
|
||||
Now that you've installed MySQLOO, you need to tell Helix that you want to connect to an external MySQL database instead of using SQLite. This requires creating a `helix.yml` configuration file in the `garrysmod/gamemodes/helix` folder. There is an example one already made for you called `helix.example.yml` that you can copy and rename to `helix.yml`.
|
||||
|
||||
The first thing you'll need to change is the `adapter` entry so that it says `mysqloo`. Next is to change the other entries to match your database's connection information. Here is an example of what your `helix.yml` should look like:
|
||||
|
||||
```
|
||||
database:
|
||||
adapter: "mysqloo"
|
||||
hostname: "myexampledatabase.com"
|
||||
username: "myusername"
|
||||
password: "mypassword"
|
||||
database: "helix"
|
||||
port: 3306
|
||||
```
|
||||
|
||||
The `hostname` field can either be a domain name (like `myexampledatabase.com`) or an IP address (`123.123.123.123`). If you don't know what the `port` field should be, simply leave it as the default `3306`; this is the default port for MySQL database connections. The `database` field is the name of the database that you've created for Helix. Note that it does not need to be `helix`, it can be whatever you'd like.
|
||||
|
||||
Another important thing to note about this configuration file is that you **must** indent with **two spaces only**. `database` should not have any spacing before it, and all other entries must have two spaces before them. Failing to ensure this will make the configuration file fail to load.
|
||||
|
||||
# Starting with the HL2 RP schema (Basic)
|
||||
This section is for using the existing HL2 RP schema as a base for your own schema. It contains a good amount of example code if you need a stronger foundation than just a skeleton.
|
||||
|
||||
First, you'll need to download the schema from [GitHub](https://github.com/NebulousCloud/helix-hl2rp). Make sure that you download the contents of the repository into a folder called `ixhl2rp` and place it into your `garrysmod/gamemodes` folder. That's all you'll need to do to get the schema installed, other than setting your gamemode to `ixhl2rp` in the server's command line.
|
||||
|
||||
# Starting with the skeleton (Basic)
|
||||
If you don't want excess code you might not use, or prefer to build from an almost-empty foundation that covers the basic bootstrapping, then the skeleton schema is for you. The skeleton schema contains a lot of comments explaining why code is laid out in a certain way, and some other helpful tips/explanations. Make sure you give it a read!
|
||||
|
||||
You'll need to download the schema from [GitHub](https://github.com/NebulousCloud/helix-skeleton) into the folder name of your choice - just make sure it's all lowercase with no spaces. Our example for the sake of brevity will be `myschema`. Place the folder into `garrysmod/gamemodes`.
|
||||
|
||||
Next up is to modify the gamemode info so that Garry's Mod will properly recognize it. Rename `skeleton.txt` in your schema folder to your folder's name. In our example we would rename `skeleton.txt` to `myschema.txt`. Next, you'll need to modify the contents of `myschema.txt` and replace the existing information with your own - making sure to replace the `"skeleton"` at the top of the file to your folder's name. In our case we would replace it with `"myschema"`. Once you've renamed the file, you're all good to go!
|
||||
|
||||
# Converting from Clockwork (Intermediate)
|
||||
If you are looking to switch to Helix from Clockwork, you can follow the @{converting-from-clockwork|conversion guide}.
|
||||
|
||||
# Starting from scratch (Intermediate)
|
||||
You can always create the gamemode files yourself if you'd like (although we suggest the skeleton schema in general). In general, a schema is a gamemode that is derived from `helix` and automatically loads `schema/sh_schema.lua`. You shouldn't have your schema files outside of the `schema` folder. The files you'll need are as follows:
|
||||
|
||||
`gamemode/init.lua`
|
||||
```
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
DeriveGamemode("helix")
|
||||
```
|
||||
|
||||
`gamemode/cl_init.lua`
|
||||
```
|
||||
DeriveGamemode("helix")
|
||||
```
|
||||
|
||||
`schema/sh_schema.lua`
|
||||
```
|
||||
Schema.name = "My Schema"
|
||||
Schema.author = "me!"
|
||||
Schema.description = "My awesome schema."
|
||||
|
||||
-- include your other schema files
|
||||
ix.util.Include("cl_schema.lua")
|
||||
ix.util.Include("sv_schema.lua")
|
||||
-- etc.
|
||||
```
|
||||
19
garrysmod/gamemodes/helix/docs/templates/landing.ltp
vendored
Normal file
19
garrysmod/gamemodes/helix/docs/templates/landing.ltp
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
<div class="landing">
|
||||
<h1>Helix Documentation</h1>
|
||||
</div>
|
||||
|
||||
<div class="wrapper">
|
||||
<p style="text-align: center;">Welcome to the documentation for Helix - the better gamemode framework.</p>
|
||||
<h2>Developers</h2>
|
||||
<p>The sidebar shows the entire contents of the documentation. Libraries, functions, etc are all searchable with the search box at the top of the sidebar. Migrating from Clockwork? Check out the <a href="{* ldoc.url('manual/converting-from-clockwork') *}">conversion guide</a> in the manual.</p>
|
||||
<h2>Server owners</h2>
|
||||
<p>If you're looking to get your Helix server up and running as soon as possible, check out the <a href="{* ldoc.url('manual/getting-started') *}">Getting Started</a> guide in the manual.</p>
|
||||
<h2>Community</h2>
|
||||
<p>Questions? Want to show off your work? Maybe drop a new plugin release? Come join our community <a href="https://discord.gg/2AutUcF" target="_blank">Discord server</a>.</p>
|
||||
<h2>Contributing</h2>
|
||||
<p>Helix is a large project and there are still a few things missing here and there. Contributions to the documentation - from function references, to simple typo fixes - are welcomed! Check out the <code>ix.storage</code> library's <a href="https://github.com/NebulousCloud/helix/blob/master/gamemode/core/libs/sh_storage.lua" target="_blank">source code</a> for a good example on how to write documentation. You'll need a basic understanding of <a href="https://guides.github.com/features/mastering-markdown/" target="_blank">Markdown</a>, since it's used extensively to generate the markup.</p>
|
||||
<p>If you'd like to contribute code, you can visit the <a href="https://github.com/NebulousCloud/helix/" target="_blank">GitHub repository</a> and make a pull request.</p>
|
||||
<h2>Learning</h2>
|
||||
<p>Getting started on developing with the Helix framework requires an intermediate level of Garry's Mod Lua knowledge. You'll want to learn the basics before you get starting making a schema. The <a href="https://wiki.facepunch.com/gmod/" target="_blank">Garry's Mod Wiki</a> is a good place to start.</p>
|
||||
</div>
|
||||
90
garrysmod/gamemodes/helix/docs/templates/ldoc.ltp
vendored
Normal file
90
garrysmod/gamemodes/helix/docs/templates/ldoc.ltp
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
|
||||
{%
|
||||
local baseUrl = ldoc.css:gsub("ldoc.css", "")
|
||||
local repo = "https://github.com/nebulouscloud/helix/"
|
||||
local pageTitle = mod and (ldoc.display_name(mod) .. " - " .. ldoc.title) or ldoc.title
|
||||
|
||||
local oldmarkup = ldoc.markup
|
||||
function ldoc.markup(text, item)
|
||||
return oldmarkup(text, item, ldoc.plain)
|
||||
end
|
||||
|
||||
function ldoc.url(path)
|
||||
return baseUrl .. path
|
||||
end
|
||||
|
||||
function ldoc.realm_icon(realm)
|
||||
return "<span class=\"realm " .. (realm or "") .. "\"></span>";
|
||||
end
|
||||
|
||||
function ldoc.is_kind_classmethod(kind)
|
||||
return kind ~= "libraries"
|
||||
end
|
||||
|
||||
function ldoc.repo_reference(item)
|
||||
return repo .. "tree/master" .. item.file.filename:gsub(item.file.base, "/gamemode") .. "#L" .. item.lineno
|
||||
end
|
||||
|
||||
local function moduleDescription(mod)
|
||||
if (mod.type == "topic") then
|
||||
return mod.body:gsub(mod.display_name, ""):gsub("#", ""):sub(1, 256) .. "..."
|
||||
end
|
||||
|
||||
return mod.summary
|
||||
end
|
||||
%}
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>{{pageTitle}}</title>
|
||||
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="{{pageTitle}}" />
|
||||
<meta property="og:site_name" content="Helix Documentation" />
|
||||
|
||||
{% if (mod) then %}
|
||||
<meta property="og:description" content="{{moduleDescription(mod)}}" />
|
||||
{% else %}
|
||||
<meta property="og:description" content="Documentation and function reference for the Helix framework." />
|
||||
{% end %}
|
||||
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro" />
|
||||
<link rel="stylesheet" href="{* ldoc.css *}" />
|
||||
<link rel="stylesheet" href="{* ldoc.url('highlight.css') *}" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
{(docs/templates/sidebar.ltp)}
|
||||
|
||||
<article>
|
||||
{% if (ldoc.root) then -- we're rendering the landing page (index.html) %}
|
||||
{(docs/templates/landing.ltp)}
|
||||
{% elseif (ldoc.body) then -- we're rendering non-code elements %}
|
||||
<div class="wrapper">
|
||||
{* ldoc.body *}
|
||||
</div>
|
||||
{% elseif (module) then -- we're rendering libary contents %}
|
||||
<div class="wrapper">
|
||||
{(docs/templates/module.ltp)}
|
||||
</div>
|
||||
{% end %}
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<script type="text/javascript" src="{* ldoc.url('app.js') *}"></script>
|
||||
<script type="text/javascript" src="{* ldoc.url('highlight.min.js') *}"></script>
|
||||
<script type="text/javascript">
|
||||
var elements = document.querySelectorAll("pre code")
|
||||
|
||||
hljs.configure({
|
||||
languages: ["lua"]
|
||||
});
|
||||
|
||||
for (var i = 0; i < elements.length; i++)
|
||||
{
|
||||
hljs.highlightBlock(elements[i]);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
123
garrysmod/gamemodes/helix/docs/templates/module.ltp
vendored
Normal file
123
garrysmod/gamemodes/helix/docs/templates/module.ltp
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
|
||||
<header class="module">
|
||||
<h1>{{mod.name}}</h1>
|
||||
<h2>{* ldoc.markup(mod.summary) *}</h2>
|
||||
</header>
|
||||
|
||||
<p>{* ldoc.markup(mod.description) *}</p>
|
||||
|
||||
{% for kind, items in mod.kinds() do %}
|
||||
<h1 class="title">{{kind}}</h1>
|
||||
|
||||
{% for item in items() do %}
|
||||
<section class="method">
|
||||
<header>
|
||||
<a class="anchor" id="{{item.name}}">
|
||||
<h1>{* ldoc.realm_icon(item.tags.realm[1]) *}</span>{{ldoc.display_name(item)}}</h1>
|
||||
</a>
|
||||
|
||||
{% if (item.tags.internal) then %}
|
||||
<div class="notice error">
|
||||
<div class="title">Internal</div>
|
||||
<p>This is an internal function! You are able to use it, but you risk unintended side effects if used incorrectly.</p>
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{% if (item.module and item.module.type ~= "hooks") then %}
|
||||
<a class="reference" href="{* ldoc.repo_reference(item) *}">View source »</a>
|
||||
{% end %}
|
||||
|
||||
{% if (ldoc.descript(item):len() == 0) then %}
|
||||
<div class="notice warning">
|
||||
<div class="title">Incomplete</div>
|
||||
<p>Documentation for this section is incomplete and needs expanding.</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<p>{* ldoc.markup(ldoc.descript(item)) *}</p>
|
||||
{% end %}
|
||||
</header>
|
||||
|
||||
{# function arguments #}
|
||||
{% if (item.params and #item.params > 0) then %}
|
||||
{% local subnames = mod.kinds:type_of(item).subnames %}
|
||||
|
||||
{% if (subnames) then %}
|
||||
<h3>{{subnames}}</h3>
|
||||
{% end %}
|
||||
|
||||
{% for argument in ldoc.modules.iter(item.params) do %}
|
||||
{% local argument, sublist = item:subparam(argument) %}
|
||||
|
||||
<ul>
|
||||
{% for argumentName in ldoc.modules.iter(argument) do %}
|
||||
{% local displayName = item:display_name_of(argumentName) %}
|
||||
{% local type = ldoc.typename(item:type_of_param(argumentName)) %}
|
||||
{% local default = item:default_of_param(argumentName) %}
|
||||
|
||||
<li>
|
||||
<span class="tag parameter">{{displayName}}</span>
|
||||
|
||||
{% if (type ~= "") then %}
|
||||
<span class="tag">{* type *}</span>
|
||||
{% end %}
|
||||
|
||||
{% if (default and default ~= true) then %}
|
||||
<span class="tag default">default: {{default}}</span>
|
||||
{% elseif (default) then %}
|
||||
<span class="tag default">optional</span>
|
||||
{% end %}
|
||||
|
||||
<p>{* ldoc.markup(item.params.map[argumentName]) *}</p>
|
||||
</li>
|
||||
{% end %}
|
||||
</ul>
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
||||
{# function returns #}
|
||||
{% if ((not ldoc.no_return_or_parms) and item.retgroups) then %}
|
||||
{% local groups = item.retgroups %}
|
||||
|
||||
<h3>Returns</h3>
|
||||
<ul>
|
||||
{% for i, group in ldoc.ipairs(groups) do %}
|
||||
{% for returnValue in group:iter() do %}
|
||||
{% local type, ctypes = item:return_type(returnValue) %}
|
||||
{% type = ldoc.typename(type) %}
|
||||
|
||||
<li>
|
||||
{% if (type ~= "") then %}
|
||||
{* type *}
|
||||
{% else -- we'll assume that it will return a variable type if none is set %}
|
||||
<span class="tag type">any</span>
|
||||
{% end %}
|
||||
|
||||
<p>{* ldoc.markup(returnValue.text) *}</p>
|
||||
</li>
|
||||
{% end %}
|
||||
|
||||
{% if (i ~= #groups) then %}
|
||||
<div class="or"><span>OR</span></div>
|
||||
{% end %}
|
||||
{% end %}
|
||||
</ul>
|
||||
{% end %}
|
||||
|
||||
{% if (item.usage) then -- function usage %}
|
||||
<h3>Example Usage</h3>
|
||||
{% for usage in ldoc.modules.iter(item.usage) do %}
|
||||
<pre><code>{* usage *}</code></pre>
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
||||
{% if (item.see) then %}
|
||||
<h3>See Also</h3>
|
||||
<ul>
|
||||
{% for see in ldoc.modules.iter(item.see) do %}
|
||||
<li><a href="{* ldoc.href(see) *}">{{see.label}}</a></li>
|
||||
{% end %}
|
||||
</ul>
|
||||
{% end %}
|
||||
</section>
|
||||
{% end %}
|
||||
{% end %}
|
||||
69
garrysmod/gamemodes/helix/docs/templates/sidebar.ltp
vendored
Normal file
69
garrysmod/gamemodes/helix/docs/templates/sidebar.ltp
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
{%
|
||||
local function isKindExpandable(kind)
|
||||
return kind ~= "Manual"
|
||||
end
|
||||
%}
|
||||
|
||||
<nav>
|
||||
<header>
|
||||
{% if (not ldoc.root) then %}
|
||||
<h1><a href="{* ldoc.url('') *}">Helix Documentation</a></h1>
|
||||
{% end %}
|
||||
<input id="search" type="search" autocomplete="off" placeholder="Search..." />
|
||||
</header>
|
||||
|
||||
<section>
|
||||
{% for kind, mods, type in ldoc.kinds() do %}
|
||||
{% if (ldoc.allowed_in_contents(type, mod)) then %}
|
||||
<details class="category" open>
|
||||
<summary>
|
||||
<h2>{{kind}}</h2>
|
||||
</summary>
|
||||
|
||||
<ul>
|
||||
{% for currentMod in mods() do %}
|
||||
{% local name = ldoc.display_name(currentMod) %}
|
||||
<li>
|
||||
{% if (isKindExpandable(kind)) then %}
|
||||
<details {{currentMod.name == (mod or {}).name and "open" or ""}}>
|
||||
<summary><a href="{* ldoc.ref_to_module(currentMod) *}">{{name}}</a></summary>
|
||||
|
||||
<ul>
|
||||
{% else %}
|
||||
<a href="{* ldoc.ref_to_module(currentMod) *}">{{name}}</a>
|
||||
{% end %}
|
||||
|
||||
{% if (isKindExpandable(kind)) then
|
||||
currentMod.items:sort(function(a, b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
end %}
|
||||
|
||||
{% for k, v in pairs(currentMod.items) do %}
|
||||
{% if (v.kind == "functions") then %}
|
||||
<li>
|
||||
{* ldoc.realm_icon(v.tags.realm[1]) *}
|
||||
<a href="{* ldoc.ref_to_module(currentMod) *}#{{v.name}}">
|
||||
{% if (ldoc.is_kind_classmethod(currentMod.kind)) then
|
||||
echo((v.name:gsub(".+:", "")))
|
||||
else
|
||||
echo((v.name:gsub(currentMod.name .. ".", "")))
|
||||
end %}
|
||||
</a>
|
||||
</li>
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
||||
{% if (isKindExpandable(kind)) then %}
|
||||
</ul>
|
||||
</details>
|
||||
{% end %}
|
||||
</li>
|
||||
{% end %}
|
||||
</ul>
|
||||
</details>
|
||||
{% end %}
|
||||
{% end %}
|
||||
</section>
|
||||
</nav>
|
||||
Reference in New Issue
Block a user