Skip to content

Commit 5ca9f71

Browse files
committed
Added os Wrapper
1 parent f508039 commit 5ca9f71

File tree

6 files changed

+195
-112
lines changed

6 files changed

+195
-112
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This emulates the basic ccTweaked functions missing in basic-lua.
77
- vector-functions
88
- settings
99
- (no validations what so ever as of yet)
10+
- os.pullEvent etc.
1011

1112
Additionally it emulates our **[scm](https://github.com/mc-cc-scripts/script-manager)** script and includes the **[json](https://gist.github.com/tylerneylon/59f4bcf316be525b30ab)** handler - which makes tests a lot easier.
1213

@@ -34,6 +35,10 @@ local scriptToTest = require("scriptToTest")
3435
-- without any need to modify the script you want to test
3536
```
3637

38+
#### os
39+
[how to test with os functions](docs/ccOS.md)
40+
41+
3742
### How to import these scripts
3843

3944
For how to import the scipts, an example is already used by this repo for some of ITS dependancies (which you will also need):

events.lua renamed to ccOS.lua

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ local class = require("ccClass")
1818
---@field thread thread
1919
---@field waiting boolean
2020

21-
---@class ccEvent
21+
---@class ccOS
2222
---@field FIFOEventList Event[]
2323
---@field TimerList timerList
2424
---@field thread thread
2525
---@field subThreads table<string, subThread>
2626
---@field time number eq. os.time("ingame") from ccTweaked)
2727
---@field epoch number eq. os.epoch("ingame") from ccTweaked)
2828
---@field private run thread
29-
local Events = class(
29+
local ccOS = class(
3030
function(baseClass)
31-
---@cast baseClass ccEvent
31+
---@cast baseClass ccOS
3232
baseClass.FIFOEventList = {}
3333
baseClass.TimerList = {timers = {}, currentID = 1}
3434
baseClass.time = 0
@@ -65,9 +65,9 @@ local Events = class(
6565
---@param wrapModule? boolean This will modify the Module!
6666
---@param ... any If loading a Module, these are the parameters
6767
---@return T|nil result if module is wrapped, it returns the wrapped module.
68-
function Events:wrap(func, wrapModule, ...)
68+
function ccOS:wrap(func, wrapModule, ...)
6969
assert(self.subThreads, "Do not use Eventclass, create an Event-Object via 'local eventObj = ccEvent()'")
70-
local manager = self
70+
local ccOSInstance = self
7171
local env = {}
7272
---@class EventOS: oslib
7373
env.os = setmetatable({
@@ -82,15 +82,31 @@ function Events:wrap(func, wrapModule, ...)
8282
return table.unpack(event)
8383
end,
8484
queueEvent = function(name, ...)
85-
manager:invoke(name, ...)
85+
ccOSInstance:invoke(name, ...)
8686
end,
8787
startTimer = function(time)
8888
assert(type(time) == "number")
89-
return manager:addTimer(time)
89+
return ccOSInstance:addTimer(time)
9090
end,
9191
cancleTimer = function(id)
92-
manager:removeTimer(id)
93-
end
92+
ccOSInstance:removeTimer(id)
93+
end,
94+
sleep = function(time)
95+
local expectedId = env.os.startTimer(time)
96+
local correctTimer = false
97+
while not correctTimer do
98+
local _, id = env.os.pullEvent("timer")
99+
correctTimer = id == expectedId
100+
end
101+
end,
102+
time = function()
103+
-- TODO: add locale
104+
return ccOSInstance.time
105+
end,
106+
epoch = function()
107+
-- TODO: add args
108+
return ccOSInstance.epoch
109+
end,
94110

95111
}, {__index = os})
96112
setmetatable(env, {__index = _G})
@@ -140,7 +156,7 @@ end
140156

141157
---@param time number seconds
142158
---@return number timerID
143-
function Events:addTimer(time)
159+
function ccOS:addTimer(time)
144160
assert(type(time) == "number" and time > 0)
145161
local triggerAfter = time * 1000 + self.epoch - 1
146162
local id = self.TimerList.currentID
@@ -149,19 +165,19 @@ function Events:addTimer(time)
149165
return id
150166
end
151167

152-
function Events:removeTimer(id)
168+
function ccOS:removeTimer(id)
153169
assert(type(id) == "number")
154170
for k,v in pairs(self.TimerList.timers) do
155171
if v.id == id then
156-
self.TimerList.currentID[id] = nil
172+
self.TimerList.timers[id] = nil
157173
end
158174
end
159175
end
160176

161177
---Passes time (in Seconds)
162178
---Required for timers
163179
---@param time number seconds
164-
function Events:passTime(time)
180+
function ccOS:passTime(time)
165181
assert(type(time) == "number")
166182
time = time * 1000
167183
self.time = (self.time + (time / 60 / 24)) % 24 -- TODO: Test
@@ -176,12 +192,12 @@ function Events:passTime(time)
176192

177193
end
178194

179-
function Events:invoke(eventName, ...)
195+
function ccOS:invoke(eventName, ...)
180196
---@type Event
181197
local event = {eventName = eventName, receivedBy = {}, eventArgs = {...}}
182198
table.insert(self.FIFOEventList, event)
183199
self.newEventAdded = true
184200
assert(coroutine.resume(self.run, "tick"))
185201
end
186202

187-
return Events
203+
return ccOS

docs/ccOS.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# OS
2+
3+
## How to use
4+
5+
### for functions
6+
```lua
7+
-- import
8+
local osEmulator = require("ccOS")
9+
10+
-- create instance
11+
local osInstance = osEmulator()
12+
13+
local testFunction = osInstance:wrap(function()
14+
os.pullEvent("CustomEvent")
15+
print("Event got called")
16+
end)
17+
18+
testFunction() -- < Programm yields until event gets invoked, in the instances' thread
19+
osInstance:invoke("CustomEvent") -- < Programm continues -> prints: "Event got called"
20+
21+
```
22+
23+
### for Modules
24+
```lua
25+
local osEmulator = require("ccOS")
26+
-- create instance
27+
local osInstance = osEmulator()
28+
29+
local moduleFile = loadfile("someModule","t")
30+
local testModule = osInstance:wrap(moduleFile, true, ...)
31+
-- <true> tells the wrapper to wrap all functioncalls, so they run in a coroutine thread, instead of the callers thread
32+
-- <...> as the module will need to be called once, you can provide additional parameters as need
33+
34+
testModule:someFunction(...)
35+
-- the function will now run on the osInstance-Thread, knowing all currently implemented os-Functions
36+
```

tests/event_spec.lua

Lines changed: 0 additions & 97 deletions
This file was deleted.

tests/os_spec.lua

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
---@class are
2+
---@field same string
3+
---@field equal string
4+
---@field equals string
5+
6+
---@class is
7+
---@field truthy string
8+
---@field falsy string
9+
---@field not_true string
10+
---@field not_false string
11+
12+
---@class has
13+
---@field error string
14+
---@field errors string
15+
16+
---@class assert
17+
---@field are are
18+
---@field is is
19+
---@field are_not are
20+
---@field is_not is
21+
---@field has has
22+
---@field has_no has
23+
---@field True string
24+
---@field False string
25+
---@field has_error string
26+
---@field is_false string
27+
---@field is_true string
28+
---@field equal string
29+
assert = assert
30+
31+
package.path = package.path .. ";"
32+
.."libs/?.lua;"
33+
34+
local osEmulator = require("ccOS")
35+
36+
describe("Event-Tests", function ()
37+
---@type ccOS, TestFile, string
38+
local osEnv, testModule, invokeWord
39+
local path = "tests/testFiles/event_testFile.lua"
40+
before_each(function()
41+
osEnv = osEmulator()
42+
end)
43+
describe("#basics", function()
44+
it("#pullAndInvokeOnFunctionOnly", function ()
45+
invokeWord = "testEvent"
46+
local testFunc = osEnv:wrap(function(parameter)
47+
assert(parameter == "parameterCheck")
48+
os.pullEvent(invokeWord)
49+
end, false)
50+
51+
testFunc("parameterCheck")
52+
assert.are.equal("suspended", coroutine.status(osEnv.thread))
53+
osEnv:invoke()
54+
assert.are.equal("suspended", coroutine.status(osEnv.thread))
55+
osEnv:invoke(invokeWord)
56+
assert.are.equal("dead", coroutine.status(osEnv.thread))
57+
end)
58+
it("#pullAndInvokeModule", function()
59+
local file = loadfile(path, "t")
60+
testModule = osEnv:wrap(file, true)
61+
assert(type(testModule)=="table", type(testModule))
62+
63+
invokeWord = "test"
64+
assert.are.equal(false, osEnv.subThreads.event1.waiting)
65+
testModule:event1(invokeWord) -- start function (runs in a thread)
66+
assert.are.equal(true, osEnv.subThreads.event1.waiting)
67+
osEnv:invoke("wrongword")
68+
assert.are.equal("suspended", coroutine.status(osEnv.subThreads.event1.thread))
69+
osEnv:invoke(invokeWord)
70+
assert.are.equal(false, osEnv.subThreads.event1.waiting)
71+
assert.are.equal(invokeWord, testModule.status.event1)
72+
end)
73+
end)
74+
describe("#timer",function()
75+
it("#start", function()
76+
local file = loadfile(path, "t")
77+
testModule = osEnv:wrap(file, true)
78+
assert(testModule)
79+
80+
testModule:event2()
81+
testModule:event2()
82+
testModule:event2()
83+
assert.are.same(1, #osEnv.TimerList.timers) -- only one timer is inserted, the pullEvent didn't trigger
84+
85+
assert.are.same(1, testModule.status.event2)
86+
osEnv:passTime(3)
87+
assert.are.same(1, testModule.status.event2)
88+
osEnv:passTime(1)
89+
assert.are.same(1, testModule.status.event2)
90+
osEnv:passTime(1)
91+
assert.are.same(nil, testModule.status.event2)
92+
osEnv:passTime(1)
93+
assert.are.same(nil, testModule.status.event2) -- the next pullEvent should never be triggered
94+
end)
95+
it("#cancel", function()
96+
local file = loadfile(path, "t")
97+
testModule = osEnv:wrap(file, true)
98+
assert(testModule)
99+
100+
testModule:event2()
101+
osEnv:removeTimer(1)
102+
osEnv:passTime(8)
103+
assert.are.same(1, testModule.status.event2)
104+
end)
105+
it("#sleep", function()
106+
local file = loadfile(path, "t")
107+
testModule = osEnv:wrap(file,true)
108+
assert(testModule)
109+
110+
testModule:event3()
111+
assert.are.same(nil, testModule.status.event3)
112+
osEnv:passTime(4)
113+
assert.are.same(nil, testModule.status.event3)
114+
osEnv:passTime(1)
115+
assert.are.same(true, testModule.status.event3)
116+
end)
117+
end)
118+
end)

0 commit comments

Comments
 (0)