Skip to content

Commit 115a971

Browse files
authored
merge: Peach 0.6.0
merge: Peach 0.6.0
2 parents 8383f5b + 201f768 commit 115a971

31 files changed

Lines changed: 1218 additions & 412 deletions

.luarc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"/**/"
2121
],
2222
"Lua.diagnostics.disable": [
23-
"duplicate-set-field"
23+
"duplicate-set-field",
24+
"invisible"
2425
],
2526
"Lua.workspace.checkThirdParty": false,
2627
"diagnostics.globals": [

README.md

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,30 @@ Each **package** is a self-contained unit — just like an addon — with built-
88

99
## Features
1010
- Modular **package-based** architecture
11-
- Built-in **dependency resolution**
11+
- Built-in **dependency managment**
12+
- Built-in configuration system with in-database saving
1213
- Flexible **OOP** utilities and core libraries
13-
- Expandable with **atomic.\*** modules (config, command, network, etc.)
14+
- Expandable with **atomic.\*** libraries (i18n, command, network, etc.)
1415
- Designed for both **addons** and **gamemodes**
1516

17+
## Examples
18+
You can quickly view [examples](./examples/README.md) of packages (addons) made on Atomic Framework to understand how it works.
19+
1620
---
1721

1822
## Documentation
1923
Full documentation, API references, and examples are available here:
20-
👉 **[Atomic Framework Wiki](https://github.com/AtomicGmod/atomic-framework/wiki)**
24+
👉 **[Atomic Framework Wiki](https://github.com/TeamMeadows/atomic-framework/wiki)**
2125

2226
---
2327

2428
## Installation
29+
Simply place the framework in your `addons/` folder.
30+
Atomic will automatically load available packages.
31+
2532
Optional dependencies:
2633
- For `atomic.mysql` → install [MySQLOO](https://github.com/FredyH/MySQLOO)
27-
- For `atomic.git` → install [gm_git](https://github.com/AtomicGmod/gm_git)
28-
29-
Simply place the framework in your `addons/` folder.
30-
Atomic will automatically load and register available packages.
34+
- For `atomic.git` → install [gm_git](https://github.com/TeamMeadows/gm_git)
3135

3236
---
3337

@@ -38,11 +42,6 @@ Discussions and proposals are also encouraged in the issue tracker.
3842

3943
---
4044

41-
## Roadmap
42-
See [To Do](#) or the project’s issue tracker for current development progress.
43-
44-
---
45-
4645
## License
4746
This project is licensed under the **GNU General Public License v3.0**.
4847
See the [LICENSE](./LICENSE) file for more details.

examples/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Examples
2+
3+
This subfolder contains drop-in packages that
4+
will show you how to work with Atomic Framework.
5+
6+
You can just drop this folder (`examples`, not `lua`) in
7+
`GarrysModDS/garrysmod/addons/`, and it will work.
8+
9+
* [Ping](./lua/atomic/packages/ping) — shows you how to work with packages, network, measure time
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---@class ExamplePackagePing: Atomic.Package
2+
local package = atomic.package.current()
3+
4+
--- this function will send
5+
--- an asynchronous network message to the server
6+
--- and wait for a response
7+
function package:ping()
8+
local instant = atomic.time.newInstant()
9+
10+
coroutine.start(function()
11+
local message = self:sendNetworkMessageAsync("Ping", {})
12+
13+
local ms = instant:elapsed():as_millis()
14+
15+
package.logger:debug("Server ping took %sms", ms)
16+
package.logger:debug("Server response: %s", message.contentz)
17+
end)
18+
end
19+
20+
--- Removing console command
21+
--- when package will disabled
22+
---
23+
--- !!! it's optional
24+
package:listen("onDisable", function()
25+
concommand.Remove("do_ping")
26+
end)
27+
28+
concommand.Add("do_ping", function()
29+
package:ping()
30+
end)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---@class ExamplePackagePing: Atomic.Package
2+
local package = atomic.package.current()
3+
4+
package:onNetworkMessage(function(message)
5+
local sender = message:getSender()
6+
7+
sender:ChatPrint("Pong!")
8+
9+
message:reply({
10+
content = "Hello from server!"
11+
})
12+
end, "Ping")
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---@class ExamplePackagePing: Atomic.Package
2+
local package = atomic.package.current()
3+
4+
--- Registering new Network Schema
5+
--- that will be visible on both sides - on client and server
6+
package:networkSchema("Ping")
7+
-- server will send to client
8+
-- field "content" with type of string
9+
:clientField("content", "string")
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---@type Atomic.Package.Metadata
2+
return {
3+
id = "team.meadows.example_ping",
4+
title = "Example package - Ping",
5+
version = "1.0.0",
6+
files = {
7+
client = { "core/client.lua" },
8+
shared = { "core/shared.lua" },
9+
server = { "core/server.lua" }
10+
}
11+
}

lua/atomic/libraries/benchmark.lua

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
atomic.benchmark = atomic.benchmark or {}
2+
3+
local Instant = atomic.time.newInstant
4+
local Duration = atomic.time.newDuration
5+
6+
---@class Atomic.BenchmarkResult
7+
---@field iterations Atomic.Time.Duration[]
8+
---@field average Atomic.Time.Duration
9+
---@field min Atomic.Time.Duration
10+
---@field max Atomic.Time.Duration
11+
12+
---@param func function
13+
---@param opts? { repeats: number, warmup: number }
14+
---@return Atomic.BenchmarkResult
15+
function atomic.benchmark.run(func, opts)
16+
opts = opts or { repeats = 1, warmup = 2 }
17+
local repeats = opts.repeats or 1
18+
local warmup = opts.warmup or 2
19+
20+
-- warmup
21+
for i = 1, warmup do
22+
func()
23+
end
24+
25+
local iterations = {}
26+
27+
-- benchmark
28+
for i = 1, repeats do
29+
local start = Instant()
30+
func()
31+
iterations[#iterations+1] = start:elapsed()
32+
end
33+
34+
-- statistic
35+
local min = iterations[1]
36+
local max = iterations[1]
37+
local sum = Duration(0, 0)
38+
39+
for i = 1, #iterations do
40+
local v = iterations[i]
41+
if v < min then min = v end
42+
if v > max then max = v end
43+
sum = sum + v
44+
end
45+
46+
local average = sum / #iterations
47+
48+
return {
49+
iterations = iterations,
50+
min = min,
51+
max = max,
52+
average = average
53+
}
54+
end

lua/atomic/libraries/class.lua

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ atomic.class = atomic.class or {
55
[atomic.meta.version] = {}
66
}
77
},
8-
9-
---@type Atomic.Package
10-
---@diagnostic disable-next-line
11-
pseudo = { id = "atomic", version = atomic.meta.version };
8+
pseudo = {
9+
_metadata = {
10+
id = "atomic",
11+
version = atomic.meta.version,
12+
documentation = "https://github.com/TeamMeadows/atomic-framework/wiki",
13+
}
14+
}
1215
}
1316

1417
---@class Atomic.Class
@@ -30,7 +33,6 @@ function atomic.class.create(name, parent)
3033
local class = setmetatable({ _name = name }, { __index = parent or classMt })
3134
class.__index = class
3235
class.__tostring = function(self)
33-
---@diagnostic disable-next-line
3436
return "instance of " .. tostring(self._name)
3537
end
3638

@@ -58,11 +60,11 @@ end
5860
---@generic T
5961
---@return T: Atomic.Class?
6062
function atomic.class.get(name, packageOrId, packageVersion)
61-
local pkgName = type(packageOrId) == "table" and packageOrId.id
63+
local pkgName = type(packageOrId) == "table" and packageOrId._metadata.id
6264
or type(packageOrId) == "string" and packageOrId
6365
or not packageOrId and "atomic"
6466

65-
local pkgVersion = type(packageOrId) == "table" and packageOrId.version
67+
local pkgVersion = type(packageOrId) == "table" and packageOrId._metadata.version
6668
or type(packageVersion) == "string" and packageVersion
6769
or pkgName == "atomic" and atomic.meta.version
6870

@@ -76,12 +78,11 @@ end
7678
--- ```
7779
---
7880
---@generic T
79-
---@param class Atomic.Class
80-
---@param tab T? Content of the instance
81-
---@vararg any
81+
---@param class T: Atomic.Class
82+
---@vararg any Arguments to be passed to the class constructor
8283
---@return T: Atomic.Class
83-
function atomic.class.new(class, tab, ...)
84-
local instance = setmetatable(tab or {}, class)
84+
function atomic.class.new(class, ...)
85+
local instance = setmetatable({}, class)
8586

8687
if (type(instance.init) == "function") then
8788
instance:init(...)
@@ -125,7 +126,7 @@ end
125126
---@param package Atomic.Package
126127
function atomic.class.register(class, package)
127128
local storage = atomic.class._storage
128-
local id, version = package.id, package.version
129+
local id, version = package._metadata.id, package._metadata.version
129130

130131
if (type(storage[id]) ~= "table") then
131132
storage[id] = {}
@@ -135,7 +136,6 @@ function atomic.class.register(class, package)
135136
storage[id][version] = {}
136137
end
137138

138-
---@diagnostic disable-next-line
139139
storage[id][version][class._name] = class
140140

141141
atomic.class._storage = storage
@@ -145,7 +145,6 @@ function atomic.class.unregister(class, package)
145145
local storage = atomic.class._storage
146146
local id, version = package.id, package.version
147147

148-
---@diagnostic disable-next-line
149148
storage[id][version][class._name] = nil
150149

151150
atomic.class._storage = storage

lua/atomic/libraries/command/class.lua

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
---@field private _arguments {[1]: string, [2]: Atomic.Command.ArgumentKind}[]
88
---@field private _execute Atomic.Command.ExecuteFunc
99
---@field private _enabled boolean Internal
10-
local command = atomic.class.create("Command")
11-
atomic.class.register(command, atomic.class.pseudo)
10+
local Command = atomic.class.create("Command")
11+
atomic.class.register(Command, atomic.class.pseudo)
1212

1313
---@param name string
1414
---@param permission string
15-
function command:init(name, permission)
15+
function Command:init(name, permission)
1616
self._name = name
1717
self._permission = permission
1818
self._arguments = {}
@@ -22,15 +22,15 @@ end
2222
---@param name string
2323
---@param kind Atomic.Command.ArgumentKind
2424
---@return self
25-
function command:argument(name, kind)
25+
function Command:argument(name, kind)
2626
self._arguments[#self._arguments + 1] = { name, kind }
2727

2828
return self
2929
end
3030

3131
---@param executable Atomic.Command.ExecuteFunc
3232
---@return self
33-
function command:onExecute(executable)
33+
function Command:onExecute(executable)
3434
self._execute = executable
3535

3636
return self
@@ -64,7 +64,7 @@ end
6464
---@private
6565
---@param executor Player
6666
---@param arguments table<string, Atomic.Command.ArgumentKind>
67-
function command:doExecute(executor, arguments)
67+
function Command:doExecute(executor, arguments)
6868
if (not self._enabled) then
6969
return
7070
end
@@ -83,7 +83,7 @@ function command:doExecute(executor, arguments)
8383
end
8484

8585
---@param b boolean
86-
function command:setEnabled(b)
86+
function Command:setEnabled(b)
8787
self._enabled = b
8888

8989
return self

0 commit comments

Comments
 (0)