diff --git a/mulit/.gitignore b/mulit/.gitignore deleted file mode 100644 index c11b7e0..0000000 --- a/mulit/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ - -test.lua -test2.lua diff --git a/mulit/LICENSE b/mulit/LICENSE deleted file mode 100644 index a21d570..0000000 --- a/mulit/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Ryan Ward - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/mulit/README.html b/mulit/README.html deleted file mode 100644 index b55c552..0000000 --- a/mulit/README.html +++ /dev/null @@ -1,1853 +0,0 @@ - - - - - README.html - - - - - - -

multi Version: 1.8.6 (System Threaded Job Queues gets an update!)

In Changes you’ll find documentation for(In Order):

My multitasking library for lua. It is a pure lua binding if you ingore the integrations and the love2d compat. If you find any bugs or have any issues please let me know :). If you don’t see a table of contents try using the ReadMe.html file. It is eaiser to navigate the readme

-

INSTALLING

To install copy the multi folder into your enviroment and you are good to go

or use luarocks

luarocks install multi
-

Discord

For real-time assistance with my libraries! A place where you can ask questions and get help with any of my libraries. Also you can request features and stuff there as well.

https://discord.gg/U8UspuA

Planned features/TODO

Known Bugs/Issues

In regards to integrations, thread cancellation works slightly different for love2d and lanes. Within love2d I was unable to (To lazy to…) not use the multi library within the thread. A fix for this is to call multi:Stop() when you are done with your threaded code! This may change however if I find a way to work around this. In love2d in order to mimic the GLOBAL table I needed the library to constantly sync tha data… You can use the sThread.waitFor(varname), or sThread.hold(func) methods to sync the globals, to get the value instead of using GLOBAL and this could work. If you want to go this route I suggest setting multi.isRunning=true to prevent the auto runner from doing its thing! This will make the multi manager no longer function, but thats the point :P

Another bug concerns the SystemThreadedJobQueue, Only 1 can be used for now… Creating more may not be a good idea.

And systemThreadedTables only supports 1 table between the main and worker thread! They do not work when shared between 2 or more threads. If you need that much flexiblity ust the GLOBAL table that all threads have.

For module creators using this library. I suggest using SystemThreadedQueues for data transfer instead of SystemThreadedTables for rapid data transfer, If you plan on having Constants that will always be the same then a table is a good idea! They support up to n threads and can be messed with and abused as much as you want :D

Love2D SystemThreadedTAbles do not send love2d userdata, use queues instead for that!

Usage:

-- Basic usage Alarms: Have been moved to the core of the library require("multi") would work as well
-require("multi") -- gets the entire library
-alarm=multi:newAlarm(3) -- in seconds can go to .001 uses the built in os.clock()
-alarm:OnRing(function(a)
-  print("3 Seconds have passed!")
-  a:Reset(n) -- if n were nil it will reset back to 3, or it would reset to n seconds
-end)
-multi:mainloop() -- the main loop of the program, multi:umanager() exists as well to allow integration in other loops Ex: love2d love.update function. More on this binding in the wiki!
-

The library is modular so you only need to require what you need to. Because of this, the global enviroment is altered

There are many useful objects that you can use

Check out the wiki for detailed usage, but here are the objects:

Examples of each object being used

We already showed alarms in action so lets move on to a Loop object

Throughout these examples I am going to do some strange things in order to show other features of the library!

LOOPS

-- Loops: Have been moved to the core of the library require("multi") would work as well
-require("multi") -- gets the entire library
-count=0
-loop=multi:newLoop(function(self,dt) -- dt is delta time and self is a reference to itself
-  count=count+1
-  if count > 10 then
-    self:Break() -- All methods on the multi objects are upper camel case, where as methods on the multi or process/queuer namespace are lower camel case
-    -- self:Break() will stop the loop and trigger the OnBreak(func) method
-    -- Stopping is the act of Pausing and deactivating the object! All objects can have the multiobj:Break() command on it!
-  else
-    print("Loop #"..count.."!")
-  end
-end)
-loop:OnBreak(function(self)
-  print("You broke me :(")
-end)
-multi:mainloop()
-

Output

Loop #1!

Loop #2!

Loop #3!

Loop #4!

Loop #5!

Loop #6!

Loop #7!

Loop #8!

Loop #9!

Loop #10!

You broke me :(

With loops out of the way lets go down the line

This library aims to be Async like. In reality everything is still on one thread unless you are using the lanes integration module WIP (More on that later)

EVENTS

-- Events, these were the first objects introduced into the library. I seldomly use them in their pure form though, but later on you'll see their advance uses!
--- Events on there own don't really do much... We are going to need 2 objects at least to get something going
-require("multi") -- gets the entire library
-count=0
--- lets use the loop again to add to count!
-loop=multi:newLoop(function(self,dt)
-  count=count+1
-end)
-event=multi:newEvent(function() return count==100 end) -- set the event
-event:OnEvent(function(self) -- connect to the event object
-  loop:Pause() -- pauses the loop from running!
-  print("Stopped that loop!")
-end) -- events like alarms need to be reset the Reset() command works here as well
-multi:mainloop()
-

Output

Stopped that loop!

STEPS

require("multi")
--- Steps, are like for loops but non blocking... You can run a loop to infintity and everything will still run I will combine Steps with Ranges in this example.
-step1=multi:newStep(1,10,1,0) -- Some explaining is due. Argument 1 is the Start # Argument 2 is the ResetAt # (inclusive) Argument 3 is the count # (in our case we are counting by +1, this can be -1 but you need to adjust your start and resetAt numbers)
--- The 4th Argument is for skipping. This is useful for timing and for basic priority management. A priority management system is included!
-step2=multi:newStep(10,1,-1,1) -- a second step, notice the slight changes!
-step1:OnStart(function(self)
-  print("Step Started!")
-end)
-step1:OnStep(function(self,pos)
-  if pos<=10 then -- what what is this? the step only goes to 10!!!
-    print("Stepping... "..pos)
-   else
-    print("How did I get here?")
-   end
-end)
-step1:OnEnd(function(self)
-  print("Done!")
-  -- We finished here, but I feel like we could have reused this step in some way... Yeah I soule Reset() it, but what if i wanted to change it...
-  if self.endAt==10 then -- lets only loop once
-    self:Update(1,11,1,0) -- oh now we can reach that else condition!
-  end
-  -- Note Update() will restart the step!
-end)
-
--- step2 is bored lets give it some love :P
-step2.range=step2:newRange() -- Set up a range object to have a nested step in a sense! Each nest requires a new range
--- it is in your interest not to share ranges between objects! You can however do it if it suits your needs though
-step2:OnStep(function(self,pos)
-  -- for 1=1,math.huge do
-    --  print("Haha I am holding the code up because I can!!!")
-  --end
-  -- We dont want to hold things up, but we want to nest.
-  -- Note a range is not nessary if the nested for loop has a small range, if however the range is rather large you may want to allow other objects to do some work
-  for i in self.range(1,100) do
-    print(pos,i) -- Now our nested for loop is using a range object which allows for other objects to get some cpu time while this one is running
-  end
-end)
--- TSteps are just like alarms and steps mixed together, the only difference in construction is the 4th Argument. On a TStep that argument controls time. The defualt is 1
--- The Reset(n) works just like you would figure!
-step3=multi:newTStep(1,10,.5,2) -- lets go from 1 to 10 counting by .5 every 2 seconds
-step3:OnStep(function(self,pos)
-  print("Ok "..pos.."!")
-end)
-multi:mainloop()
-

Output

Note: the output on this one is huge!!! So I had to … some parts! You need to run this for your self to see what is going on!

Step Started!

Stepping… 1

10 1

Stepping… 2

10 2

Stepping… 3

10 3



Ok 9.5!

Ok 10!

TLOOPS

require("multi")
--- TLoops are loops that run ever n second. We will also look at condition objects as well
--- Here we are going to modify the old loop to be a little different
-count=0
-loop=multi:newTLoop(function(self) -- We are only going to coult with this loop, but doing so using a condition!
-  while self:condition(self.cond) do
-    count=count+1
-  end
-  print("Count is "..count.."!")
-  self:Destroy() -- Lets destroy this object, casting it to the dark abyss MUHAHAHA!!!
-  -- the reference to this object will be a phantom object that does nothing!
-end,1) -- Notice the ',1' after the function! This is where you put your time value!
-loop.cond=multi:newCondition(function() return count<=100 end) -- conditions need a bit of work before i am happy with them
-multi:mainloop()
-

Output

Count is 101!

Connections

These are my favorite objects and you’ll see why. They are very useful objects for ASync connections!

require("multi")
--- Lets create the events
-yawn={} -- ill just leave that there
-OnCustomSafeEvent=multi:newConnection(true) -- lets pcall the calls incase something goes wrong defualt
-OnCustomEvent=multi:newConnection(false) -- lets not pcall the calls and let errors happen... We are good at coding though so lets get a speed advantage by not pcalling. Pcalling is useful for plugins and stuff that may have been coded badly and you can ingore those connections if need be.
-OnCustomEvent:Bind(yawn) -- create the connection lookup data in yawn
-
--- Lets connect to them, a recent update adds a nice syntax to connect to these
-cd1=OnCustomSafeEvent:Connect(function(arg1,arg2,...)
-  print("CSE1",arg1,arg2,...)
-end,"bob") -- lets give this connection a name
-cd2=OnCustomSafeEvent:Connect(function(arg1,arg2,...)
-  print("CSE2",arg1,arg2,...)
-end,"joe") -- lets give this connection a name
-cd3=OnCustomSafeEvent:Connect(function(arg1,arg2,...)
-  print("CSE3",arg1,arg2,...)
-end) -- lets not give this connection a name
-
--- no need for connect, but I kept that function because of backwards compatibility.
-OnCustomEvent(function(arg1,arg2,...)
-  print(arg1,arg2,...)
-end)
-
--- Now within some loop/other object you trigger the connection like
-OnCustomEvent:Fire(1,2,"Hello!!!") -- fire all conections
-
--- You may have noticed that some events have names! See the following example!
-OnCustomSafeEvent:getConnection("bob"):Fire(1,100,"Bye!") -- fire only bob!
-OnCustomSafeEvent:getConnection("joe"):Fire(1,100,"Hello!") -- fire only joe!!
-OnCustomSafeEvent:Fire(1,100,"Hi Ya Folks!!!") -- fire them all!!!
-
--- Connections have more to them than that though!
--- As seen above cd1-cd3 these are hooks to the connection object. This allows you to remove a connection
--- For Example:
-cd1:Remove() -- remove this connection from the master connection object
-print("------")
-OnCustomSafeEvent:Fire(1,100,"Hi Ya Folks!!!") -- fire them all again!!!
--- To remove all connections use:
-OnCustomSafeEvent:Remove()
-print("------")
-OnCustomSafeEvent:Fire(1,100,"Hi Ya Folks!!!") -- fire them all again!!!
-

Output

1 2 Hello!!!

CSE1 1 100 Bye!

CSE2 1 100 Hello!

CSE1 1 100 Hi Ya Folks!!!

CSE2 1 100 Hi Ya Folks!!!

CSE3 1 100 Hi Ya Folks!!!

CSE2 1 100 Hi Ya Folks!!!

CSE3 1 100 Hi Ya Folks!!!


You may think timers should be bundled with alarms, but they are a bit different and have cool features

TIMERS

-- You see the thing is that all time based objects use timers eg. Alarms, TSteps, and Loops. Timers are more low level!
-require("multi")
-local clock = os.clock
-function sleep(n)  -- seconds
-  local t0 = clock()
-  while clock() - t0 <= n do end
-end -- we will use this later!
-
-timer=multi:newTimer()
-timer:Start()
--- lets do a mock alarm
-set=3 -- 3 seconds
-a=0
-while timer:Get()<=set do
-  -- waiting...
-  a=a+1
-end
-print(set.." second(s) have passed!")
--- Timers can do one more thing that is interesting and that is pausing them!
-timer:Pause()
-print(timer:Get()) -- should be really close to 'set'
-sleep(3)
-print(timer:Get()) -- should be really close to 'set'
-timer:Resume()
-sleep(1)
-print(timer:Get()) -- should be really close to the value of set + 1
-timer:Pause()
-print(timer:Get()) -- should be really close to 'set'
-sleep(3)
-print(timer:Get()) -- should be really close to 'set'
-timer:Resume()
-sleep(1)
-print(timer:Get()) -- should be really close to the value of set + 2
-

Output

Note: This will make more sense when you run it for your self

3 second(s) have passed!

3.001

3.001

4.002

4.002

4.002

5.003

UPDATER

-- Updaters: Have been moved to the core of the library require("multi") would work as well
-require("multi")
-updater=multi:newUpdater(5) -- really simple, think of a look with the skip feature of a step
-updater:OnUpdate(function(self)
-  --print("updating...")
-end)
--- Here every 5 steps the updater will do stuff!
--- But I feel it is now time to touch into priority management, so lets get into basic priority stuff and get into a more advance version of it
---[[
-multi.Priority_Core -- Highest form of priority
-multi.Priority_High
-multi.Priority_Above_Normal
-multi.Priority_Normal -- The defualt form of priority
-multi.Priority_Below_Normal
-multi.Priority_Low
-multi.Priority_Idle -- Lowest form of priority
-
-Note: These only take effect when you enable priority, otherwise everything is at a core like level!
-We aren't going to use regular objects to test priority, but rather benchmarks!
-to set priority on an object though you would do
-multiobj:setPriority(one of the above)
-]]
--- lets bench for 3 seconds using the 3 forms of priority! First no Priority
-multi:benchMark(3,nil,"Regular Bench: "):OnBench(function() -- the onbench() allows us to do each bench after each other!
-  print("P1\n---------------")
-  multi:enablePriority()
-  multi:benchMark(3,multi.Priority_Core,"Core:")
-  multi:benchMark(3,multi.Priority_High,"High:")
-  multi:benchMark(3,multi.Priority_Above_Normal,"Above_Normal:")
-  multi:benchMark(3,multi.Priority_Normal,"Normal:")
-  multi:benchMark(3,multi.Priority_Below_Normal,"Below_Normal:")
-  multi:benchMark(3,multi.Priority_Low,"Low:")
-  multi:benchMark(3,multi.Priority_Idle,"Idle:"):OnBench(function()
-    print("P2\n---------------")
-    -- Finally the 3rd form
-    multi:enablePriority2()
-    multi:benchMark(3,multi.Priority_Core,"Core:")
-    multi:benchMark(3,multi.Priority_High,"High:")
-    multi:benchMark(3,multi.Priority_Above_Normal,"Above_Normal:")
-    multi:benchMark(3,multi.Priority_Normal,"Normal:")
-    multi:benchMark(3,multi.Priority_Below_Normal,"Below_Normal:")
-    multi:benchMark(3,multi.Priority_Low,"Low:")
-    multi:benchMark(3,multi.Priority_Idle,"Idle:")
-  end)
-end)
-multi:mainloop() -- Notice how the past few examples did not need this, well only actors need to be in a loop! More on this in the wiki.
-

Output

Note: These numbers will vary drastically depending on your compiler and cpu power

Regular Bench: 2094137 Steps in 3 second(s)!

P1

Below_Normal: 236022 Steps in 3 second(s)!

Normal: 314697 Steps in 3 second(s)!

Above_Normal: 393372 Steps in 3 second(s)!

High: 472047 Steps in 3 second(s)!

Core: 550722 Steps in 3 second(s)!

Low: 157348 Steps in 3 second(s)!

Idle: 78674 Steps in 3 second(s)!

P2

Core: 994664 Steps in 3 second(s)!

High: 248666 Steps in 3 second(s)!

Above_Normal: 62166 Steps in 3 second(s)!

Normal: 15541 Steps in 3 second(s)!

Below_Normal: 3885 Steps in 3 second(s)!

Idle: 242 Steps in 3 second(s)!

Low: 971 Steps in 3 second(s)!

Notice: Even though I started each bench at the same time the order that they finished differed the order is likely to vary on your machine as well!

Processes

A process allows you to group the Actor objects within a controlable interface

require("multi")
-proc=multi:newProcess() -- takes an optional file as an argument, but for this example we aren't going to use that
--- a process works just like the multi object!
-b=0
-loop=proc:newTLoop(function(self)
-    a=a+1
-    proc:Pause() -- pauses the cpu cycler for this processor! Individual objects are not paused, however because they aren't getting cpu time they act as if they were paused
-end,.1)
-updater=proc:newUpdater(multi.Priority_Idle) -- priority can be used in skip arguments as well to manage priority without enabling it!
-updater:OnUpdate(function(self)
-    b=b+1
-end)
-a=0 -- a counter
-loop2=proc:newLoop(function(self,dt)
-    print("Lets Go!")
-    self:hold(3) -- this will keep this object from doing anything! Note: You can only have one hold active at a time! Multiple are possible, but results may not be as they seem see * for how hold works
-    -- Within a process using hold will keep it alive until the hold is satisified!
-    print("Done being held for 1 second")
-    self:hold(function() return a>10 end)
-    print("A is now: "..a.." b is also: "..b)
-    self:Destroy()
-    self.Parent:Pause() -- lets say you don't have the reference to the process!
-    os.exit()
-end)
--- Notice this is now being created on the multi namespace
-event=multi:newEvent(function() return os.clock()>=1 end)
-event:OnEvent(function(self)
-    proc:Resume()
-    self:Destroy()
-end)
-proc:Start()
-multi:mainloop()
-

Output

Lets Go!

Done being held for 1 second

A is now: 29 b is also: 479

Hold: This method works as follows

function multi:hold(task)
-    self:Pause() -- pause the current object
-    self.held=true -- set held
-    if type(task)=='number' then -- a sleep cmd
-        local timer=multi:newTimer()
-        timer:Start()
-        while timer:Get()<task do -- This while loop is what makes using multiple holds tricky... If the outer while is good before the nested one then the outter one will have to wait! There is a way around this though!
-            if love then
-                self.Parent:lManager()
-            else
-                self.Parent:Do_Order()
-            end
-        end
-        self:Resume()
-        self.held=false
-    elseif type(task)=='function' then
-        local env=self.Parent:newEvent(task)
-        env:OnEvent(function(envt) envt:Pause() envt.Active=false end)
-        while env.Active do
-            if love then
-                self.Parent:lManager()
-            else
-                self.Parent:Do_Order()
-            end
-        end
-        env:Destroy()
-        self:Resume()
-        self.held=false
-    else
-        print('Error Data Type!!!')
-    end
-end
-

Queuer (WIP)

A queuer works just like a process however objects are processed in order that they were created…

require("multi")
-queue = multi:newQueuer()
-queue:newAlarm(3):OnRing(function()
-    print("Ring ring!!!")
-end)
-queue:newStep(1,10):OnStep(function(self,pos)
-    print(pos)
-end)
-queue:newLoop(function(self,dt)
-    if dt==3 then
-        self:Break()
-        print("Done")
-    end
-end)
-queue:Start()
-multi:mainloop()
-

Expected Output

Note: the queuer still does not work as expected!

Ring ring!!!

1

2

3

4

5

6

7

8

9

10

Done

Actual Output

Done

1

2

3

4

5

6

7

8

9

10

Ring ring!!!

Threads

These fix the hold problem that you get with regular objects, and they work exactly the same! They even have some extra features that make them really useful.

require("multi")
-test=multi:newThreadedProcess("main") -- you can thread processors and all Actors see note for a list of actors you can thread!
-test2=multi:newThreadedProcess("main2")
-count=0
-test:newLoop(function(self,dt)
-    count=count+1
-    thread.sleep(.01)
-end)
-test2:newLoop(function(self,dt)
-    print("Hello!")
-    thread.sleep(1) -- sleep for some time
-end)
--- threads take a name object then the rest as normal
-step=multi:newThreadedTStep("step",1,10)
-step:OnStep(function(self,p)
-    print("step",p)
-    thread.skip(21) -- skip n cycles
-end)
-step:OnEnd(function()
-    print("Killing thread!")
-    thread.kill() -- kill the thread
-end)
-loop=multi:newThreadedLoop("loop",function(self,dt)
-    print(dt)
-    thread.sleep(1.1)
-end)
-loop2=multi:newThreadedLoop("loop",function(self,dt)
-    print(dt)
-    thread.hold(function() return count>=100 end)
-    print("Count is "..count)
-    os.exit()
-end)
-alarm=multi:newThreadedAlarm("alarm",1)
-alarm:OnRing(function(self)
-    print("Ring")
-    self:Reset()
-end)
-multi:mainloop()
-

Output

Ring

0.992

0.992

Hello!

step 1

step 2

Hello!

Ring

2.092

step 3

Hello!

Ring

Count is 100

Threadable Actors

Functions

If you ever wanted to pause a function then great now you can
The uses of the Function object allows one to have a method that can run free in a sense

require("multi")
-func=multi:newFunction(function(self,arg1,arg2,...)
-    self:Pause()
-    return arg1
-end)
-print(func("Hello"))
-print(func("Hello2")) -- returns PAUSED allows for the calling of functions that should only be called once. returns PAUSED instantly if paused
-func:Resume()
-print(func("Hello3"))
-

Output

Hello

PAUSED

Hello3

ThreadedUpdater

-- Works the same as a regular updater!
-require("multi")
-multi:newThreadedUpdater("Test",10000):OnUpdate(function(self)
-    print(self.pos)
-end)
-multi:mainloop()
-

Output

1

2



.inf

Triggers

Triggers were what I used before connections became a thing, also Function objects are a lot like triggers and can be paused as well, while triggers cannot…

They are simple to use, but in most cases you are better off using a connection

require("multi")
--- They work like connections but can only have one event binded to them
-trig=multi:newTrigger(function(self,a,b,c,...)
-    print(a,b,c,...)
-end)
-trig:Fire(1,2,3)
-trig:Fire(1,2,3,"Hello",true)
-

Output

1 2 3

1 2 3 Hello true

Tasks

Tasks allow you to run a block of code before the multi mainloops does it thing. Tasks still have a use, but depending on how you program they aren’t needed.

require("multi")
-multi:newTask(function()
-    print("Hi!")
-end)
-multi:newLoop(function(self,dt)
-    print("Which came first the task or the loop?")
-    self:Break()
-end)
-multi:newTask(function()
-    print("Hello there!")
-end)
-multi:mainloop()
-

Output

Hi!

Hello there!

Which came first the task or the loop?

As seen in the example above the tasks were done before anything else in the mainloop! This is useful when making libraries around the multitasking features and you need things to happen in a certain order!

Jobs

Jobs were a strange feature that was created for throttling connections! When I was building a irc bot around this library I couldn’t have messages posting too fast due to restrictions. Jobs allowed functions to be added to a queue that were executed after a certain amount of time has passed

require("multi") -- jobs use alarms I am pondering if alarms should be added to the core or if jobs should use timers instead...
--- jobs are built into the core of the library so no need to require them
-print(multi:hasJobs())
-multi:setJobSpeed(1) -- set job speed to 1 second
-multi:newJob(function()
-    print("A job!")
-end,"test")
-
-multi:newJob(function()
-    print("Another job!")
-    multi:removeJob("test") -- removes all jobs with name "test"
-end,"test")
-
-multi:newJob(function()
-    print("Almost done!")
-end,"test")
-
-multi:newJob(function()
-    print("Final job!")
-end,"test")
-print(multi:hasJobs())
-print("There are "..multi:getJobs().." jobs in the queue!")
-multi:mainloop()
-

Output

false 0

true 4

There are 4 jobs in the queue!

A job!


Another job!

Watchers

Watchers allow you to monitor a variable and trigger an event when the variable has changed!

require("multi")
-a=0
-watcher=multi:newWatcher(_G,"a") -- watch a in the global enviroment
-watcher:OnValueChanged(function(self,old,new)
-    print(old,new)
-end)
-tloop=multi:newTLoop(function(self)
-    a=a+1
-end,1)
-multi:mainloop()
-

Output

0 1

1 2

2 3



.inf-1 inf

Timeout management

-- Note: I used a tloop so I could control the output of the program a bit.
-require("multi")
-a=0
-inc=1 -- change to 0 to see it not met at all, 1 if you want to see the first condition not met but the second and 2 if you want to see it meet the condition on the first go.
-loop=multi:newTLoop(function(self)
-    print("Looping...")
-    a=a+inc
-    if a==14 then
-        self:ResolveTimer("1","2","3") -- ... any number of arguments can be passed to the resolve handler
-        -- this will also automatically pause the object that it is binded to
-    end
-end,.1)
-loop:SetTime(1)
-loop:OnTimerResolved(function(self,a,b,c) -- the handler will return the self and the passed arguments
-    print("We did it!",a,b,c)
-end)
-loop:OnTimedOut(function(self)
-    if not TheSecondTry then
-        print("Loop timed out!",self.Type,"Trying again...")
-        self:ResetTime(2)
-        self:Resume()
-        TheSecondTry=true
-    else
-        print("We just couldn't do it!") -- print if we don't get anything working
-    end
-end)
-multi:mainloop()
-

Output (Change the value inc as indicated in the comment to see the outcomes!)

Looping…

Looping…

Looping…

Looping…

Looping…

Looping…

Looping…

Looping…

Looping…

Loop timed out! tloop Trying again…

Looping…

Looping…

Looping…

Looping…

Looping…

We did it! 1 2 3

Changes

Update: 1.8.6

Added:

This will run said function in every thread.

-- Going to use love2d code this time, almost the same as last time... See ramblings
-require("core.Library")
-GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library
-require("core.GuiManager")
-gui.ff.Color=Color.Black
-jQueue=multi:newSystemThreadedJobQueue()
-jQueue:registerJob("TEST_JOB",function(a,s)
-    math.randomseed(s)
-    TEST_JOB2()
-    return math.random(0,255)
-end)
-jQueue:registerJob("TEST_JOB2",function()
-    print("Test Works!")
-end)
--- 1.8.6 EXAMPLE Change
-jQueue:start() -- This is now needed!
---
-jQueue:doToAll(function()
-    print("Doing this 2? times!")
-end)
-tableOfOrder={}
-jQueue.OnJobCompleted(function(JOBID,n)
-    tableOfOrder[JOBID]=n
-    if #tableOfOrder==10 then
-        t.text="We got all of the pieces!"
-    end
-end)
-for i=1,10 do -- Job Name of registered function, ... varargs
-    jQueue:pushJob("TEST_JOB","This is a test!",math.random(1,1000000))
-end
-t=gui:newTextLabel("no done yet!",0,0,300,100)
-t:centerX()
-t:centerY()
-

Update: 1.8.5

Added:

Allows the execution of system calls without hold up. It is possible to do the same using io.popen()! You decide which works best for you!

local GLOBAL,sThread=require("multi.integration.lanesManager").init()
-cmd=multi:newSystemThreadedExecute("SystemThreadedExecuteTest.lua") -- This file is important!
-cmd.OnCMDFinished(function(code) -- callback function to grab the exit code... Called when the command goes through
-    print("Got Code: "..code)
-end)
-multi:newTLoop(function()
-    print("...") -- lets show that we aren't being held up
-end,1)
-multi:mainloop()
-

Update: 1.8.4

Added:

Using multi:newSystemThreadedJobQueue()

First you need to create the object
This works the same way as love2d as it does with lanes… It is getting increasing harder to make both work the same way with speed in mind… Anyway…

-- Creating the object using lanes manager to show case this. Examples has the file for love2d
-local GLOBAL,sThread=require("multi.integration.lanesManager").init()
-jQueue=multi:newSystemThreadedJobQueue(n) -- this internally creates System threads. By defualt it will use the # of processors on your system You can set this number though.
--- Only create 1 jobqueue! For now making more than 1 is buggy. You only really need one though. Just register new functions if you want 1 queue to do more. The one reason though is keeping track of jobIDs. I have an idea that I will roll out in the next update.
-jQueue:registerJob("TEST_JOB",function(a,s)
-    math.randomseed(s)
-    -- We will push a random #
-    TEST_JOB2() -- You can call other registered functions as well!
-    return math.random(0,255) -- send the result to the main thread
-end)
-jQueue:registerJob("TEST_JOB2",function()
-    print("Test Works!") -- this is called from the job since it is registered on the same queue
-end)
-tableOfOrder={} -- This is how we will keep order of our completed jobs. There is no guarantee that the order will be correct
-jQueue.OnJobCompleted(function(JOBID,n) -- whenever a job is completed you hook to the event that is called. This passes the JOBID folled by the returns of the job
-    -- JOBID is the completed job, starts at 1 and counts up by 1.
-    -- Threads finish at different times so jobids may be passed out of order! Be sure to have a way to order them
-    tableOfOrder[JOBID]=n -- we order ours by putting them into a table
-    if #tableOfOrder==10 then
-        print("We got all of the pieces!")
-    end
-end)
--- Lets push the jobs now
-for i=1,10 do -- Job Name of registered function, ... varargs
-    jQueue:pushJob("TEST_JOB","This is a test!",math.random(1,1000000))
-end
-print("I pushed all of the jobs :)")
-multi:mainloop() -- Start the main loop :D
-

Thats it from this version!

Update: 1.8.3

Added:

New Mainloop functions Below you can see the slight differences… Function overhead is not too bad in lua, but has a real difference. multi:mainloop() and multi:unprotectedMainloop() use the same algorithm yet the dedicated unprotected one is slightly faster due to having less function overhead.

* The OG mainloop function remains the same and old methods to achieve what we have with the new ones still exist

These new methods help by removing function overhead that is caused through the original mainloop function. The one downside is that you no longer have the flexiblity to change the processing during runtime.

However there is a work around! You can use processes to run multiobjs as well and use the other methods on them.

I may make a full comparison between each method and which is faster, but for now trust that the dedicated ones with less function overhead are infact faster. Not by much but still faster. :D

Update: 1.8.2

Added:

The threaded table is setup just like the threaded queue.

It provids GLOBAL like features without having to write to GLOBAL!

This is useful for module creators who want to keep their data private, but also use GLOBAL like coding.

It has a few features that makes it a bit better than plain ol GLOBAL (For now…)
(ThreadedTable - TT for short)

we also have the “sync” method, this one was made for love2d because we do a syncing trick to get data in a table format. The lanes side has a sync method as well so no worries. Using indexing calls sync once and may grab your variable. This allows you to have the lanes indexing ‘like’ syntax when doing regular indexing in love2d side of the module. As of right now both sides work flawlessly! And this effect is now the GLOBAL as well

On GLOBALS sync is a internal method for keeping the GLOBAL table in order. You can still use sThread.waitFor(name) to wait for variables that may of may not yet exist!

Time for some examples:

Using multi:newSystemThreadedTable(name)

-- lanes Desktop lua! NOTE: this is in lanesintergratetest6.lua in the examples folder
-local GLOBAL,sThread=require("multi.integration.lanesManager").init()
-test=multi:newSystemThreadedTable("YO"):init()
-test["test1"]="lol"
-multi:newSystemThread("test",function()
-    tab=sThread.waitFor("YO"):init()
-    print(tab:has("test1"))
-    sThread.sleep(3)
-    tab["test2"]="Whats so funny?"
-end)
-multi:newThread("test2",function()
-    print(test:waitFor("test2"))
-end)
-multi:mainloop()
-
-- love2d gaming lua! NOTE: this is in main4.lua in the love2d examples
-require("core.Library")
-GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library
-require("core.GuiManager")
-gui.ff.Color=Color.Black
-test=multi:newSystemThreadedTable("YO"):init()
-test["test1"]="lol"
-multi:newSystemThread("test",function()
-    tab=sThread.waitFor("YO"):init()
-    print(tab["test1"])
-    sThread.sleep(3)
-    tab["test2"]="Whats so funny?"
-end)
-multi:newThread("test2",function()
-    print(test:waitFor("test2"))
-    t.text="DONE!"
-end)
-t=gui:newTextLabel("no done yet!",0,0,300,100)
-t:centerX()
-t:centerY()
-

Update: 1.8.1

No real change!

Changed the structure of the library. Combined the coroutine based threads into the core!

Only compat and integrations are not part of the core and never will be by nature.

This should make the library more convient to use.

I left multi/all.lua file so if anyone had libraries/projects that used that it will still work!

Updated from 1.7.6 to 1.8.0
(How much thread could a thread thread if a thread could thread thread?)
Added:

Using multi:systemThreadedBenchmark()

package.path="?/init.lua;"..package.path
-local GLOBAL,sThread=require("multi.integration.lanesManager").init()
-multi:systemThreadedBenchmark(3):OnBench(function(self,count)
-    print("First Bench: "..count)
-    multi:systemThreadedBenchmark(3,"All Threads: ")
-end)
-multi:mainloop()
-

Using multi:newSystemThreadedQueue()

Quick Note: queues shared across multiple objects will be pulling from the same “queue” keep this in mind when coding! Also the queue respects direction a push on the thread side cannot be popped on the thread side… Same goes for the mainthread!
Turns out i was wrong about this…

-- in love2d, this file will be in the same example folder as before, but is named main2.lua
-require("core.Library")
-GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library
---IMPORTANT
--- Do not make the above local, this is the one difference that the lanesManager does not have
--- If these are local the functions will have the upvalues put into them that do not exist on the threaded side
--- You will need to ensure that the function does not refer to any upvalues in its code. It will print an error if it does though
--- Also each thread has a .1 second delay! This is used to generate a random values for each thread!
-require("core.GuiManager")
-gui.ff.Color=Color.Black
-function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a channel on both ends
-    local c={}
-    c.name=name
-    if love then
-        if love.thread then
-            function c:init()
-                self.chan=love.thread.getChannel(self.name)
-                function self:push(v)
-                    self.chan:push(v)
-                end
-                function self:pop()
-                    return self.chan:pop()
-                end
-                GLOBAL[self.name]=self
-                return self
-            end
-            return c
-        else
-            error("Make sure you required the love.thread module!")
-        end
-    else
-        c.linda=lanes.linda()
-        function c:push(v)
-            self.linda:send("Q",v)
-        end
-        function c:pop()
-            return ({self.linda:receive(0,"Q")})[2]
-        end
-        function c:init()
-            return self
-        end
-        GLOBAL[name]=c
-    end
-    return c
-end
-queue=multi:newSystemThreadedQueue("QUEUE"):init()
-queue:push("This is a test")
-queue:push("This is a test2")
-queue:push("This is a test3")
-queue:push("This is a test4")
-multi:newSystemThread("test2",function()
-    queue=sThread.waitFor("QUEUE"):init()
-    data=queue:pop()
-    while data do
-        print(data)
-        data=queue:pop()
-    end
-    queue:push("DONE!")
-end)
-multi:newThread("test!",function()
-    thread.hold(function() return queue:pop() end)
-    t.text="Done!"
-end)
-t=gui:newTextLabel("no done yet!",0,0,300,100)
-t:centerX()
-t:centerY()
-

In Lanes

-- The code is compatible with each other, I just wanted to show different things you can do in both examples
--- This file can be found in the examples folder as lanesintegrationtest4.lua
-local GLOBAL,sThread=require("multi.integration.lanesManager").init()
-queue=multi:newSystemThreadedQueue("QUEUE"):init()
-queue:push("This is a test")
-queue:push("This is a test2")
-queue:push("This is a test3")
-queue:push("This is a test4")
-multi:newSystemThread("test2",function()
-    queue=sThread.waitFor("QUEUE"):init()
-    data=queue:pop()
-    while data do
-        print(data)
-        data=queue:pop()
-    end
-    queue:push("This is a test5")
-    queue:push("This is a test6")
-    queue:push("This is a test7")
-    queue:push("This is a test8")
-end)
-multi:newThread("test!",function() -- this is a lua thread
-    thread.sleep(.1)
-    data=queue:pop()
-    while data do
-        print(data)
-        data=queue:pop()
-    end
-end)
-multi:mainloop()
-

Update: 1.7.6

Fixed:
Typos like always
Added:

multi:getPlatform() — returns “love2d” if using the love2d platform or returns “lanes” if using lanes for threading

examples files

In Events added method setTask(func)

The old way still works and is more convient to be honest, but I felt a method to do this was ok.

Updated:
some example files to reflect changes to the core. Changes allow for less typing

loveManager to require the compat if used so you don’t need 2 require line to retrieve the library

Update: 1.7.5

Fixed some typos in the readme… (I am sure there are more there are always more)

Added more features for module support

TODO:

Work on performance of the library… I see 3 places where I can make this thing run quicker

I’ll show case some old versions of the multitasking library eventually so you can see its changes in days past!

Update: 1.7.4

Added: the example folder which will be populated with more examples in the near future!

The loveManager integration that mimics the lanesManager integration almost exactly to keep coding in both enviroments as close to possible. This is done mostly for library creation support!

An example of the loveManager in action using almost the same code as the lanesintergreationtest2.lua

NOTE: This code has only been tested to work on love2d version 1.10.2 thoough it should work version 0.9.0

require("core.Library") -- Didn't add this to a repo yet! Will do eventually... Allows for injections and other cool things
-require("multi.compat.love2d") -- allows for multitasking and binds my libraies to the love2d engine that i am using
-GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager
---IMPORTANT
--- Do not make the above local, this is the one difference that the lanesManager does not have
--- If these are local the functions will have the upvalues put into them that do not exist on the threaded side
--- You will need to ensure that the function does not refer to any upvalues in its code. It will print an error if it does though
--- Also each thread has a .1 second delay! This is used to generate a random values for each thread!
-require("core.GuiManager") -- allows the use of graphics in the program.
-gui.ff.Color=Color.Black
-function comma_value(amount)
-    local formatted = amount
-    while true do
-        formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
-        if (k==0) then
-            break
-        end
-    end
-    return formatted
-end
-multi:newSystemThread("test1",function() -- Another difference is that the multi library is already loaded in the threaded enviroment as well as a call to multi:mainloop()
-    multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 1"):OnBench(function(self,c) GLOBAL["T1"]=c multi:Stop() end)
-end)
-multi:newSystemThread("test2",function() -- spawns a thread in another lua process
-    multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 2"):OnBench(function(self,c) GLOBAL["T2"]=c multi:Stop() end)
-end)
-multi:newSystemThread("test3",function() -- spawns a thread in another lua process
-    multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 3"):OnBench(function(self,c) GLOBAL["T3"]=c multi:Stop() end)
-end)
-multi:newSystemThread("test4",function() -- spawns a thread in another lua process
-    multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 4"):OnBench(function(self,c) GLOBAL["T4"]=c multi:Stop() end)
-end)
-multi:newSystemThread("test5",function() -- spawns a thread in another lua process
-    multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 5"):OnBench(function(self,c) GLOBAL["T5"]=c multi:Stop() end)
-end)
-multi:newSystemThread("test6",function() -- spawns a thread in another lua process
-    multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 6"):OnBench(function(self,c) GLOBAL["T6"]=c multi:Stop() end)
-end)
-multi:newSystemThread("Combiner",function() -- spawns a thread in another lua process
-    function comma_value(amount)
-        local formatted = amount
-        while true do
-            formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
-            if (k==0) then
-                break
-            end
-        end
-        return formatted
-    end
-    local b=comma_value(tostring(sThread.waitFor("T1")+sThread.waitFor("T2")+sThread.waitFor("T3")+sThread.waitFor("T4")+sThread.waitFor("T5")+sThread.waitFor("T6")))
-    GLOBAL["DONE"]=b
-end)
-multi:newThread("test0",function()
-    -- sThread.waitFor("DONE") -- lets hold the main thread completely so we don't eat up cpu
-    -- os.exit()
-    -- when the main thread is holding there is a chance that error handling on the system threads may not work!
-    -- instead we can do this
-    while true do
-        thread.skip(1) -- allow error handling to take place... Otherwise lets keep the main thread running on the low
-        -- Before we held just because we could... But this is a game and we need to have logic continue
-        --sThreadM.sleep(.001) -- Sleeping for .001 is a greeat way to keep cpu usage down. Make sure if you aren't doing work to rest. Abuse the hell out of GLOBAL if you need to :P
-        if GLOBAL["DONE"] then
-            t.text="Bench: "..GLOBAL["DONE"]
-        end
-    end
-end)
-GLOBAL["Bench"]=3
-t=gui:newTextLabel("no done yet!",0,0,300,100)
-t:centerX()
-t:centerY()
-

Update: 1.7.3

Changed how requiring the library works!
require("multi.all") Will still work as expected; however, with the exception of threading, compat, and integrations everything else has been moved into the core of the library.

-- This means that these are no longer required and will cause an error if done so
-require("multi.loop")
-require("multi.alarm")
-require("multi.updater")
-require("multi.tloop")
-require("multi.watcher")
-require("multi.tstep")
-require("multi.step")
-require("multi.task")
--- ^ they are all part of the core now
-

Update: 1.7.2

Moved updaters, loops, and alarms into the init.lua file. I consider them core features and they are referenced in the init.lua file so they need to exist there. Threaded versions are still separate though. Added another example file

Update: 1.7.1 Bug Fixes Only

Update: 1.7.0

Modified: multi.integration.lanesManager.lua
It is now in a stable and simple state Works with the latest lanes version! Tested with version 3.11 I cannot promise that everything will work with eariler versions. Future versions are good though.

Example Usage:

sThread is a handle to a global interface for system threads to interact with themself

thread is the interface for multithreads as seen in the threading section

GLOBAL a table that can be used throughout each and every thread

sThreads have a few methods

sThread.set(name,val) — you can use the GLOBAL table instead modifies the same table anyway

sThread.get(name) — you can use the GLOBAL table instead modifies the same table anyway

sThread.waitFor(name) — waits until a value exists, if it does it returns it

sThread.getCores() — returns the number of cores on your cpu

sThread.sleep(n) — sleeps for a bit stopping the entire thread from running

sThread.hold(n) — sleeps until a condition is met

local GLOBAL,sThread=require("multi.integration.lanesManager").init()
-require("multi.all")
-multi:newAlarm(2):OnRing(function(self)
-    GLOBAL["NumOfCores"]=sThread.getCores()
-end)
-multi:newAlarm(7):OnRing(function(self)
-    GLOBAL["AnotherTest"]=true
-end)
-multi:newAlarm(13):OnRing(function(self)
-    GLOBAL["FinalTest"]=true
-end)
-multi:newSystemThread("test",function() -- spawns a thread in another lua process
-    require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the integration. You would need to require the interaction again though
-    print("Waiting for variable: NumOfCores")
-    print("Got it: ",sThread.waitFor("NumOfCores"))
-    sThread.hold(function()
-        return GLOBAL["AnotherTest"] -- note this would hold the entire systemthread. Spawn a coroutine thread using multi:newThread() or multi:newThreaded...
-    end)
-    print("Holding works!")
-    multi:newThread("tests",function()
-        thread.hold(function()
-            return GLOBAL["FinalTest"] -- note this will not hold the entire systemthread. As seen with the TLoop constantly going!
-        end)
-        print("Final test works!")
-        os.exit()
-    end)
-    local a=0
-    multi:newTLoop(function()
-        a=a+1
-        print(a)
-    end,.5)
-    multi:mainloop()
-end)
-multi:mainloop()
-

Update: 1.6.0

Changed: steps and loops

-- Was
-step:OnStep(function(pos,self) -- same goes for tsteps as well
-    print(pos)
-end)
-multi:newLoop(function(dt,self)
-    print(dt)
-end)
--- Is now
-step:OnStep(function(self,pos) -- same goes for tsteps as well
-    print(pos)
-end)
-multi:newLoop(function(self,dt)
-    print(dt)
-end)
-

Reasoning I wanted to keep objects consistant, but a lot of my older libraries use the old way of doing things. Therefore I added a backwards module

require("multi.all")
-require("multi.compat.backwards[1,5,0]") -- allows for the use of features that were scrapped/changed in 1.6.0+
-

Update: 1.5.0

Added:

Update: 1.4.1 - First Public release of the library

IMPORTANT:

Every update I make aims to make things simpler more efficent and just better, but a lot of old code, which can be really big, uses a lot of older features. I know the pain of having to rewrite everything. My promise to my library users is that I will always have backwards support for older features! New ways may exist that are quicker and eaiser, but the old features/methods will be supported.

Rambling

Love2d Sleeping reduces the cpu time making my load detection think the system is under more load, thus preventing it from sleeping… I will look into other means. As of right now it will not eat all of your cpu if threads are active. For now I suggest killing threads that aren’t needed anymore. On lanes threads at idle use 0% cpu and it is amazing. A state machine may solve what I need though. One state being idle state that sleeps and only goes into the active state if a job request or data is sent to it… after some time of not being under load it wil switch back into the idle state… We’ll see what happens.

Love2d doesn’t like to send functions through channels. By defualt it does not support this. I achieve this by dumping the function and loadstring it on the thread. This however is slow. For the System Threaded Job Queue I had to change my original idea of sending functions as jobs. The current way you do it now is register a job functions once and then call that job across the thread through a queue. Each worker thread pops from the queue and returns the job. The Job ID is automatically updated and allows you to keep track of the order that the data comes in. A table with # indexes can be used to originze the data…

In regards to benchmarking. If you see my bench marks and are wondering they are 10x better its because I am using luajit for my tests. I highly recommend using luajit for my library, but lua 5.1 will work just as well, but not as fast.

So while working on the jobQueue:doToAll() method I figured out why love2d’s threaded tables were acting up when more than 1 thread was sharing the table. It turns out 1 thread was eating all of the pops from the queue and starved all of the other queues… Ill need to use the same trick I did with GLOBAL to fix the problem… However at the rate I am going threading in love will become way slower. I might use the regualr GLOBAL to manage data internally for threadedtables…

It has been awhile since I had to bring out the Multi Functions… Syncing within threads are a pain! I had no idea what a task it would be to get something as simple as syncing data was going to be… I will probably add a SystemThreadedSyncer in the future because it will make life eaiser for you guys as well. SystemThreadedTables are still not going to work on love2d, but will work fine on lanes… I have a solution and it is being worked on… Depending on when I pust the next update to this library the second half of this ramble won’t apply anymore

I have been using this (EventManager —> MultiManager —> now multi) for my own purposes and started making this when I first started learning lua. You are able to see how the code changed and evolved throughout the years. I tried to include all the versions that still existed on my HDD.

I added my old versions to this library… It started out as the EventManager and was kinda crappy but it was the start to this library. It kept getting better and better until it became what it is today. There are some features that nolonger exist in the latest version, but they were remove because they were useless… I added these files to the github so for those interested can see into my mind in a sense and see how I developed the library before I used github.

The first version of the EventManager was function based not object based and benched at about 2000 steps per second… Yeah that was bad… I used loadstring and it was a mess… Take a look and see how it grew throughout the years I think it may intrest some of you guys!

- - - - diff --git a/mulit/README.md b/mulit/README.md deleted file mode 100644 index 9a803b6..0000000 --- a/mulit/README.md +++ /dev/null @@ -1,1357 +0,0 @@ -# multi Version: 1.8.6 (System Threaded Job Queues gets an update!) - -**NOTE: I have been studying a lot about threading in the past few weeks and have some awesome additions in store! They will take a while to come out though. The goal of the library is still to provide a simple and efficient way to multi task in lua** - -In Changes you'll find documentation for(In Order): -- System Threaded Job Queues -- New mainloop functions -- System Threaded Tables -- System Threaded Benchmark -- System Threaded Queues -- Threading related features -- And backwards compat stuff - -My multitasking library for lua. It is a pure lua binding if you ingore the integrations and the love2d compat. If you find any bugs or have any issues please let me know :). **If you don't see a table of contents try using the ReadMe.html file. It is eaiser to navigate the readme**
- -[TOC] - -INSTALLING ----------- -To install copy the multi folder into your enviroment and you are good to go
- -**or** use luarocks - -``` -luarocks install multi -``` -Discord -------- -For real-time assistance with my libraries! A place where you can ask questions and get help with any of my libraries. Also you can request features and stuff there as well.
-https://discord.gg/U8UspuA
- -Planned features/TODO ---------------------- -- [x] ~~Add system threads for love2d that works like the lanesManager (loveManager, slight differences).~~ -- [x] ~~Improve performance of the library~~ -- [x] ~~Improve coroutine based threading scheduling~~ -- [ ] Improve love2d Idle thread cpu usage... Tricky Look at the rambling section for insight. -- [ ] Add more control to coroutine based threading -- [ ] Add more control to system based threading -- [ ] Fix the performance when using system threads in love2d -- [ ] Make practical examples that show how you can solve real problems -- [x] ~~Add more features to support module creators~~ -- [x] ~~Make a framework for eaiser thread task distributing~~ -- [x] ~~Fix Error handling on threaded multi objects~~ Non threaded multiobjs will crash your program if they error though! Use multi:newThread() of multi:newSystemThread() if your code can error! Unless you use multi:protect() this however lowers performance! -- [x] ~~Add multi:OnError(function(obj,err))~~ -- [ ] sThread.wrap(obj) **May or may not be completed** Theory: Allows interaction in one thread to affect it in another. The addition to threaded tables may make this possible! -- [ ] SystemThreaded Actors -- After some tests i figured out a way to make this work... It will work slightly different though. This is due to the actor needing to be splittable... -- [ ] LoadBalancing for system threads (Once SystemThreaded Actors are done) -- [ ] Add more integrations -- [ ] Finish the wiki stuff. (11% done) -- [ ] Test for unknown bugs - -Known Bugs/Issues ------------------ -In regards to integrations, thread cancellation works slightly different for love2d and lanes. Within love2d I was unable to (To lazy to...) not use the multi library within the thread. A fix for this is to call `multi:Stop()` when you are done with your threaded code! This may change however if I find a way to work around this. In love2d in order to mimic the GLOBAL table I needed the library to constantly sync tha data... You can use the sThread.waitFor(varname), or sThread.hold(func) methods to sync the globals, to get the value instead of using GLOBAL and this could work. If you want to go this route I suggest setting multi.isRunning=true to prevent the auto runner from doing its thing! This will make the multi manager no longer function, but thats the point :P - -Another bug concerns the SystemThreadedJobQueue, Only 1 can be used for now... Creating more may not be a good idea. - -And systemThreadedTables only supports 1 table between the main and worker thread! They do not work when shared between 2 or more threads. If you need that much flexiblity ust the GLOBAL table that all threads have. - -For module creators using this library. I suggest using SystemThreadedQueues for data transfer instead of SystemThreadedTables for rapid data transfer, If you plan on having Constants that will always be the same then a table is a good idea! They support up to **n** threads and can be messed with and abused as much as you want :D - -Love2D SystemThreadedTAbles do not send love2d userdata, use queues instead for that! - -Usage:
------ -```lua --- Basic usage Alarms: Have been moved to the core of the library require("multi") would work as well -require("multi") -- gets the entire library -alarm=multi:newAlarm(3) -- in seconds can go to .001 uses the built in os.clock() -alarm:OnRing(function(a) - print("3 Seconds have passed!") - a:Reset(n) -- if n were nil it will reset back to 3, or it would reset to n seconds -end) -multi:mainloop() -- the main loop of the program, multi:umanager() exists as well to allow integration in other loops Ex: love2d love.update function. More on this binding in the wiki! -``` -The library is modular so you only need to require what you need to. Because of this, the global enviroment is altered
- -There are many useful objects that you can use
-Check out the wiki for detailed usage, but here are the objects:
-- Process#
-- QueueQueuer#
-- Alarm
-- Loop
-- Event
-- Step
-- Range
-- TStep
-- TLoop
-- Condition
-- Connection
-- Timer
-- Updater
-- Thread*
-- Trigger
-- Task
-- Job
-- Function
-- Watcher
-Note: *Both a process and queue act like the multi namespace, but allows for some cool things. Because they use the other objects an example on them will be done last*
-*Uses the built in coroutine features of lua, these have an interesting interaction with the other means of multi-tasking
-Triggers are kind of useless after the creation of the Connection
-Watchers have no real purpose as well I made it just because.
- -# Examples of each object being used
-We already showed alarms in action so lets move on to a Loop object - -Throughout these examples I am going to do some strange things in order to show other features of the library! - -LOOPS ------ -```lua --- Loops: Have been moved to the core of the library require("multi") would work as well -require("multi") -- gets the entire library -count=0 -loop=multi:newLoop(function(self,dt) -- dt is delta time and self is a reference to itself - count=count+1 - if count > 10 then - self:Break() -- All methods on the multi objects are upper camel case, where as methods on the multi or process/queuer namespace are lower camel case - -- self:Break() will stop the loop and trigger the OnBreak(func) method - -- Stopping is the act of Pausing and deactivating the object! All objects can have the multiobj:Break() command on it! - else - print("Loop #"..count.."!") - end -end) -loop:OnBreak(function(self) - print("You broke me :(") -end) -multi:mainloop() -``` -# Output -Loop #1!
-Loop #2!
-Loop #3!
-Loop #4!
-Loop #5!
-Loop #6!
-Loop #7!
-Loop #8!
-Loop #9!
-Loop #10!
-You broke me :(
- - -With loops out of the way lets go down the line - -This library aims to be Async like. In reality everything is still on one thread *unless you are using the lanes integration module WIP* (More on that later) - -EVENTS ------- -```lua --- Events, these were the first objects introduced into the library. I seldomly use them in their pure form though, but later on you'll see their advance uses! --- Events on there own don't really do much... We are going to need 2 objects at least to get something going -require("multi") -- gets the entire library -count=0 --- lets use the loop again to add to count! -loop=multi:newLoop(function(self,dt) - count=count+1 -end) -event=multi:newEvent(function() return count==100 end) -- set the event -event:OnEvent(function(self) -- connect to the event object - loop:Pause() -- pauses the loop from running! - print("Stopped that loop!") -end) -- events like alarms need to be reset the Reset() command works here as well -multi:mainloop() -``` -# Output -Stopped that loop! - -STEPS ------ -```lua -require("multi") --- Steps, are like for loops but non blocking... You can run a loop to infintity and everything will still run I will combine Steps with Ranges in this example. -step1=multi:newStep(1,10,1,0) -- Some explaining is due. Argument 1 is the Start # Argument 2 is the ResetAt # (inclusive) Argument 3 is the count # (in our case we are counting by +1, this can be -1 but you need to adjust your start and resetAt numbers) --- The 4th Argument is for skipping. This is useful for timing and for basic priority management. A priority management system is included! -step2=multi:newStep(10,1,-1,1) -- a second step, notice the slight changes! -step1:OnStart(function(self) - print("Step Started!") -end) -step1:OnStep(function(self,pos) - if pos<=10 then -- what what is this? the step only goes to 10!!! - print("Stepping... "..pos) - else - print("How did I get here?") - end -end) -step1:OnEnd(function(self) - print("Done!") - -- We finished here, but I feel like we could have reused this step in some way... Yeah I soule Reset() it, but what if i wanted to change it... - if self.endAt==10 then -- lets only loop once - self:Update(1,11,1,0) -- oh now we can reach that else condition! - end - -- Note Update() will restart the step! -end) - --- step2 is bored lets give it some love :P -step2.range=step2:newRange() -- Set up a range object to have a nested step in a sense! Each nest requires a new range --- it is in your interest not to share ranges between objects! You can however do it if it suits your needs though -step2:OnStep(function(self,pos) - -- for 1=1,math.huge do - -- print("Haha I am holding the code up because I can!!!") - --end - -- We dont want to hold things up, but we want to nest. - -- Note a range is not nessary if the nested for loop has a small range, if however the range is rather large you may want to allow other objects to do some work - for i in self.range(1,100) do - print(pos,i) -- Now our nested for loop is using a range object which allows for other objects to get some cpu time while this one is running - end -end) --- TSteps are just like alarms and steps mixed together, the only difference in construction is the 4th Argument. On a TStep that argument controls time. The defualt is 1 --- The Reset(n) works just like you would figure! -step3=multi:newTStep(1,10,.5,2) -- lets go from 1 to 10 counting by .5 every 2 seconds -step3:OnStep(function(self,pos) - print("Ok "..pos.."!") -end) -multi:mainloop() -``` -# Output - -Note: the output on this one is huge!!! So I had to ... some parts! You need to run this for your self to see what is going on!
-Step Started!
-Stepping... 1
-10 1
-Stepping... 2
-10 2
-Stepping... 3
-10 3
-...
-Ok 9.5!
-Ok 10!
- -TLOOPS ------- -```lua -require("multi") --- TLoops are loops that run ever n second. We will also look at condition objects as well --- Here we are going to modify the old loop to be a little different -count=0 -loop=multi:newTLoop(function(self) -- We are only going to coult with this loop, but doing so using a condition! - while self:condition(self.cond) do - count=count+1 - end - print("Count is "..count.."!") - self:Destroy() -- Lets destroy this object, casting it to the dark abyss MUHAHAHA!!! - -- the reference to this object will be a phantom object that does nothing! -end,1) -- Notice the ',1' after the function! This is where you put your time value! -loop.cond=multi:newCondition(function() return count<=100 end) -- conditions need a bit of work before i am happy with them -multi:mainloop() -``` -# Output -Count is 101! - -Connections ------------ -These are my favorite objects and you'll see why. They are very useful objects for ASync connections! - -```lua -require("multi") --- Lets create the events -yawn={} -- ill just leave that there -OnCustomSafeEvent=multi:newConnection(true) -- lets pcall the calls incase something goes wrong defualt -OnCustomEvent=multi:newConnection(false) -- lets not pcall the calls and let errors happen... We are good at coding though so lets get a speed advantage by not pcalling. Pcalling is useful for plugins and stuff that may have been coded badly and you can ingore those connections if need be. -OnCustomEvent:Bind(yawn) -- create the connection lookup data in yawn - --- Lets connect to them, a recent update adds a nice syntax to connect to these -cd1=OnCustomSafeEvent:Connect(function(arg1,arg2,...) - print("CSE1",arg1,arg2,...) -end,"bob") -- lets give this connection a name -cd2=OnCustomSafeEvent:Connect(function(arg1,arg2,...) - print("CSE2",arg1,arg2,...) -end,"joe") -- lets give this connection a name -cd3=OnCustomSafeEvent:Connect(function(arg1,arg2,...) - print("CSE3",arg1,arg2,...) -end) -- lets not give this connection a name - --- no need for connect, but I kept that function because of backwards compatibility. -OnCustomEvent(function(arg1,arg2,...) - print(arg1,arg2,...) -end) - --- Now within some loop/other object you trigger the connection like -OnCustomEvent:Fire(1,2,"Hello!!!") -- fire all conections - --- You may have noticed that some events have names! See the following example! -OnCustomSafeEvent:getConnection("bob"):Fire(1,100,"Bye!") -- fire only bob! -OnCustomSafeEvent:getConnection("joe"):Fire(1,100,"Hello!") -- fire only joe!! -OnCustomSafeEvent:Fire(1,100,"Hi Ya Folks!!!") -- fire them all!!! - --- Connections have more to them than that though! --- As seen above cd1-cd3 these are hooks to the connection object. This allows you to remove a connection --- For Example: -cd1:Remove() -- remove this connection from the master connection object -print("------") -OnCustomSafeEvent:Fire(1,100,"Hi Ya Folks!!!") -- fire them all again!!! --- To remove all connections use: -OnCustomSafeEvent:Remove() -print("------") -OnCustomSafeEvent:Fire(1,100,"Hi Ya Folks!!!") -- fire them all again!!! -``` -# Output -1 2 Hello!!!
-CSE1 1 100 Bye!
-CSE2 1 100 Hello!
-CSE1 1 100 Hi Ya Folks!!!
-CSE2 1 100 Hi Ya Folks!!!
-CSE3 1 100 Hi Ya Folks!!!
-CSE2 1 100 Hi Ya Folks!!!
-CSE3 1 100 Hi Ya Folks!!!
-
- -You may think timers should be bundled with alarms, but they are a bit different and have cool features
-TIMERS ------- -```lua --- You see the thing is that all time based objects use timers eg. Alarms, TSteps, and Loops. Timers are more low level! -require("multi") -local clock = os.clock -function sleep(n) -- seconds - local t0 = clock() - while clock() - t0 <= n do end -end -- we will use this later! - -timer=multi:newTimer() -timer:Start() --- lets do a mock alarm -set=3 -- 3 seconds -a=0 -while timer:Get()<=set do - -- waiting... - a=a+1 -end -print(set.." second(s) have passed!") --- Timers can do one more thing that is interesting and that is pausing them! -timer:Pause() -print(timer:Get()) -- should be really close to 'set' -sleep(3) -print(timer:Get()) -- should be really close to 'set' -timer:Resume() -sleep(1) -print(timer:Get()) -- should be really close to the value of set + 1 -timer:Pause() -print(timer:Get()) -- should be really close to 'set' -sleep(3) -print(timer:Get()) -- should be really close to 'set' -timer:Resume() -sleep(1) -print(timer:Get()) -- should be really close to the value of set + 2 -``` -# Output -Note: This will make more sense when you run it for your self
-3 second(s) have passed!
-3.001
-3.001
-4.002
-4.002
-4.002
-5.003
- -UPDATER -------- -```lua --- Updaters: Have been moved to the core of the library require("multi") would work as well -require("multi") -updater=multi:newUpdater(5) -- really simple, think of a look with the skip feature of a step -updater:OnUpdate(function(self) - --print("updating...") -end) --- Here every 5 steps the updater will do stuff! --- But I feel it is now time to touch into priority management, so lets get into basic priority stuff and get into a more advance version of it ---[[ -multi.Priority_Core -- Highest form of priority -multi.Priority_High -multi.Priority_Above_Normal -multi.Priority_Normal -- The defualt form of priority -multi.Priority_Below_Normal -multi.Priority_Low -multi.Priority_Idle -- Lowest form of priority - -Note: These only take effect when you enable priority, otherwise everything is at a core like level! -We aren't going to use regular objects to test priority, but rather benchmarks! -to set priority on an object though you would do -multiobj:setPriority(one of the above) -]] --- lets bench for 3 seconds using the 3 forms of priority! First no Priority -multi:benchMark(3,nil,"Regular Bench: "):OnBench(function() -- the onbench() allows us to do each bench after each other! - print("P1\n---------------") - multi:enablePriority() - multi:benchMark(3,multi.Priority_Core,"Core:") - multi:benchMark(3,multi.Priority_High,"High:") - multi:benchMark(3,multi.Priority_Above_Normal,"Above_Normal:") - multi:benchMark(3,multi.Priority_Normal,"Normal:") - multi:benchMark(3,multi.Priority_Below_Normal,"Below_Normal:") - multi:benchMark(3,multi.Priority_Low,"Low:") - multi:benchMark(3,multi.Priority_Idle,"Idle:"):OnBench(function() - print("P2\n---------------") - -- Finally the 3rd form - multi:enablePriority2() - multi:benchMark(3,multi.Priority_Core,"Core:") - multi:benchMark(3,multi.Priority_High,"High:") - multi:benchMark(3,multi.Priority_Above_Normal,"Above_Normal:") - multi:benchMark(3,multi.Priority_Normal,"Normal:") - multi:benchMark(3,multi.Priority_Below_Normal,"Below_Normal:") - multi:benchMark(3,multi.Priority_Low,"Low:") - multi:benchMark(3,multi.Priority_Idle,"Idle:") - end) -end) -multi:mainloop() -- Notice how the past few examples did not need this, well only actors need to be in a loop! More on this in the wiki. -``` -# Output -Note: These numbers will vary drastically depending on your compiler and cpu power
-Regular Bench: 2094137 Steps in 3 second(s)!
-P1
-Below_Normal: 236022 Steps in 3 second(s)!
-Normal: 314697 Steps in 3 second(s)!
-Above_Normal: 393372 Steps in 3 second(s)!
-High: 472047 Steps in 3 second(s)!
-Core: 550722 Steps in 3 second(s)!
-Low: 157348 Steps in 3 second(s)!
-Idle: 78674 Steps in 3 second(s)!
-P2
-Core: 994664 Steps in 3 second(s)!
-High: 248666 Steps in 3 second(s)!
-Above_Normal: 62166 Steps in 3 second(s)!
-Normal: 15541 Steps in 3 second(s)!
-Below_Normal: 3885 Steps in 3 second(s)!
-Idle: 242 Steps in 3 second(s)!
-Low: 971 Steps in 3 second(s)!
- -Notice: Even though I started each bench at the same time the order that they finished differed the order is likely to vary on your machine as well!
- -Processes ---------- -A process allows you to group the Actor objects within a controlable interface -```lua -require("multi") -proc=multi:newProcess() -- takes an optional file as an argument, but for this example we aren't going to use that --- a process works just like the multi object! -b=0 -loop=proc:newTLoop(function(self) - a=a+1 - proc:Pause() -- pauses the cpu cycler for this processor! Individual objects are not paused, however because they aren't getting cpu time they act as if they were paused -end,.1) -updater=proc:newUpdater(multi.Priority_Idle) -- priority can be used in skip arguments as well to manage priority without enabling it! -updater:OnUpdate(function(self) - b=b+1 -end) -a=0 -- a counter -loop2=proc:newLoop(function(self,dt) - print("Lets Go!") - self:hold(3) -- this will keep this object from doing anything! Note: You can only have one hold active at a time! Multiple are possible, but results may not be as they seem see * for how hold works - -- Within a process using hold will keep it alive until the hold is satisified! - print("Done being held for 1 second") - self:hold(function() return a>10 end) - print("A is now: "..a.." b is also: "..b) - self:Destroy() - self.Parent:Pause() -- lets say you don't have the reference to the process! - os.exit() -end) --- Notice this is now being created on the multi namespace -event=multi:newEvent(function() return os.clock()>=1 end) -event:OnEvent(function(self) - proc:Resume() - self:Destroy() -end) -proc:Start() -multi:mainloop() -``` -# Output -Lets Go!
-Done being held for 1 second
-A is now: 29 b is also: 479
- -**Hold: This method works as follows** -```lua -function multi:hold(task) - self:Pause() -- pause the current object - self.held=true -- set held - if type(task)=='number' then -- a sleep cmd - local timer=multi:newTimer() - timer:Start() - while timer:Get() -Ring ring!!!
-1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-Done
-# Actual Output -Done
-1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-Ring ring!!!
- -Threads -------- -These fix the hold problem that you get with regular objects, and they work exactly the same! They even have some extra features that make them really useful.
-```lua -require("multi") -test=multi:newThreadedProcess("main") -- you can thread processors and all Actors see note for a list of actors you can thread! -test2=multi:newThreadedProcess("main2") -count=0 -test:newLoop(function(self,dt) - count=count+1 - thread.sleep(.01) -end) -test2:newLoop(function(self,dt) - print("Hello!") - thread.sleep(1) -- sleep for some time -end) --- threads take a name object then the rest as normal -step=multi:newThreadedTStep("step",1,10) -step:OnStep(function(self,p) - print("step",p) - thread.skip(21) -- skip n cycles -end) -step:OnEnd(function() - print("Killing thread!") - thread.kill() -- kill the thread -end) -loop=multi:newThreadedLoop("loop",function(self,dt) - print(dt) - thread.sleep(1.1) -end) -loop2=multi:newThreadedLoop("loop",function(self,dt) - print(dt) - thread.hold(function() return count>=100 end) - print("Count is "..count) - os.exit() -end) -alarm=multi:newThreadedAlarm("alarm",1) -alarm:OnRing(function(self) - print("Ring") - self:Reset() -end) -multi:mainloop() -``` -# Output -Ring
-0.992
-0.992
-Hello!
-step 1
-step 2
-Hello!
-Ring
-2.092
-step 3
-Hello!
-Ring
-Count is 100
-Threadable Actors ------------------ -- Alarms -- Events -- Loop/TLoop -- Process -- Step/TStep - -Functions ---------- -If you ever wanted to pause a function then great now you can -The uses of the Function object allows one to have a method that can run free in a sense -```lua -require("multi") -func=multi:newFunction(function(self,arg1,arg2,...) - self:Pause() - return arg1 -end) -print(func("Hello")) -print(func("Hello2")) -- returns PAUSED allows for the calling of functions that should only be called once. returns PAUSED instantly if paused -func:Resume() -print(func("Hello3")) -``` -# Output -Hello
-PAUSED
-Hello3
- -ThreadedUpdater ---------------- - -```lua --- Works the same as a regular updater! -require("multi") -multi:newThreadedUpdater("Test",10000):OnUpdate(function(self) - print(self.pos) -end) -multi:mainloop() -``` -# Output -1
-2
-...
-.inf
- -Triggers --------- -Triggers were what I used before connections became a thing, also Function objects are a lot like triggers and can be paused as well, while triggers cannot...
-They are simple to use, but in most cases you are better off using a connection
-```lua -require("multi") --- They work like connections but can only have one event binded to them -trig=multi:newTrigger(function(self,a,b,c,...) - print(a,b,c,...) -end) -trig:Fire(1,2,3) -trig:Fire(1,2,3,"Hello",true) -``` - -# Output -1 2 3
-1 2 3 Hello true
- -Tasks ------ -Tasks allow you to run a block of code before the multi mainloops does it thing. Tasks still have a use, but depending on how you program they aren't needed.
-```lua -require("multi") -multi:newTask(function() - print("Hi!") -end) -multi:newLoop(function(self,dt) - print("Which came first the task or the loop?") - self:Break() -end) -multi:newTask(function() - print("Hello there!") -end) -multi:mainloop() -``` -# Output -Hi!
-Hello there!
-Which came first the task or the loop?
- -As seen in the example above the tasks were done before anything else in the mainloop! This is useful when making libraries around the multitasking features and you need things to happen in a certain order!
- -Jobs ----- -Jobs were a strange feature that was created for throttling connections! When I was building a irc bot around this library I couldn't have messages posting too fast due to restrictions. Jobs allowed functions to be added to a queue that were executed after a certain amount of time has passed -```lua -require("multi") -- jobs use alarms I am pondering if alarms should be added to the core or if jobs should use timers instead... --- jobs are built into the core of the library so no need to require them -print(multi:hasJobs()) -multi:setJobSpeed(1) -- set job speed to 1 second -multi:newJob(function() - print("A job!") -end,"test") - -multi:newJob(function() - print("Another job!") - multi:removeJob("test") -- removes all jobs with name "test" -end,"test") - -multi:newJob(function() - print("Almost done!") -end,"test") - -multi:newJob(function() - print("Final job!") -end,"test") -print(multi:hasJobs()) -print("There are "..multi:getJobs().." jobs in the queue!") -multi:mainloop() -``` -# Output -false 0
-true 4
-There are 4 jobs in the queue!
-A job!

-Another job!
- -Watchers --------- -Watchers allow you to monitor a variable and trigger an event when the variable has changed! -```lua -require("multi") -a=0 -watcher=multi:newWatcher(_G,"a") -- watch a in the global enviroment -watcher:OnValueChanged(function(self,old,new) - print(old,new) -end) -tloop=multi:newTLoop(function(self) - a=a+1 -end,1) -multi:mainloop() -``` -# Output -0 1
-1 2
-2 3
-...
-.inf-1 inf
- -Timeout management ------------------- -```lua --- Note: I used a tloop so I could control the output of the program a bit. -require("multi") -a=0 -inc=1 -- change to 0 to see it not met at all, 1 if you want to see the first condition not met but the second and 2 if you want to see it meet the condition on the first go. -loop=multi:newTLoop(function(self) - print("Looping...") - a=a+inc - if a==14 then - self:ResolveTimer("1","2","3") -- ... any number of arguments can be passed to the resolve handler - -- this will also automatically pause the object that it is binded to - end -end,.1) -loop:SetTime(1) -loop:OnTimerResolved(function(self,a,b,c) -- the handler will return the self and the passed arguments - print("We did it!",a,b,c) -end) -loop:OnTimedOut(function(self) - if not TheSecondTry then - print("Loop timed out!",self.Type,"Trying again...") - self:ResetTime(2) - self:Resume() - TheSecondTry=true - else - print("We just couldn't do it!") -- print if we don't get anything working - end -end) -multi:mainloop() -``` -# Output (Change the value inc as indicated in the comment to see the outcomes!) -Looping...
-Looping...
-Looping...
-Looping...
-Looping...
-Looping...
-Looping...
-Looping...
-Looping...
-Loop timed out! tloop Trying again...
-Looping...
-Looping...
-Looping...
-Looping...
-Looping...
-We did it! 1 2 3
- -Changes -------- -Update: 1.8.6 -------------- -Added: -- jobQueue:doToAll(function) -- jobQueue:start() is now required Call this after all calls to registerJob()'s. Calling it afterwards will not guarantee your next push job with that job will work. Not calling this will make pushing jobs impossible! -- Fixed a bug with love2d Threaded Queue -- Fixed some bugs -- Old versions of this library! It stems back from 2012 see rambling for more info... - -This will run said function in every thread. -```lua --- Going to use love2d code this time, almost the same as last time... See ramblings -require("core.Library") -GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library -require("core.GuiManager") -gui.ff.Color=Color.Black -jQueue=multi:newSystemThreadedJobQueue() -jQueue:registerJob("TEST_JOB",function(a,s) - math.randomseed(s) - TEST_JOB2() - return math.random(0,255) -end) -jQueue:registerJob("TEST_JOB2",function() - print("Test Works!") -end) --- 1.8.6 EXAMPLE Change -jQueue:start() -- This is now needed! --- -jQueue:doToAll(function() - print("Doing this 2? times!") -end) -tableOfOrder={} -jQueue.OnJobCompleted(function(JOBID,n) - tableOfOrder[JOBID]=n - if #tableOfOrder==10 then - t.text="We got all of the pieces!" - end -end) -for i=1,10 do -- Job Name of registered function, ... varargs - jQueue:pushJob("TEST_JOB","This is a test!",math.random(1,1000000)) -end -t=gui:newTextLabel("no done yet!",0,0,300,100) -t:centerX() -t:centerY() -``` -Update: 1.8.5 -------------- -Added: -- SystemThreadedExecute(cmd) - -Allows the execution of system calls without hold up. It is possible to do the same using io.popen()! You decide which works best for you! -```lua -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -cmd=multi:newSystemThreadedExecute("SystemThreadedExecuteTest.lua") -- This file is important! -cmd.OnCMDFinished(function(code) -- callback function to grab the exit code... Called when the command goes through - print("Got Code: "..code) -end) -multi:newTLoop(function() - print("...") -- lets show that we aren't being held up -end,1) -multi:mainloop() -``` -Update: 1.8.4 -------------- -Added: -- multi:newSystemThreadedJobQueue() -- Improved stability of the library -- Fixed a bug that made the benchmark and getload commands non-thread(coroutine) safe -- Tweaked the loveManager to help improve idle cpu usage -- Minor tweaks to the coroutine scheduling - -# Using multi:newSystemThreadedJobQueue() -First you need to create the object -This works the same way as love2d as it does with lanes... It is getting increasing harder to make both work the same way with speed in mind... Anyway... -```lua --- Creating the object using lanes manager to show case this. Examples has the file for love2d -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -jQueue=multi:newSystemThreadedJobQueue(n) -- this internally creates System threads. By defualt it will use the # of processors on your system You can set this number though. --- Only create 1 jobqueue! For now making more than 1 is buggy. You only really need one though. Just register new functions if you want 1 queue to do more. The one reason though is keeping track of jobIDs. I have an idea that I will roll out in the next update. -jQueue:registerJob("TEST_JOB",function(a,s) - math.randomseed(s) - -- We will push a random # - TEST_JOB2() -- You can call other registered functions as well! - return math.random(0,255) -- send the result to the main thread -end) -jQueue:registerJob("TEST_JOB2",function() - print("Test Works!") -- this is called from the job since it is registered on the same queue -end) -tableOfOrder={} -- This is how we will keep order of our completed jobs. There is no guarantee that the order will be correct -jQueue.OnJobCompleted(function(JOBID,n) -- whenever a job is completed you hook to the event that is called. This passes the JOBID folled by the returns of the job - -- JOBID is the completed job, starts at 1 and counts up by 1. - -- Threads finish at different times so jobids may be passed out of order! Be sure to have a way to order them - tableOfOrder[JOBID]=n -- we order ours by putting them into a table - if #tableOfOrder==10 then - print("We got all of the pieces!") - end -end) --- Lets push the jobs now -for i=1,10 do -- Job Name of registered function, ... varargs - jQueue:pushJob("TEST_JOB","This is a test!",math.random(1,1000000)) -end -print("I pushed all of the jobs :)") -multi:mainloop() -- Start the main loop :D -``` - -Thats it from this version! - -Update: 1.8.3 -------------- -Added:
-**New Mainloop functions** Below you can see the slight differences... Function overhead is not too bad in lua, but has a real difference. multi:mainloop() and multi:unprotectedMainloop() use the same algorithm yet the dedicated unprotected one is slightly faster due to having less function overhead. -- multi:mainloop()\* -- Bench: 16830003 Steps in 3 second(s)! -- multi:protectedMainloop() -- Bench: 16699308 Steps in 3 second(s)! -- multi:unprotectedMainloop() -- Bench: 16976627 Steps in 3 second(s)! -- multi:prioritizedMainloop1() -- Bench: 15007133 Steps in 3 second(s)! -- multi:prioritizedMainloop2() -- Bench: 15526248 Steps in 3 second(s)! - -\* The OG mainloop function remains the same and old methods to achieve what we have with the new ones still exist - -These new methods help by removing function overhead that is caused through the original mainloop function. The one downside is that you no longer have the flexiblity to change the processing during runtime. - -However there is a work around! You can use processes to run multiobjs as well and use the other methods on them. - -I may make a full comparison between each method and which is faster, but for now trust that the dedicated ones with less function overhead are infact faster. Not by much but still faster. :D - -Update: 1.8.2 -------------- -Added:
-- multi:newsystemThreadedTable(name) NOTE: Metatables are not supported in transfers. However there is a work around obj:init() that you see does this. Take a look in the multi/integration/shared/shared.lua files to see how I did it! -- Modified the GLOBAL metatable to sync before doing its tests -- multi._VERSION was multi.Version, felt it would be more consistant this way... I left the old way of getting the version just incase someone has used that way. It will eventually be gone. Also multi:getVersion() will do the job just as well and keep your code nice and update related bug free! -- Also everything that is included in the: multi/integration/shared/shared.lua (Which is loaded automatically) works in both lanes and love2d enviroments! - -The threaded table is setup just like the threaded queue.
-It provids GLOBAL like features without having to write to GLOBAL!
-This is useful for module creators who want to keep their data private, but also use GLOBAL like coding.
-It has a few features that makes it a bit better than plain ol GLOBAL (For now...) -(ThreadedTable - TT for short) -- TT:waitFor(name) -- TT:sync() -- TT["var"]=value -- print(TT["var"]) - -we also have the "sync" method, this one was made for love2d because we do a syncing trick to get data in a table format. The lanes side has a sync method as well so no worries. Using indexing calls sync once and may grab your variable. This allows you to have the lanes indexing 'like' syntax when doing regular indexing in love2d side of the module. As of right now both sides work flawlessly! And this effect is now the GLOBAL as well
- -On GLOBALS sync is a internal method for keeping the GLOBAL table in order. You can still use sThread.waitFor(name) to wait for variables that may of may not yet exist! - -Time for some examples: -# Using multi:newSystemThreadedTable(name) -```lua --- lanes Desktop lua! NOTE: this is in lanesintergratetest6.lua in the examples folder -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -test=multi:newSystemThreadedTable("YO"):init() -test["test1"]="lol" -multi:newSystemThread("test",function() - tab=sThread.waitFor("YO"):init() - print(tab:has("test1")) - sThread.sleep(3) - tab["test2"]="Whats so funny?" -end) -multi:newThread("test2",function() - print(test:waitFor("test2")) -end) -multi:mainloop() -``` - -```lua --- love2d gaming lua! NOTE: this is in main4.lua in the love2d examples -require("core.Library") -GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library -require("core.GuiManager") -gui.ff.Color=Color.Black -test=multi:newSystemThreadedTable("YO"):init() -test["test1"]="lol" -multi:newSystemThread("test",function() - tab=sThread.waitFor("YO"):init() - print(tab["test1"]) - sThread.sleep(3) - tab["test2"]="Whats so funny?" -end) -multi:newThread("test2",function() - print(test:waitFor("test2")) - t.text="DONE!" -end) -t=gui:newTextLabel("no done yet!",0,0,300,100) -t:centerX() -t:centerY() -``` - -Update: 1.8.1 -------------- -No real change!
-Changed the structure of the library. Combined the coroutine based threads into the core!
-Only compat and integrations are not part of the core and never will be by nature.
-This should make the library more convient to use.
-I left multi/all.lua file so if anyone had libraries/projects that used that it will still work!
-Updated from 1.7.6 to 1.8.0
(How much thread could a thread thread if a thread could thread thread?) -Added:
-- multi:newSystemThreadedQueue() -- multi:systemThreadedBenchmark() -- More example files -- multi:canSystemThread() -- true if an integration was added false otherwise (For module creation) -- Fixed a few bugs in the loveManager - -# Using multi:systemThreadedBenchmark() -```lua -package.path="?/init.lua;"..package.path -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -multi:systemThreadedBenchmark(3):OnBench(function(self,count) - print("First Bench: "..count) - multi:systemThreadedBenchmark(3,"All Threads: ") -end) -multi:mainloop() -``` - -# Using multi:newSystemThreadedQueue() -Quick Note: queues shared across multiple objects will be pulling from the same "queue" keep this in mind when coding! ~~Also the queue respects direction a push on the thread side cannot be popped on the thread side... Same goes for the mainthread!
~~ Turns out i was wrong about this... -```lua --- in love2d, this file will be in the same example folder as before, but is named main2.lua -require("core.Library") -GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library ---IMPORTANT --- Do not make the above local, this is the one difference that the lanesManager does not have --- If these are local the functions will have the upvalues put into them that do not exist on the threaded side --- You will need to ensure that the function does not refer to any upvalues in its code. It will print an error if it does though --- Also each thread has a .1 second delay! This is used to generate a random values for each thread! -require("core.GuiManager") -gui.ff.Color=Color.Black -function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a channel on both ends - local c={} - c.name=name - if love then - if love.thread then - function c:init() - self.chan=love.thread.getChannel(self.name) - function self:push(v) - self.chan:push(v) - end - function self:pop() - return self.chan:pop() - end - GLOBAL[self.name]=self - return self - end - return c - else - error("Make sure you required the love.thread module!") - end - else - c.linda=lanes.linda() - function c:push(v) - self.linda:send("Q",v) - end - function c:pop() - return ({self.linda:receive(0,"Q")})[2] - end - function c:init() - return self - end - GLOBAL[name]=c - end - return c -end -queue=multi:newSystemThreadedQueue("QUEUE"):init() -queue:push("This is a test") -queue:push("This is a test2") -queue:push("This is a test3") -queue:push("This is a test4") -multi:newSystemThread("test2",function() - queue=sThread.waitFor("QUEUE"):init() - data=queue:pop() - while data do - print(data) - data=queue:pop() - end - queue:push("DONE!") -end) -multi:newThread("test!",function() - thread.hold(function() return queue:pop() end) - t.text="Done!" -end) -t=gui:newTextLabel("no done yet!",0,0,300,100) -t:centerX() -t:centerY() -``` -# In Lanes -```lua --- The code is compatible with each other, I just wanted to show different things you can do in both examples --- This file can be found in the examples folder as lanesintegrationtest4.lua -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -queue=multi:newSystemThreadedQueue("QUEUE"):init() -queue:push("This is a test") -queue:push("This is a test2") -queue:push("This is a test3") -queue:push("This is a test4") -multi:newSystemThread("test2",function() - queue=sThread.waitFor("QUEUE"):init() - data=queue:pop() - while data do - print(data) - data=queue:pop() - end - queue:push("This is a test5") - queue:push("This is a test6") - queue:push("This is a test7") - queue:push("This is a test8") -end) -multi:newThread("test!",function() -- this is a lua thread - thread.sleep(.1) - data=queue:pop() - while data do - print(data) - data=queue:pop() - end -end) -multi:mainloop() -``` -Update: 1.7.6 -------------- -Fixed: -Typos like always -Added:
-multi:getPlatform() -- returns "love2d" if using the love2d platform or returns "lanes" if using lanes for threading
-examples files
-In Events added method setTask(func)
-The old way still works and is more convient to be honest, but I felt a method to do this was ok.
- -Updated: -some example files to reflect changes to the core. Changes allow for less typing
-loveManager to require the compat if used so you don't need 2 require line to retrieve the library
- -Update: 1.7.5 -------------- -Fixed some typos in the readme... (I am sure there are more there are always more)
-Added more features for module support
-TODO:
-Work on performance of the library... I see 3 places where I can make this thing run quicker
- -I'll show case some old versions of the multitasking library eventually so you can see its changes in days past!
- -Update: 1.7.4 -------------- -Added: the example folder which will be populated with more examples in the near future!
-The loveManager integration that mimics the lanesManager integration almost exactly to keep coding in both enviroments as close to possible. This is done mostly for library creation support!
-An example of the loveManager in action using almost the same code as the lanesintergreationtest2.lua
-NOTE: This code has only been tested to work on love2d version 1.10.2 thoough it should work version 0.9.0 -```lua -require("core.Library") -- Didn't add this to a repo yet! Will do eventually... Allows for injections and other cool things -require("multi.compat.love2d") -- allows for multitasking and binds my libraies to the love2d engine that i am using -GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager ---IMPORTANT --- Do not make the above local, this is the one difference that the lanesManager does not have --- If these are local the functions will have the upvalues put into them that do not exist on the threaded side --- You will need to ensure that the function does not refer to any upvalues in its code. It will print an error if it does though --- Also each thread has a .1 second delay! This is used to generate a random values for each thread! -require("core.GuiManager") -- allows the use of graphics in the program. -gui.ff.Color=Color.Black -function comma_value(amount) - local formatted = amount - while true do - formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') - if (k==0) then - break - end - end - return formatted -end -multi:newSystemThread("test1",function() -- Another difference is that the multi library is already loaded in the threaded enviroment as well as a call to multi:mainloop() - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 1"):OnBench(function(self,c) GLOBAL["T1"]=c multi:Stop() end) -end) -multi:newSystemThread("test2",function() -- spawns a thread in another lua process - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 2"):OnBench(function(self,c) GLOBAL["T2"]=c multi:Stop() end) -end) -multi:newSystemThread("test3",function() -- spawns a thread in another lua process - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 3"):OnBench(function(self,c) GLOBAL["T3"]=c multi:Stop() end) -end) -multi:newSystemThread("test4",function() -- spawns a thread in another lua process - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 4"):OnBench(function(self,c) GLOBAL["T4"]=c multi:Stop() end) -end) -multi:newSystemThread("test5",function() -- spawns a thread in another lua process - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 5"):OnBench(function(self,c) GLOBAL["T5"]=c multi:Stop() end) -end) -multi:newSystemThread("test6",function() -- spawns a thread in another lua process - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 6"):OnBench(function(self,c) GLOBAL["T6"]=c multi:Stop() end) -end) -multi:newSystemThread("Combiner",function() -- spawns a thread in another lua process - function comma_value(amount) - local formatted = amount - while true do - formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') - if (k==0) then - break - end - end - return formatted - end - local b=comma_value(tostring(sThread.waitFor("T1")+sThread.waitFor("T2")+sThread.waitFor("T3")+sThread.waitFor("T4")+sThread.waitFor("T5")+sThread.waitFor("T6"))) - GLOBAL["DONE"]=b -end) -multi:newThread("test0",function() - -- sThread.waitFor("DONE") -- lets hold the main thread completely so we don't eat up cpu - -- os.exit() - -- when the main thread is holding there is a chance that error handling on the system threads may not work! - -- instead we can do this - while true do - thread.skip(1) -- allow error handling to take place... Otherwise lets keep the main thread running on the low - -- Before we held just because we could... But this is a game and we need to have logic continue - --sThreadM.sleep(.001) -- Sleeping for .001 is a greeat way to keep cpu usage down. Make sure if you aren't doing work to rest. Abuse the hell out of GLOBAL if you need to :P - if GLOBAL["DONE"] then - t.text="Bench: "..GLOBAL["DONE"] - end - end -end) -GLOBAL["Bench"]=3 -t=gui:newTextLabel("no done yet!",0,0,300,100) -t:centerX() -t:centerY() -``` -Update: 1.7.3 -------------- -Changed how requiring the library works! -`require("multi.all")` Will still work as expected; however, with the exception of threading, compat, and integrations everything else has been moved into the core of the library. -```lua --- This means that these are no longer required and will cause an error if done so -require("multi.loop") -require("multi.alarm") -require("multi.updater") -require("multi.tloop") -require("multi.watcher") -require("multi.tstep") -require("multi.step") -require("multi.task") --- ^ they are all part of the core now -``` - -Update: 1.7.2 -------------- -Moved updaters, loops, and alarms into the init.lua file. I consider them core features and they are referenced in the init.lua file so they need to exist there. Threaded versions are still separate though. Added another example file - -Update: 1.7.1 Bug Fixes Only -------------- - -Update: 1.7.0 -------------- -Modified: multi.integration.lanesManager.lua -It is now in a stable and simple state Works with the latest lanes version! Tested with version 3.11 I cannot promise that everything will work with eariler versions. Future versions are good though.
-Example Usage:
-sThread is a handle to a global interface for system threads to interact with themself
-thread is the interface for multithreads as seen in the threading section
- -GLOBAL a table that can be used throughout each and every thread - -sThreads have a few methods
-sThread.set(name,val) -- you can use the GLOBAL table instead modifies the same table anyway
-sThread.get(name) -- you can use the GLOBAL table instead modifies the same table anyway
-sThread.waitFor(name) -- waits until a value exists, if it does it returns it
-sThread.getCores() -- returns the number of cores on your cpu
-sThread.sleep(n) -- sleeps for a bit stopping the entire thread from running
-sThread.hold(n) -- sleeps until a condition is met
-```lua -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -require("multi.all") -multi:newAlarm(2):OnRing(function(self) - GLOBAL["NumOfCores"]=sThread.getCores() -end) -multi:newAlarm(7):OnRing(function(self) - GLOBAL["AnotherTest"]=true -end) -multi:newAlarm(13):OnRing(function(self) - GLOBAL["FinalTest"]=true -end) -multi:newSystemThread("test",function() -- spawns a thread in another lua process - require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the integration. You would need to require the interaction again though - print("Waiting for variable: NumOfCores") - print("Got it: ",sThread.waitFor("NumOfCores")) - sThread.hold(function() - return GLOBAL["AnotherTest"] -- note this would hold the entire systemthread. Spawn a coroutine thread using multi:newThread() or multi:newThreaded... - end) - print("Holding works!") - multi:newThread("tests",function() - thread.hold(function() - return GLOBAL["FinalTest"] -- note this will not hold the entire systemthread. As seen with the TLoop constantly going! - end) - print("Final test works!") - os.exit() - end) - local a=0 - multi:newTLoop(function() - a=a+1 - print(a) - end,.5) - multi:mainloop() -end) -multi:mainloop() -``` - -Update: 1.6.0 -------------- -Changed: steps and loops -```lua --- Was -step:OnStep(function(pos,self) -- same goes for tsteps as well - print(pos) -end) -multi:newLoop(function(dt,self) - print(dt) -end) --- Is now -step:OnStep(function(self,pos) -- same goes for tsteps as well - print(pos) -end) -multi:newLoop(function(self,dt) - print(dt) -end) -``` -Reasoning I wanted to keep objects consistant, but a lot of my older libraries use the old way of doing things. Therefore I added a backwards module -```lua -require("multi.all") -require("multi.compat.backwards[1,5,0]") -- allows for the use of features that were scrapped/changed in 1.6.0+ -``` -Update: 1.5.0 -------------- -Added: -- An easy way to manage timeouts -- Small bug fixes - -Update: 1.4.1 - First Public release of the library -------------- - -IMPORTANT:
-Every update I make aims to make things simpler more efficent and just better, but a lot of old code, which can be really big, uses a lot of older features. I know the pain of having to rewrite everything. My promise to my library users is that I will always have backwards support for older features! New ways may exist that are quicker and eaiser, but the old features/methods will be supported.
-Rambling --------- -Love2d Sleeping reduces the cpu time making my load detection think the system is under more load, thus preventing it from sleeping... I will look into other means. As of right now it will not eat all of your cpu if threads are active. For now I suggest killing threads that aren't needed anymore. On lanes threads at idle use 0% cpu and it is amazing. A state machine may solve what I need though. One state being idle state that sleeps and only goes into the active state if a job request or data is sent to it... after some time of not being under load it wil switch back into the idle state... We'll see what happens. - -Love2d doesn't like to send functions through channels. By defualt it does not support this. I achieve this by dumping the function and loadstring it on the thread. This however is slow. For the System Threaded Job Queue I had to change my original idea of sending functions as jobs. The current way you do it now is register a job functions once and then call that job across the thread through a queue. Each worker thread pops from the queue and returns the job. The Job ID is automatically updated and allows you to keep track of the order that the data comes in. A table with # indexes can be used to originze the data... - -In regards to benchmarking. If you see my bench marks and are wondering they are 10x better its because I am using luajit for my tests. I highly recommend using luajit for my library, but lua 5.1 will work just as well, but not as fast. - -So while working on the jobQueue:doToAll() method I figured out why love2d's threaded tables were acting up when more than 1 thread was sharing the table. It turns out 1 thread was eating all of the pops from the queue and starved all of the other queues... Ill need to use the same trick I did with GLOBAL to fix the problem... However at the rate I am going threading in love will become way slower. I might use the regualr GLOBAL to manage data internally for threadedtables... - -It has been awhile since I had to bring out the Multi Functions... Syncing within threads are a pain! I had no idea what a task it would be to get something as simple as syncing data was going to be... I will probably add a SystemThreadedSyncer in the future because it will make life eaiser for you guys as well. SystemThreadedTables are still not going to work on love2d, but will work fine on lanes... I have a solution and it is being worked on... Depending on when I pust the next update to this library the second half of this ramble won't apply anymore - -I have been using this (EventManager --> MultiManager --> now multi) for my own purposes and started making this when I first started learning lua. You are able to see how the code changed and evolved throughout the years. I tried to include all the versions that still existed on my HDD. - -I added my old versions to this library... It started out as the EventManager and was kinda crappy but it was the start to this library. It kept getting better and better until it became what it is today. There are some features that nolonger exist in the latest version, but they were remove because they were useless... I added these files to the github so for those interested can see into my mind in a sense and see how I developed the library before I used github. - -The first version of the EventManager was function based not object based and benched at about 2000 steps per second... Yeah that was bad... I used loadstring and it was a mess... Take a look and see how it grew throughout the years I think it may intrest some of you guys! diff --git a/mulit/examples/SystemThreadedExecuteTest.lua b/mulit/examples/SystemThreadedExecuteTest.lua deleted file mode 100644 index 2b830d3..0000000 --- a/mulit/examples/SystemThreadedExecuteTest.lua +++ /dev/null @@ -1,6 +0,0 @@ -package.path="?/init.lua;"..package.path -require("multi") -multi:newAlarm(5):OnRing(function() - os.exit(10) -end) -multi:mainloop() diff --git a/mulit/examples/alarmTest.lua b/mulit/examples/alarmTest.lua deleted file mode 100644 index 632a8ee..0000000 --- a/mulit/examples/alarmTest.lua +++ /dev/null @@ -1,11 +0,0 @@ --- Tick Tock Example -require("multi") -alarm=multi:newAlarm(1) -alarm.state=-1 -- set the state to -1 -alarm.sounds={[-1]="Tick",[1]="Tock"} -- this makes changing between states easy and fast -alarm:OnRing(function(self) - print(self.sounds[self.state]) - self.state=self.state*-1 -- change the state in one line - self:Reset() -- Reset the alarm so it runs again -end) -multi:mainloop() diff --git a/mulit/examples/compattest.lua b/mulit/examples/compattest.lua deleted file mode 100644 index 2edc13e..0000000 --- a/mulit/examples/compattest.lua +++ /dev/null @@ -1,7 +0,0 @@ -package.path="?/init.lua;"..package.path -require("multi") -require("multi.compat.backwards[1,5,0]") -multi:newLoop(function(dt,self) - print(dt) -end) -multi:mainloop() -- start the main runner diff --git a/mulit/examples/lanesintegratetest.lua b/mulit/examples/lanesintegratetest.lua deleted file mode 100644 index 820385c..0000000 --- a/mulit/examples/lanesintegratetest.lua +++ /dev/null @@ -1,34 +0,0 @@ -package.path="?/init.lua;?.lua;"..package.path -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -multi:newAlarm(2):OnRing(function(self) - GLOBAL["NumOfCores"]=sThread.getCores() -end) -multi:newAlarm(7):OnRing(function(self) - GLOBAL["AnotherTest"]=true -end) -multi:newAlarm(13):OnRing(function(self) - GLOBAL["FinalTest"]=true -end) -multi:newSystemThread("test",function() -- spawns a thread in another lua process - require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though - print("Waiting for variable: NumOfCores") - print("Got it: ",sThread.waitFor("NumOfCores")) - sThread.hold(function() - return GLOBAL["AnotherTest"] -- note this would hold the entire systemthread. Spawn a coroutine thread using multi:newThread() or multi:newThreaded... - end) - print("Holding works!") - multi:newThread("tests",function() - thread.hold(function() - return GLOBAL["FinalTest"] -- note this will not hold the entire systemthread. As seen with the TLoop constantly going! - end) - print("Final test works!") - os.exit() - end) - local a=0 - multi:newTLoop(function() - a=a+1 - print(a) - end,.5) - multi:mainloop() -end) -multi:mainloop() diff --git a/mulit/examples/lanesintegratetest2.lua b/mulit/examples/lanesintegratetest2.lua deleted file mode 100644 index ecaf091..0000000 --- a/mulit/examples/lanesintegratetest2.lua +++ /dev/null @@ -1,59 +0,0 @@ -package.path="?/init.lua;?.lua;"..package.path -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -- loads the lanesManager and includes the entire multi library -local function comma_value(amount) - local formatted = amount - while true do - formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') - if (k==0) then - break - end - end - return formatted -end -multi:newSystemThread("test1",function() -- spawns a thread in another lua process - require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 1"):OnBench(function(self,c) GLOBAL["T1"]=c multi:Stop() end) - multi:mainloop() -end) -multi:newSystemThread("test2",function() -- spawns a thread in another lua process - require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 2"):OnBench(function(self,c) GLOBAL["T2"]=c multi:Stop() end) - multi:mainloop() -end) -multi:newSystemThread("test3",function() -- spawns a thread in another lua process - require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 3"):OnBench(function(self,c) GLOBAL["T3"]=c multi:Stop() end) - multi:mainloop() -end) -multi:newSystemThread("test4",function() -- spawns a thread in another lua process - require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 4"):OnBench(function(self,c) GLOBAL["T4"]=c multi:Stop() end) - multi:mainloop() -end) -multi:newSystemThread("test5",function() -- spawns a thread in another lua process - require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 5"):OnBench(function(self,c) GLOBAL["T5"]=c multi:Stop() end) - multi:mainloop() -end) -multi:newSystemThread("test6",function() -- spawns a thread in another lua process - require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 6"):OnBench(function(self,c) GLOBAL["T6"]=c multi:Stop() end) - multi:mainloop() - print("Bench: ",comma_value(tostring(sThread.waitFor("T1")+sThread.waitFor("T2")+sThread.waitFor("T3")+sThread.waitFor("T4")+sThread.waitFor("T5")+sThread.waitFor("T6")))) - GLOBAL["DONE"]=true -end) -multi:newThread("test0",function() - -- sThread.waitFor("DONE") -- lets hold the main thread completely so we don't eat up cpu - -- os.exit() - -- when the main thread is holding there is a chance that error handling on the system threads may not work! - -- instead we can do this - while true do - thread.skip(1) -- allow error handling to take place... Otherwise lets keep the main thread running on the low - sThread.sleep(.001) -- Sleeping for .001 is a greeat way to keep cpu usage down. Make sure if you aren't doing work to rest. Abuse the hell out of GLOBAL if you need to :P - if GLOBAL["DONE"] then - os.exit() - end - end -end) -GLOBAL["Bench"]=60 -multi:mainloop() diff --git a/mulit/examples/lanesintegratetest3.lua b/mulit/examples/lanesintegratetest3.lua deleted file mode 100644 index e83d6f5..0000000 --- a/mulit/examples/lanesintegratetest3.lua +++ /dev/null @@ -1,48 +0,0 @@ -package.path="?/init.lua;?.lua;"..package.path -- Spawing threads using 1 method and the sThread.getCores() function! -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -- loads the lanesManager and includes the entire multi library -local function comma_value(amount) - local formatted = amount - while true do - formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') - if (k==0) then - break - end - end - return formatted -end -GLOBAL["BENCHCOUNT"],GLOBAL["CNUM"],GLOBAL["DONE"]=0,0,0 -cores=sThread.getCores() -function benchmark() -- our single function that will be used across a bunch of threads - require("multi.all") -- get the library - local n=GLOBAL["CNUM"]; GLOBAL["CNUM"]=n+1 -- do some math so we can identify which thread is which - multi:benchMark(sThread.waitFor("BENCH"),nil,"Thread "..n+1):OnBench(function(self,c) GLOBAL["BENCHCOUNT"]=GLOBAL["BENCHCOUNT"]+c; GLOBAL["DONE"]=GLOBAL["DONE"]+1; multi:Stop() end) - -- ^ do the bench mark and add to the BENCHCOUNT GLOBAL value, then increment the DONE Value - multi:mainloop() -end -for i=1,cores do -- loop based on the number of cores you have - multi:newSystemThread("test"..i,benchmark) -- create a system thread based on the benchmark -end -multi:newThread("test0",function() - while true do - thread.skip(1) - sThread.sleep(.001) - if GLOBAL["DONE"]==cores then - print(comma_value(tostring(GLOBAL["BENCHCOUNT"]))) - os.exit() - end - end -end) -GLOBAL["BENCH"]=10 -print("Platform is: ",multi:getPlatform()) -- returns love2d or lanes depending on which platform you are using... If I add more intergrations then this method will be updated! corona sdk may see this library in the future... -multi:mainloop() ---[[ Output on my machine! I am using luajit and have 6 cores on my computer. Your numbers will vary, but it should look something like this -Intergrated Lanes! -Platform is: lanes -Thread 1 62442125 Steps in 10 second(s)! -Thread 2 61379095 Steps in 10 second(s)! -Thread 3 62772502 Steps in 10 second(s)! -Thread 4 62740684 Steps in 10 second(s)! -Thread 5 60926715 Steps in 10 second(s)! -Thread 6 61793175 Steps in 10 second(s)! -372,054,296 -]] diff --git a/mulit/examples/lanesintegratetest4.lua b/mulit/examples/lanesintegratetest4.lua deleted file mode 100644 index 40be2c4..0000000 --- a/mulit/examples/lanesintegratetest4.lua +++ /dev/null @@ -1,27 +0,0 @@ -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -queue=multi:newSystemThreadedQueue("QUEUE"):init() -queue:push("This is a test") -queue:push("This is a test2") -queue:push("This is a test3") -queue:push("This is a test4") -multi:newSystemThread("test2",function() - queue=sThread.waitFor("QUEUE"):init() - data=queue:pop() - while data do - print(data) - data=queue:pop() - end - queue:push("This is a test5") - queue:push("This is a test6") - queue:push("This is a test7") - queue:push("This is a test8") -end) -multi:newThread("test!",function() -- this is a lua thread - thread.sleep(.1) - data=queue:pop() - while data do - print(data) - data=queue:pop() - end -end) -multi:mainloop() diff --git a/mulit/examples/lanesintegratetest5.lua b/mulit/examples/lanesintegratetest5.lua deleted file mode 100644 index 7e0898a..0000000 --- a/mulit/examples/lanesintegratetest5.lua +++ /dev/null @@ -1,28 +0,0 @@ -package.path="?/init.lua;"..package.path -- slightly different usage of the code -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -queue=multi:newSystemThreadedQueue("QUEUE") -queue:push(1) -queue:push(2) -queue:push(3) -queue:push(4) -queue:push(5) -queue:push(6) -multi:newSystemThread("STHREAD_1",function() - queue=sThread.waitFor("QUEUE"):init() - GLOBAL["QUEUE"]=nil - data=queue:pop() - while data do - print(data) - data=queue:pop() - end -end) -multi:newThread("THREAD_1",function() - while true do - if GLOBAL["QUEUE"]==nil then - print("Deleted a Global!") - break - end - thread.skip(1) - end -end) -multi:mainloop() diff --git a/mulit/examples/lanesintegratetest6.lua b/mulit/examples/lanesintegratetest6.lua deleted file mode 100644 index 5b7443c..0000000 --- a/mulit/examples/lanesintegratetest6.lua +++ /dev/null @@ -1,14 +0,0 @@ --- lanes Desktop lua! NOTE: this is in lanesintergratetest6.lua in the examples folder -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -test=multi:newSystemThreadedTable("YO"):init() -test["test1"]="lol" -multi:newSystemThread("test",function() - tab=sThread.waitFor("YO"):init() - print(tab["test1"]) - sThread.sleep(3) - tab["test2"]="Whats so funny?" -end) -multi:newThread("test2",function() - print(test:waitFor("test2")) -end) -multi:mainloop() diff --git a/mulit/examples/lanesintegratetest7.lua b/mulit/examples/lanesintegratetest7.lua deleted file mode 100644 index a77c05b..0000000 --- a/mulit/examples/lanesintegratetest7.lua +++ /dev/null @@ -1,29 +0,0 @@ --- Creating the object using lanes manager to show case this. Examples has the file for love2d -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -jQueue=multi:newSystemThreadedJobQueue(n) -- this internally creates System threads. By defualt it will use the # of processors on your system You can set this number though. --- Only create 1 jobqueue! For now making more than 1 is buggy. You only really need one though. Just register new functions if you want 1 queue to do more. The one reason though is keeping track of jobIDs. I have an idea that I will roll out in the next update. -jQueue:registerJob("TEST_JOB",function(a,s) - math.randomseed(s) - -- We will push a random # - TEST_JOB2() -- You can call other registered functions as well! - return math.random(0,255) -- send the result to the main thread -end) -jQueue:registerJob("TEST_JOB2",function() - print("Test Works!") -- this is called from the job since it is registered on the same queue -end) -jQueue:start() -tableOfOrder={} -- This is how we will keep order of our completed jobs. There is no guarantee that the order will be correct -jQueue.OnJobCompleted(function(JOBID,n) -- whenever a job is completed you hook to the event that is called. This passes the JOBID folled by the returns of the job - -- JOBID is the completed job, starts at 1 and counts up by 1. - -- Threads finish at different times so jobids may be passed out of order! Be sure to have a way to order them - tableOfOrder[JOBID]=n -- we order ours by putting them into a table - if #tableOfOrder==10 then - print("We got all of the pieces!") - end -end) --- LEts push the jobs now -for i=1,10 do -- Job Name of registered function, ... varargs - jQueue:pushJob("TEST_JOB","This is a test!",math.random(1,1000000)) -end -print("I pushed all of the jobs :)") -multi:mainloop() -- Start the main loop :D diff --git a/mulit/examples/lanesintegratetest8.lua b/mulit/examples/lanesintegratetest8.lua deleted file mode 100644 index c64586a..0000000 --- a/mulit/examples/lanesintegratetest8.lua +++ /dev/null @@ -1,11 +0,0 @@ -package.path="../?.lua;../?/init.lua;"..package.path -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -cmd=multi:newSystemThreadedExecute("SystemThreadedExecuteTest.lua") -- This file is important! -cmd.OnCMDFinished(function(code) -- callback function to grab the exit code... Called when the command goes through - print("Got Code: "..code) -end) -multi:newTLoop(function() - print("...") -end,1) -multi:mainloop() - diff --git a/mulit/examples/lanesintegratetest9.lua b/mulit/examples/lanesintegratetest9.lua deleted file mode 100644 index eac0284..0000000 --- a/mulit/examples/lanesintegratetest9.lua +++ /dev/null @@ -1,26 +0,0 @@ -package.path="?/init.lua;"..package.path -local GLOBAL,sThread=require("multi.integration.lanesManager").init() -jQueue=multi:newSystemThreadedJobQueue(n) -jQueue:registerJob("TEST_JOB",function(a,s) - math.randomseed(s) - TEST_JOB2() - return math.random(0,255) -end) -jQueue:registerJob("TEST_JOB2",function() - print("Test Works!") -end) -jQueue:start() -jQueue:doToAll(function() - print("Doing this 6? times!") -end) -for i=1,10 do -- Job Name of registered function, ... varargs - jQueue:pushJob("TEST_JOB","This is a test!",math.random(1,1000000)) -end -tableOfOrder={} -jQueue.OnJobCompleted(function(JOBID,n) - tableOfOrder[JOBID]=n - if #tableOfOrder==10 then - print("We got all of the pieces!") - end -end) -multi:mainloop() diff --git a/mulit/examples/loopTest.lua b/mulit/examples/loopTest.lua deleted file mode 100644 index 138d8ba..0000000 --- a/mulit/examples/loopTest.lua +++ /dev/null @@ -1,9 +0,0 @@ --- like the while loop (kinda) -require("multi") -loop=multi:newLoop(function(self,dt) - if dt>10 then - print("Enough time has passed!") - self:Break() -- lets break this thing - end -end) -multi:mainloop() diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Core/Clickable.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Core/Clickable.int deleted file mode 100644 index f192d8e..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Core/Clickable.int +++ /dev/null @@ -1,15 +0,0 @@ -function gui:Clickable() - local x,y,w,h=love.graphics.getScissor() - local mx=love.mouse.getX() - local my=love.mouse.getY() - if _GuiPro.HasStencel then - local obj=_GuiPro.StencelHolder - if self:isDescendant(obj) then - return math.sqrt((mx-obj.x)^2+(my-obj.y)^2)<=(obj.offset.size.x or 0) - end - end - if not(x) then - return true - end - return not(mx>x+w or mxy+h or myx+w or mxy+h or my self.x and x < self.x+self.width and y > self.y and y < self.y+self.height and self:TClickable(x,y) and self:eventable()) - end - end - self.id=-1 -end -multi:newTask(function() -- A bit of post-loading haha - gui.touchpressed=multi:newConnection() - gui.touchreleased=multi:newConnection() - gui.touchmoved=multi:newConnection() - love.touchpressed=Library.convert(love.touchpressed or function() end) - love.touchreleased=Library.convert(love.touchreleased or function() end) - love.touchmoved=Library.convert(love.touchmoved or function() end) - love.touchpressed:inject(function(id, x, y, dx, dy, pressure) gui.touchpressed:Fire(id, x, y, dx, dy, pressure) return {id, x, y, dx, dy, pressure} end,1) - love.touchreleased:inject(function(id, x, y, dx, dy, pressure) gui.touchreleased:Fire(id, x, y, dx, dy, pressure) return {id, x, y, dx, dy, pressure} end,1) - love.touchmoved:inject(function(id, x, y, dx, dy, pressure) gui.touchmoved:Fire(id, x, y, dx, dy, pressure) return {id, x, y, dx, dy, pressure} end,1) - _GuiPro.TouchReady=true - _GuiPro.TouchRegister={} - gui.touchpressed:connect(function(id, x, y, dx, dy, pressure) - for i,v in pairs(_GuiPro.TouchRegister) do - if #v.tid==0 then - if (x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable()) then - v:addTID(id) - v.touchcount=1 - for i=1,#v.ToFuncP do - v.ToFuncP[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) - end - end - elseif not(v:hasTID(id)) then - if (x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable()) then - v:addTID(id) - v.touchcount=v.touchcount+1 - for i=1,#v.ToFuncP do - v.ToFuncP[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) - end - end - end - end - end) - gui.touchreleased:connect(function(id, x, y, dx, dy, pressure) - for i,v in pairs(_GuiPro.TouchRegister) do - if v:hasTID(id) then - v:removeTID(id) - for i=1,#v.ToFuncR do - v.ToFuncR[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) - end - end - end - end) - gui.touchmoved:connect(function(id, x, y, dx, dy, pressure) - for i,v in pairs(_GuiPro.TouchRegister) do - if v:hasTID(id) and (x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable()) then - for i=1,#v.ToFuncM do - v.ToFuncM[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) - end - elseif v:hasTID(id) and not((x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable())) then - v:removeTID(id) - for i=1,#v.ToFuncR do - v.ToFuncR[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) - end - end - end - end) -end) --- now that that is done lets set up some more post loading checks -_GuiPro.int=multi:newProcess() -_GuiPro.int:Start() -_GuiPro.int:setJobSpeed(.001) -_GuiPro.EXACT=0 -_GuiPro.LAX=.01 -_GuiPro.LAZY=.05 --- now lets define the reg function -function gui.Compare(a,b,v,tp) - if tp==">" then - if (a+v>b or a-v>b) then - return true - end - elseif tp=="<" then - if (a+v=" then - if (a+v>=b or a-v>=b) then - return true - end - elseif tp=="==" then -- this one is gonna be tricky - if (a>=b-v and a<=b+v) or (b>=a-v and b<=a+v) then - return true - end - end - return false -end -function gui:regesterTouch() - local obj=self - obj.ToFuncP={} - obj.ToFuncM={} - obj.ToFuncR={} - obj.To2Func={} - obj.ToDTFunc={} - obj.touchRendering =_GuiPro.EXACT -- exact(0), lax(), # - function obj:removeTID(id) - for i=1,#self.tid do - if self.tid[i]==id then - table.remove(self.tid,i) - self.touchcount=self.touchcount-1 - return - end - end - end - function obj:hasTID(id) - for i=1,#self.tid do - if self.tid[i]==id then - return true - end - end - return false - end - obj.txl1=0 - obj.tyl1=0 - obj.txl2=0 - obj.tyl2=0 - obj.LS=0 - obj:OnUpdate(function(self) - if self.touchcount==2 then - local x1,y1=love.touch.getPosition( self.tid[1] ) - local x2,y2=love.touch.getPosition( self.tid[2] ) - local CS=math.sqrt((x2-x1)^2+(y2-y1)^2) - if gui.Compare(CS,self.LS,self.touchRendering,">") then - for i=1,#self.To2Func do - self.To2Func[i](self,CS,x1-self.x,y1-self.y,x2-self.x,y2-self.y) - end - elseif gui.Compare(CS,self.LS,self.touchRendering,"<") then - for i=1,#self.To2Func do - self.To2Func[i](self,-CS,x1-self.x,y1-self.y,x2-self.x,y2-self.y) - end - elseif gui.Compare(CS,self.LS,self.touchRendering,"==") then - for i=1,#self.To2Func do - self.To2Func[i](self,0,x1-self.x,y1-self.y,x2-self.x,y2-self.y) - end - end - -- if self.txl1~=x1 or self.txl2~=x2 or self.tyl1~=y1 or self.tyl2~=y2 then - -- for i=1,#self.To2Func do - -- self.To2Func[i](self,0,x1-self.x,y1-self.y,x2-self.x,y2-self.y) - -- end - -- end - self.LS=CS - self.txl1=x1 - self.txl2=x2 - self.tyl1=y1 - self.tyl2=y2 - end - end) - function obj:OnDoubleTap(func) - table.insert(self.ToDTFunc,func) - end - function obj:On2TouchMoved(func) - table.insert(self.To2Func,func) - end - function obj:addTID(id) - table.insert(self.tid,id) - end - function obj:OnTouchPressed(func) - table.insert(self.ToFuncP,func) -- event for touches - end - function obj:OnTouchReleased(func) -- event for touches - table.insert(self.ToFuncR,func) - end - function obj:OnTouchMoved(func) -- event for touches - table.insert(self.ToFuncM,func) - end - if _GuiPro.TouchReady then -- my sneaky test - print("Registred: "..tostring(obj)) - table.insert(_GuiPro.TouchRegister,obj) - else - print("Attempting to register: "..tostring(obj)) - _GuiPro.int:newJob(function() table.insert(_GuiPro.TouchRegister,obj) end) -- a sneaky way to ensure that your object gets registered eventually, even if you call the method before the touch patch was activated. - end -end diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/AddDrawRuleB.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/AddDrawRuleB.int deleted file mode 100644 index 5510a3d..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/AddDrawRuleB.int +++ /dev/null @@ -1,4 +0,0 @@ -function gui:AddDrawRuleB(rule) - if not(self.DrawRulesB) then self.DrawRulesB={} end - table.insert(self.DrawRulesB,rule) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/AddDrawRuleE.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/AddDrawRuleE.int deleted file mode 100644 index a025f89..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/AddDrawRuleE.int +++ /dev/null @@ -1,4 +0,0 @@ -function gui:AddDrawRuleE(rule) - if not(self.DrawRulesE) then self.DrawRulesE={} end - table.insert(self.DrawRulesE,rule) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/draw.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/draw.int deleted file mode 100644 index d0b2404..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/draw.int +++ /dev/null @@ -1,12 +0,0 @@ -function gui:draw() - if _GuiPro.rotate~=0 then - love.graphics.rotate(math.rad(_GuiPro.rotate)) - end - if self.FormFactor:lower()=="rectangle" then - self:drawR() - elseif self.FormFactor:lower()=="circle" then - self:drawC() - else - error("Unsupported FormFactor: "..self.FormFactor.."!") - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/drawC.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/drawC.int deleted file mode 100644 index 22782ed..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/drawC.int +++ /dev/null @@ -1,89 +0,0 @@ -function gui:drawC() - if love.mouse.isDown("l")==false and love.mouse.isDown("m")==false and love.mouse.isDown("r")==false then - _GuiPro.DragItem={} - _GuiPro.hasDrag=false - end - if self.Visible==true and self.VIS==true then - local b=true - for i,v in pairs(_GuiPro.Clips) do - if self:isDescendant(v)==true then - b=false - end - end - if b then - love.graphics.setStencilTest( ) - _GuiPro.HasStencel=false - _GuiPro.StencelHolder=nil - end - local x,y,r,s=(self.offset.pos.x or 0)+self.Parent.x,(self.offset.pos.y or 0)+self.Parent.y,self.offset.size.x or 0,self.offset.size.y or 360 - if self.CC then - x,y=x+r,y+r - end - self.x,self.y=x,y - _GuiPro.circleStencilFunction = function() - love.graphics.circle("fill",x,y,r,s) - end - if math.sqrt((love.mouse.getX()-x)^2+(love.mouse.getY()-y)^2)<=r and self:eventable() and self:Clickable() and self.Active==true then - self.hovering=true - if love.mouse.isDown("l") and _GuiPro.hasDrag==false then - if string.find(self.Type, "Button") then - love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.lclicked=true - elseif love.mouse.isDown("r") and _GuiPro.hasDrag==false then - if string.find(self.Type, "Button") then - love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.rclicked=true - elseif love.mouse.isDown("m") and _GuiPro.hasDrag==false then - if string.find(self.Type, "Button") then - love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.mclicked=true - else - if string.find(self.Type, "Button") and _GuiPro.hasDrag==false then - love.graphics.setColor(self.Color[1]-5, self.Color[2]-5, self.Color[3]-5,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.rclicked=false - self.lclicked=false - self.mclicked=false - end - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - self.hovering=false - self.rclicked=false - self.lclicked=false - self.mclicked=false - end - if self.ClipDescendants==true then - _GuiPro.Clips[tostring(self)]=self - _GuiPro.HasStencel=true - _GuiPro.StencelHolder=self - love.graphics.stencil(_GuiPro.circleStencilFunction) - love.graphics.setStencilTest("notequal",0) - end - love.graphics.circle("fill",x,y,r,s) - love.graphics.setColor(self.BorderColor[1], self.BorderColor[2], self.BorderColor[3],self.BorderVisibility*254) - for b=0,self.BorderSize-1 do - love.graphics.circle("line",x,y,r+b,s) - end - if string.find(self.Type, "Text") then - if self.text~=nil then - if self.AutoScaleText then - self.FontSize=math.floor(self.height/1.45833) - end - love.graphics.setColor(self.TextColor[1],self.TextColor[2],self.TextColor[3],self.TextVisibility*254) - love.graphics.setFont(self.Font) - love.graphics.printf(self.text, x-(r/2)+(self.XTween), y-(r/2)+self.Tween, r, self.TextFormat) - end - end - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/drawR.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/drawR.int deleted file mode 100644 index ad4297b..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Drawing/drawR.int +++ /dev/null @@ -1,118 +0,0 @@ -function gui:drawR() - if love.mouse.isDown("l")==false and love.mouse.isDown("m")==false and love.mouse.isDown("r")==false then - _GuiPro.DragItem={} - _GuiPro.hasDrag=false - end - if self.Visible==true and self.VIS==true then - local b=true - for i,v in pairs(_GuiPro.Clips) do - if self:isDescendant(v)==true then - b=false - end - end - if b==true then - love.graphics.setStencilTest() - love.graphics.setScissor() - end - self.x=(self.Parent.width*self.scale.pos.x)+self.offset.pos.x+self.Parent.x - self.y=(self.Parent.height*self.scale.pos.y)+self.offset.pos.y+self.Parent.y - self.width=(self.Parent.width*self.scale.size.x)+self.offset.size.x - self.height=(self.Parent.height*self.scale.size.y)+self.offset.size.y - if self.DrawRulesB then - for dr=1,#self.DrawRulesB do - self.DrawRulesB[dr](self) - end - end - if (love.mouse.getX() > self.x and love.mouse.getX() < self.x+self.width and love.mouse.getY() > self.y and love.mouse.getY() < self.y+self.height and self:Clickable() and self:eventable()) or self:touchable("r") and self.Active==true then - self.hovering=true - if love.mouse.isDown("l") or self:touchable("r") and _GuiPro.hasDrag==false then - if string.find(self.Type, "Button") then - love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.lclicked=true - elseif love.mouse.isDown("r") or self:touchable("r") and _GuiPro.hasDrag==false then - if string.find(self.Type, "Button") then - love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.rclicked=true - elseif love.mouse.isDown("m") or self:touchable("r") and _GuiPro.hasDrag==false then - if string.find(self.Type, "Button") then - love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.mclicked=true - else - if string.find(self.Type, "Button") or self:touchable("r") and _GuiPro.hasDrag==false then - love.graphics.setColor(self.Color[1]-5, self.Color[2]-5, self.Color[3]-5,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.rclicked=false - self.lclicked=false - self.mclicked=false - end - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - self.hovering=false - self.rclicked=false - self.lclicked=false - self.mclicked=false - end - if self.ClipDescendants==true then - _GuiPro.Clips[tostring(self)]=self - love.graphics.setScissor(self.x, self.y, self.width, self.height) - end - if self:hasRoundness() then - love.graphics.stencil(self.stfunc, "replace", 1) - love.graphics.setStencilTest("greater", 0) - end - love.graphics.rectangle("fill", self.x, self.y, self.width, self.height,(self.rx or 1)*self.DPI,(self.ry or 1)*self.DPI,(self.segments or 1)*self.DPI) - if string.find(self.Type, "Image") then - self:ImageRule() - end - if self.Type=="Video" then - self:VideoRule() - end - if self:hasRoundness() then - love.graphics.setStencilTest() - end - love.graphics.setColor(self.BorderColor[1], self.BorderColor[2], self.BorderColor[3],self.BorderVisibility*254) - for b=0,self.BorderSize-1 do - love.graphics.rectangle("line", self.x-(b/2), self.y-(b/2), self.width+b, self.height+b,(self.rx or 1)*self.DPI,(self.ry or 1)*self.DPI,(self.segments or 1)*self.DPI) - end - if string.find(self.Type, "Text") then - if self.text~=nil then - if self.AutoScaleText then - self.FontSize=math.floor(self.height/1.45833) - end - love.graphics.setColor(self.TextColor[1],self.TextColor[2],self.TextColor[3],self.TextVisibility*254) - if self.Font==_defaultfont then - love.graphics.setFont(self.Font) - love.graphics.printf(self.text, self.x+2+(self.XTween*self.DPI)+((self.marginL or 0)*self.DPI or self.XTween*self.DPI), self.y+(self.FontHeight/2)+self.Tween*self.DPI, self.width+(0 or (self.marginR or 0)*self.DPI), self.TextFormat) - else - if type(self.Font)=="string" then - self.Font=love.graphics.newFont(self.Font,self.FontSize) - self.FontHeight=self.Font:getHeight() - else - love.graphics.setFont(self.Font) - end - if type(self.FontSize)=="string" then - self.FontSize=tonumber(self.FontSize) - love.graphics.setNewFont(self.FontSize) - end - love.graphics.printf(self.text, self.x+2+((self.marginL or 0)*self.DPI or self.XTween*self.DPI), self.y+math.floor((self.FontHeight-self.FontSize)/2)+self.Tween*self.DPI, self.width+(0 or (self.marginR or 0)*self.DPI), self.TextFormat) - end - end - end - if self.DrawRulesE then - for dr=1,#self.DrawRulesE do - self.DrawRulesE[dr](self) - end - end - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newDropFrame.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newDropFrame.int deleted file mode 100644 index 97e4720..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newDropFrame.int +++ /dev/null @@ -1,37 +0,0 @@ -function gui:newDropFrame(name,x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("DropFrame",name, x, y, w, h, sx ,sy ,sw ,sh) - c.WasBeingDragged=false - c.IsBeingDragged=false - c.Draggable=false - c.funcD={} - function c:GetDroppedItems() - local t=self:getChildren() - local tab={} - for i=1,#t do - if t[i].Type=="TextImageButtonFrameDrag" then - table.insert(tab,t[i]) - end - end - return tab - end - function c:OnDropped(func) - table.insert(self.funcD,func) - end - c:OnUpdate(function(self) - if _GuiPro.DragItem then - if _GuiPro.DragItem.Type=="TextImageButtonFrameDrag" and love.mouse.isDown(_GuiPro.DragItem.dragbut or "m")==false and self:IsHovering() then - local t=_GuiPro.DragItem - _GuiPro.DragItem={} - for i=1,#t.funcD do - t.funcD[i](self,t) - end - for i=1,#self.funcD do - self.funcD[i](self,t) - end - _GuiPro.hasDrag=false - end - end - end) - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newFrame.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newFrame.int deleted file mode 100644 index 5e6b084..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newFrame.int +++ /dev/null @@ -1,8 +0,0 @@ -function gui:newFrame(name,x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("Frame",name, x, y, w, h, sx ,sy ,sw ,sh) - c.WasBeingDragged=false - c.IsBeingDragged=false - c.Draggable=false - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newFullFrame.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newFullFrame.int deleted file mode 100644 index 5cda200..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newFullFrame.int +++ /dev/null @@ -1,4 +0,0 @@ -function gui:newFullFrame(name) - name=name or "" - return self:newFrame(name,0,0,0,0,0,0,1,1) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newTabFrame.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newTabFrame.int deleted file mode 100644 index 9f8f8fe..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newTabFrame.int +++ /dev/null @@ -1,59 +0,0 @@ -function gui:newTabFrame(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=gui:newFrame(name, x, y, w, h, sx ,sy ,sw ,sh) - c.tabheight=20 - c.Holder=c:newFrame("Holder",0,c.tabheight,0,0,0,0,1,1) - c.TabHolder=c:newFrame("TabHolder",0,0,0,c.tabheight,0,0,1) - function c:setTabHeight(n) - self.tabheight=n - self.Holder:SetDualDim(0,-self.tabheight,0,0,0,0,1,1) - end - function c:addTab(name,colorT,colorH) - if colorT and not(colorH) then - colorH=colorT - end - local tab=self.TabHolder:newTextButton(name,name,0,0,0,0,0,0,0,1) - tab.Tween=-3 - if colorT then - tab.Color=colorT - end - local holder=self.Holder:newFrame(name,0,0,0,0,0,0,1,1) - if colorH then - holder.Color=colorH - end - tab.frame=holder - tab:OnReleased(function(b,self) - if b=="l" then - local tt=self.Parent:getChildren() - local th=self.Parent.Parent.Holder:getChildren() - for i=1,#th do - th[i].Visible=false - end - for i=1,#tt do - tt[i].frame.Visible=false - tt[i].BorderSize=1 - end - self.BorderSize=0 - self.frame.Visible=true - end - end) - local tt=self.TabHolder:getChildren() - for i=1,#tt do - tt[i].frame.Visible=false - tt[i].BorderSize=1 - end - tab.frame.Visible=true - tab.BorderSize=0 - return tab,holder - end - c:OnUpdate(function(self) - local th=self.TabHolder:getChildren() - local l=self.width/#th - for i=1,#th do - th[i]:SetDualDim(l*(i-1),0,l) - end - if #th==0 then - self:Destroy() - end - end) - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newratioFrame.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Frame/newratioFrame.int deleted file mode 100644 index e69de29..0000000 diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/SetImage.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/SetImage.int deleted file mode 100644 index d0d5f78..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/SetImage.int +++ /dev/null @@ -1,13 +0,0 @@ -function gui:SetImage(i) - if type(i)=="string" then - self.Image=love.graphics.newImage(i) - else - self.Image=i - end - if self.Image~=nil then - self.ImageHeigth=self.Image:getHeight() - self.ImageWidth=self.Image:getWidth() - self.Quad=love.graphics.newQuad(0,0,self.width,self.height,self.ImageWidth,self.ImageHeigth) - end - return self.ImageWidth,self.ImageHeigth -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/UpdateImage.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/UpdateImage.int deleted file mode 100644 index be4cfd7..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/UpdateImage.int +++ /dev/null @@ -1,5 +0,0 @@ -function gui:UpdateImage() - self.ImageHeigth=self.Image:getHeight() - self.ImageWidth=self.Image:getWidth() - self.Quad=love.graphics.newQuad(0,0,self.width,self.height,self.ImageWidth,self.ImageHeigth) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/getTile.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/getTile.int deleted file mode 100644 index 6b6fcae..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/getTile.int +++ /dev/null @@ -1,20 +0,0 @@ -function gui:getTile(i,x,y,w,h)-- returns imagedata - if type(i)=="string" then - i=love.graphics.newImage(i) - elseif type(i)=="userdata" then - -- do nothing - elseif string.find(self.Type,"Image",1,true) then - local i,x,y,w,h=self.Image,i,x,y,w - else - error("getTile invalid args!!! Usage: ImageElement:getTile(x,y,w,h) or gui:getTile(imagedata,x,y,w,h)") - end - local iw,ih=i:getDimensions() - local id,_id=i:getData(),love.image.newImageData(w,h) - for _x=x,w+x-1 do - for _y=y,h+y-1 do - -- - _id:setPixel(_x-x,_y-y,id:getPixel(_x,_y)) - end - end - return love.graphics.newImage(_id) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newAnim.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newAnim.int deleted file mode 100644 index 30850aa..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newAnim.int +++ /dev/null @@ -1,57 +0,0 @@ -function gui:newAnim(file,delay, x, y, w, h, sx ,sy ,sw ,sh) - local x,y,w,h,sx,sy,sw,sh=filter(file, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("ImageAnimation",file, x, y, w, h, sx ,sy ,sw ,sh) - c.Visibility=0 - c.ImageVisibility=1 - c.delay=delay or .05 - c.files={} - c.AnimStart={} - c.AnimEnd={} - local _files=alphanumsort(love.filesystem.getDirectoryItems(file)) - for i=1,#_files do - if string.sub(_files[i],-1,-1)~="b" then - table.insert(c.files,love.graphics.newImage(file.."/".._files[i])) - end - end - c.step=multi:newTStep(1,#c.files,1,c.delay) - c.step.parent=c - c.rotation=0 - c.step:OnStart(function(step) - for i=1,#step.parent.AnimStart do - step.parent.AnimStart[i](step.parent) - end - end) - c.step:OnStep(function(pos,step) - step.parent:SetImage(step.parent.files[pos]) - end) - c.step:OnEnd(function(step) - for i=1,#step.parent.AnimEnd do - step.parent.AnimEnd[i](step.parent) - end - end) - function c:OnAnimStart(func) - table.insert(self.AnimStart,func) - end - function c:OnAnimEnd(func) - table.insert(self.AnimEnd,func) - end - function c:Pause() - self.step:Pause() - end - function c:Resume() - self.step:Resume() - end - function c:Reset() - self.step.pos=1 - end - function c:getFrames() - return #self.files - end - function c:getFrame() - return self.step.pos - end - function c:setFrame(n) - return self:SetImage(self.files[n]) - end - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newAnimFromData.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newAnimFromData.int deleted file mode 100644 index 02c85c7..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newAnimFromData.int +++ /dev/null @@ -1,52 +0,0 @@ -function gui:newAnimFromData(data,delay, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("ImageAnimation","FromFile", x, y, w, h, sx ,sy ,sw ,sh) - c.Visibility=0 - c.ImageVisibility=1 - c.delay=delay or .05 - c.files=data - c.AnimStart={} - c.AnimEnd={} - c:SetImage(c.files[1]) - c.step=multi:newTStep(1,#c.files,1,c.delay) - c.step.parent=c - c.rotation=0 - c.step:OnStart(function(step) - for i=1,#step.parent.AnimStart do - step.parent.AnimStart[i](step.parent) - end - end) - c.step:OnStep(function(pos,step) - step.parent:SetImage(step.parent.files[pos]) - end) - c.step:OnEnd(function(step) - for i=1,#step.parent.AnimEnd do - step.parent.AnimEnd[i](step.parent) - end - end) - function c:OnAnimStart(func) - table.insert(self.AnimStart,func) - end - function c:OnAnimEnd(func) - table.insert(self.AnimEnd,func) - end - function c:Pause() - self.step:Pause() - end - function c:Resume() - self.step:Resume() - end - function c:Reset() - self.step.pos=1 - end - function c:getFrames() - return #self.files - end - function c:getFrame() - return self.step.pos - end - function c:setFrame(n) - return self:SetImage(self.files[n]) - end - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newAnimFromTiles.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newAnimFromTiles.int deleted file mode 100644 index 70aea2c..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newAnimFromTiles.int +++ /dev/null @@ -1,59 +0,0 @@ -function gui:newAnimFromTiles(file,xd,yd,delay, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(file, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("ImageAnimation",file, x, y, w, h, sx ,sy ,sw ,sh) - local im=love.graphics.newImage(file) - local _x,_y=im:getDimensions() - c.Visibility=0 - c.ImageVisibility=1 - c.delay=delay or .05 - c.files={} - c.AnimStart={} - c.AnimEnd={} - for i=0,_y/yd-1 do - for j=0,_x/xd-1 do - table.insert(c.files,gui:getTile(im,j*xd,i*yd,xd,yd)) - end - end - c:SetImage(c.files[1]) - c.step=multi:newTStep(1,#c.files,1,c.delay) - c.step.parent=c - c.rotation=0 - c.step:OnStart(function(step) - for i=1,#step.parent.AnimStart do - step.parent.AnimStart[i](step.parent) - end - end) - c.step:OnStep(function(pos,step) - step.parent:SetImage(step.parent.files[pos]) - end) - c.step:OnEnd(function(step) - for i=1,#step.parent.AnimEnd do - step.parent.AnimEnd[i](step.parent) - end - end) - function c:OnAnimStart(func) - table.insert(self.AnimStart,func) - end - function c:OnAnimEnd(func) - table.insert(self.AnimEnd,func) - end - function c:Pause() - self.step:Pause() - end - function c:Resume() - self.step:Resume() - end - function c:Reset() - self.step.pos=1 - end - function c:getFrames() - return #self.files - end - function c:getFrame() - return self.step.pos - end - function c:setFrame(n) - return self:SetImage(self.files[n]) - end - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newFullImageLabel.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newFullImageLabel.int deleted file mode 100644 index 953f480..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newFullImageLabel.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:newFullImageLabel(i,name) - return self:newImageLabel(i,name,0,0,0,0,0,0,1,1) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newImageButton.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newImageButton.int deleted file mode 100644 index 6d0e51d..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newImageButton.int +++ /dev/null @@ -1,25 +0,0 @@ -function gui:newImageButton(i,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("ImageButton",name, x, y, w, h, sx ,sy ,sw ,sh) - if type(i)=="string" then - c.Image=love.graphics.newImage(i) - else - c.Image=i - end - c.Visibility=0 - c.ImageVisibility=1 - c.rotation=0 - if c.Image~=nil then - c.ImageHeigth=c.Image:getHeight() - c.ImageHeight=c.Image:getHeight() - c.ImageWidth=c.Image:getWidth() - c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) - end - c:OnEnter(function() - love.mouse.setCursor(_GuiPro.CursorH) - end) - c:OnExit(function() - love.mouse.setCursor(_GuiPro.CursorN) - end) - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newImageLabel.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newImageLabel.int deleted file mode 100644 index 47323e1..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newImageLabel.int +++ /dev/null @@ -1,18 +0,0 @@ -function gui:newImageLabel(i,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("ImageLabel",name, x, y, w, h, sx ,sy ,sw ,sh) - if type(i)=="string" then - c.Image=love.graphics.newImage(i) - else - c.Image=i - end - c.Visibility=0 - c.ImageVisibility=1 - c.rotation=0 - if c.Image~=nil then - c.ImageHeigth=c.Image:getHeight() - c.ImageWidth=c.Image:getWidth() - c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) - end - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newVideo.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newVideo.int deleted file mode 100644 index de2c379..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Image-Animation/newVideo.int +++ /dev/null @@ -1,62 +0,0 @@ -function gui:newVideo(name,i,x,y,w,h,sx,sy,sw,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("Video",name, x, y, w, h, sx ,sy ,sw ,sh) - if type(i)=="string" then - c.Video=love.graphics.newVideo(i) - else - c.Video=i - end - c.Visibility=0 - c.VideoVisibility=1 - c.rotation=0 - if c.Video~=nil then - c.VideoHeigth=c.Video:getHeight() - c.VideoWidth=c.Video:getWidth() - c.Quad=love.graphics.newQuad(0,0,w,h,c.VideoWidth,c.VideoHeigth) - end - c.funcV={} - function c:Play() - self.handStart=true - self.Video:play() - end - function c:Pause() - self.Video:pause() - end - c.Resume=c.Play - function c:Stop() - self.handStart=false - self:Pause() - self:Rewind() - for i=1,# self.funcV do - self.funcV[i](self) - end - end - function c:OnVideoStopped(func) - table.insert(self.funcV,func) - end - function c:Rewind() - self.Video:rewind() - end - function c:Restart() - self:Rewind() - self:Play() - end - function c:Seek(o) - self.Video:seek(o) - end - function c:Tell() - self.Video:tell() - end - function c:SetFilter(min, mag, anisotropy) - self.Video:setFilter(min, mag, anisotropy) - end - function c:IsPlaying() - return self.Video:isPlaying() - end - c:OnUpdate(function(self) - if self.Video:isPlaying()==false and self.handStart == true then - self:Stop() - end - end) - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Item/newDragItem.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Item/newDragItem.int deleted file mode 100644 index 162341c..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Item/newDragItem.int +++ /dev/null @@ -1,51 +0,0 @@ -function gui:newDragItem(t,i,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("TextImageButtonFrameDrag",name, x, y, w, h, sx ,sy ,sw ,sh) - c.WasBeingDragged=false - c.IsBeingDragged=false - c.Draggable=true - c.funcD={} - if type(i)=="string" then - c.Image=love.graphics.newImage(i) - c.ImageVisibility=1 - c.ImageHeigth=c.Image:getHeight() - c.ImageWidth=c.Image:getWidth() - c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) - elseif type(i)=="image" then - c.Image=i - c.ImageVisibility=1 - c.ImageHeigth=c.Image:getHeight() - c.ImageWidth=c.Image:getWidth() - c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) - end - c:OnDragStart(function(self,x,y) - if _GuiPro.hasDrag==false then - self:setParent(_GuiPro) - self:SetDualDim(x,y) - self:TopStack() - end - end) - c.rotation=0 - c.Tween=0 - c.XTween=0 - c.text = t - c.AutoScaleText=false - c.FontHeight=_defaultfont:getHeight() - c.Font=_defaultfont - c.FontSize=15 - c.TextFormat="center" - c.TextVisibility=1 - c.TextColor = {0, 0, 0} - function c:OnDropped(func) - table.insert(self.funcD,func) - end - c:OnUpdate(function(self) - if love.mouse.isDown("m" or self.dragbut)==false and self==_GuiPro.DragItem and self.hovering==false then - _GuiPro.DragItem={} - for i=1,#self.func7 do - self.func7[i](self,(love.mouse.getX())-self.width/2,(love.mouse.getY())-self.height/2) - end - end - end) - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Item/newItem.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Item/newItem.int deleted file mode 100644 index 57a68d5..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Item/newItem.int +++ /dev/null @@ -1,28 +0,0 @@ -function gui:newItem(t,i,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("TextImageButtonFrame",name, x, y, w, h, sx ,sy ,sw ,sh) - if type(i)=="string" then - c.Image=love.graphics.newImage(i) - else - c.Image=i - end - c.rotation=0 - c.ImageVisibility=1 - c.Draggable=false - if c.Image~=nil then - c.ImageHeigth=c.Image:getHeight() - c.ImageWidth=c.Image:getWidth() - c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) - end - c.Tween=0 - c.XTween=0 - c.text = t - c.AutoScaleText=false - c.FontHeight=_defaultfont:getHeight() - c.Font=_defaultfont - c.FontSize=15 - c.TextFormat="center" - c.TextVisibility=1 -- 0=invisible,1=solid (self.TextVisibility*254+1) - c.TextColor = {0, 0, 0} - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/AdvTextBox.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/AdvTextBox.int deleted file mode 100644 index 08a3499..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/AdvTextBox.int +++ /dev/null @@ -1,45 +0,0 @@ -function gui:AdvTextBox(txt,x,y,w,h,sx,sy,sw,sh) - name="AdvTextBox" - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("AdvTextBoxFrame",name, x, y, w, 30, sx ,sy ,sw ,sh) - c.Draggable=true - c.dragbut="r" - c.BorderSize=0 - c:ApplyGradient{Color.Blue,Color.sexy_purple} - c:newTextLabel(txt,"Holder",0,0,0,h-30,0,1,1,0).Color=Color.sexy_purple - c.funcO={} - c.funcX={} - c:OnDragStart(function(self) - self:TopStack() - end) - --local temp = c:newTextButton("X","Close",-25,5,20,20,1) - --temp.Tween=-5 - --temp.XTween=-2 - --temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent) end end) - --temp.Color=Color.Red - c.tLink=c:newTextBox("puttext","TextBox",5,h-95,-40,30,0,1,1,1) - c.tLink.Color=Color.light_gray - c.tLink.ClearOnFocus=true - c.tLink:OnFocus(function(self) self.ClearOnFocus=false end) - local temp=c:newTextButton("OK","Ok",-35,h-65,30,30,1,1) - temp:OnReleased(function(b,self) for i=1,#self.Parent.funcO do self.Parent.funcO[i](self.Parent,self.Parent.tLink.text) end end) - temp.Color=Color.Green - temp.XTween=-2 - local temp=c:newTextButton("X","Cancel",-35,h-95,30,30,1,1) - temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent,self.Parent.tLink.text) end end) - temp.Color=Color.Red - temp.XTween=-2 - function c:Close() - self.Visible=false - end - function c:Open() - self.Visible=true - end - function c:OnOk(func) - table.insert(self.funcO,func) - end - function c:OnX(func) - table.insert(self.funcX,func) - end - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/ApplyGradient.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/ApplyGradient.int deleted file mode 100644 index e092739..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/ApplyGradient.int +++ /dev/null @@ -1,36 +0,0 @@ -function _GuiPro.gradient(colors) - local direction = colors.direction or "horizontal" - colors.direction=nil - trans = colors.trans or 255 - trans=math.floor(trans) - if direction == "horizontal" then - direction = true - elseif direction == "vertical" then - direction = false - else - error("Invalid direction '" .. tostring(direction) "' for gradient. Horizontal or vertical expected.") - end - local result = love.image.newImageData(direction and 1 or #colors, direction and #colors or 1) - for __i, color in ipairs(colors) do - local x, y - if direction then - x, y = 0, __i - 1 - else - x, y = __i - 1, 0 - end - result:setPixel(x, y, color[1], color[2], color[3], trans) - end - result = love.graphics.newImage(result) - result:setFilter('linear', 'linear') - return result -end -function _GuiPro.drawinrect(img, x, y, w, h, r, ox, oy, kx, ky) - love.graphics.draw(img, x, y, r, w / img:getWidth(), h / img:getHeight(), ox, oy, kx, ky) -end -function gui:ApplyGradient(rules) - self.Image=nil - self.Type=self.Type.."w/GradImage" - self.rotation=0 - self.ImageVisibility=rules.visibility or 1 - self:SetImage(_GuiPro.gradient(rules)) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/BottomStack.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/BottomStack.int deleted file mode 100644 index b339ec4..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/BottomStack.int +++ /dev/null @@ -1,10 +0,0 @@ -function gui:BottomStack() - childs=self.Parent:getChildren() - for i=1,#childs do - if childs[i]==self then - table.remove(self.Parent.Children,i) - table.insert(self.Parent.Children,1,self) - break - end - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/Center.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/Center.int deleted file mode 100644 index 0089c93..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/Center.int +++ /dev/null @@ -1,4 +0,0 @@ -function gui:Center() - local x,y=self:getFullSize() - self:SetDualDim(-math.floor(x/2),-math.floor(y/2),nil,nil,.5,.5) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/Destroy.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/Destroy.int deleted file mode 100644 index 9c524f1..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/Destroy.int +++ /dev/null @@ -1,9 +0,0 @@ -function gui:Destroy() - check=self.Parent:getChildren() - local cc=0 - for cc=1,#check do - if check[cc]==self then - table.remove(self.Parent.Children,cc) - end - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/GetAllChildren.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/GetAllChildren.int deleted file mode 100644 index b3a0ae4..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/GetAllChildren.int +++ /dev/null @@ -1,25 +0,0 @@ -function gui:GetAllChildren() - local Stuff = {} - function Seek(Items) - for i=1,#Items do - if Items[i].Visible==true then - table.insert(Stuff,Items[i]) - local NItems = Items[i]:getChildren() - if NItems ~= nil then - Seek(NItems) - end - end - end - end - local Objs = self:getChildren() - for i=1,#Objs do - if Objs[i].Visible==true then - table.insert(Stuff,Objs[i]) - local Items = Objs[i]:getChildren() - if Items ~= nil then - Seek(Items) - end - end - end - return Stuff -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/GetChild.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/GetChild.int deleted file mode 100644 index d434f40..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/GetChild.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:GetChild(name) - return self.Children[name] or self -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/InGrid.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/InGrid.int deleted file mode 100644 index 4e097a7..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/InGrid.int +++ /dev/null @@ -1,3 +0,0 @@ -function InGrid(i,x,y,s) - return math.floor((i-1)/x)*s,(i-1)*s-(math.floor((i-1)/y)*(s*x)) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/InGridX.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/InGridX.int deleted file mode 100644 index c4aadc2..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/InGridX.int +++ /dev/null @@ -1,5 +0,0 @@ -function InGridX(i,w,h,xs,ys) - local xc,yc=math.floor(w/xs),math.floor(h/ys) - local xi,yi=(i-1)%xc,math.floor((i-1)/xc) - return xi*xs,yi*ys -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/InGridY.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/InGridY.int deleted file mode 100644 index 555c72a..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/InGridY.int +++ /dev/null @@ -1,5 +0,0 @@ -function InGridY(i,w,h,xs,ys) - local xc,yc=math.floor(w/xs),math.floor(h/ys) - local xi,yi=math.floor((i-1)/yc),(i-1)%yc - return xi*xs,yi*ys -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/IsHovering.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/IsHovering.int deleted file mode 100644 index 072bb54..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/IsHovering.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:IsHovering() - return (love.mouse.getX() > self.x and love.mouse.getX() < self.x+self.width and love.mouse.getY() > self.y and love.mouse.getY() < self.y+self.height) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/Move.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/Move.int deleted file mode 100644 index 6f32db9..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/Move.int +++ /dev/null @@ -1,4 +0,0 @@ -function gui:Move(x,y) - self.offset.pos.x=self.offset.pos.x+x - self.offset.pos.y=self.offset.pos.y+y -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/SetDualDim.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/SetDualDim.int deleted file mode 100644 index 0774965..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/SetDualDim.int +++ /dev/null @@ -1,46 +0,0 @@ -function gui:SetDualDim(x, y, w, h, sx ,sy ,sw ,sh) - if _GuiPro.DPI_ENABLED then - if x then - x=self.DPI*x - end - if y then - y=self.DPI*y - end - if w then - w=self.DPI*w - end - if h then - h=self.DPI*h - end - end - if sx then - self.scale.pos.x=sx - end - if sy then - self.scale.pos.y=sy - end - if x then - self.offset.pos.x=x - end - if y then - self.offset.pos.y=y - end - if sw then - self.scale.size.x=sw - end - if sh then - self.scale.size.y=sh - end - if w then - self.offset.size.x=w - end - if h then - self.offset.size.y=h - end - if self.Image then - self:SetImage(self.Image) - end -end -function gui:setDualDim(...) - self:SetDualDim(...) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/SetHand.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/SetHand.int deleted file mode 100644 index 8171f2c..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/SetHand.int +++ /dev/null @@ -1,5 +0,0 @@ -_GuiPro.CursorN=love.mouse.getSystemCursor("arrow") -_GuiPro.CursorH=love.mouse.getSystemCursor("hand") -function gui:SetHand(img,x,y) - _GuiPro.CursorN=love.mouse.newCursor(img,x,y) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/SetHover.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/SetHover.int deleted file mode 100644 index 956e593..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/SetHover.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:SetHover(img,x,y) - _GuiPro.CursorH=love.mouse.newCursor(img,x,y) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/SetName.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/SetName.int deleted file mode 100644 index 1e69edd..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/SetName.int +++ /dev/null @@ -1,4 +0,0 @@ -function gui:SetName(name) - self.Parent.Children[name]=self - self.Name=name -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/TopStack.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/TopStack.int deleted file mode 100644 index a1db016..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/TopStack.int +++ /dev/null @@ -1,10 +0,0 @@ -function gui:TopStack() - childs=self.Parent:getChildren() - for i=1,#childs do - if childs[i]==self then - table.remove(self.Parent.Children,i) - table.insert(self.Parent.Children,self) - break - end - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/addDominance.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/addDominance.int deleted file mode 100644 index 5a55975..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/addDominance.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:addDominance() - _GuiPro.TopHovered=self -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/addHotKey.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/addHotKey.int deleted file mode 100644 index 0ec05e0..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/addHotKey.int +++ /dev/null @@ -1,6 +0,0 @@ -function gui:addHotKey(key) - local temp=self:newFrame(0,0,0,0) - temp.Visible=false - temp:setHotKey(key) - return temp -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/alphanumsort.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/alphanumsort.int deleted file mode 100644 index 3b36133..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/alphanumsort.int +++ /dev/null @@ -1,7 +0,0 @@ -function alphanumsort(o) - local function padnum(d) local dec, n = string.match(d, "(%.?)0*(.+)") - return #dec > 0 and ("%.12f"):format(d) or ("%s%03d%s"):format(dec, #n, n) - end - table.sort(o, function(a,b) return tostring(a):gsub("%.?%d+",padnum)..("%3d"):format(#b)< tostring(b):gsub("%.?%d+",padnum)..("%3d"):format(#a) end) - return o -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/anchorRight.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/anchorRight.int deleted file mode 100644 index 91251ad..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/anchorRight.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:anchorRight(n) - self:SetDualDim(-(self.width+n),nil,nil,nil,1) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/centerX.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/centerX.int deleted file mode 100644 index ea1f599..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/centerX.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:centerX() - self:SetDualDim(-(self.width/2),nil,nil,nil,.5) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/centerY.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/centerY.int deleted file mode 100644 index c998589..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/centerY.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:centerY() - self:SetDualDim(nil,-(self.height/2),nil,nil,nil,.5) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/disrespectHierarchy.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/disrespectHierarchy.int deleted file mode 100644 index d25162d..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/disrespectHierarchy.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:disrespectHierarchy() - _GuiPro.Hierarchy=false -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getChildren.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getChildren.int deleted file mode 100644 index 295c5fc..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getChildren.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:getChildren() - return self.Children -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getColor.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getColor.int deleted file mode 100644 index bef482e..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getColor.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:getColor(cindex) - return Color[cindex] -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getFullSize.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getFullSize.int deleted file mode 100644 index 294667a..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getFullSize.int +++ /dev/null @@ -1,12 +0,0 @@ -function gui:getFullSize() - local maxx,maxy=-math.huge,-math.huge - local temp = self:GetAllChildren() - for i=1,#temp do - if temp[i].width>maxx then - maxx=temp[i].width+temp[i].offset.pos.x - elseif temp[i].height>maxy then - maxy=temp[i].height+temp[i].offset.pos.y - end - end - return maxx,maxy -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getHighest.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getHighest.int deleted file mode 100644 index df7121a..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getHighest.int +++ /dev/null @@ -1,5 +0,0 @@ -function gui:getHighest() - if self.Children[#self.Children]~=nil then - return self.Children[#self.Children] - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getLowest.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getLowest.int deleted file mode 100644 index 5319544..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/getLowest.int +++ /dev/null @@ -1,5 +0,0 @@ -function gui:getLowest() - if self.Children[1]~=nil then - return self.Children[1] - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/isDescendant.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/isDescendant.int deleted file mode 100644 index 5c9c2a5..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/isDescendant.int +++ /dev/null @@ -1,9 +0,0 @@ -function gui:isDescendant(obj) - local things=obj:GetAllChildren() - for i=1,#things do - if things[i]==self then - return true - end - end - return false -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/isHighest.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/isHighest.int deleted file mode 100644 index 0453c16..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/isHighest.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:isHighest() - return (self==self.Parent:getHighest()) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/isLowest.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/isLowest.int deleted file mode 100644 index a210883..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/isLowest.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:isLowest() - return (self==self.Parent:getLowest()) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/massMutate.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/massMutate.int deleted file mode 100644 index 1c75aee..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/massMutate.int +++ /dev/null @@ -1,6 +0,0 @@ -function gui.massMutate(t,...) - local mut={...} - for i=1,#mut do - mut[i]:Mutate(t) - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newCheckBox.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newCheckBox.int deleted file mode 100644 index ccd530c..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newCheckBox.int +++ /dev/null @@ -1,41 +0,0 @@ -if love.filesystem.exists("CheckBoxes.png") then - _GuiPro.UC=gui:getTile("CheckBoxes.png",0,0,16,16) - _GuiPro.C=gui:getTile("CheckBoxes.png",16,0,16,16) - _GuiPro.UCH=gui:getTile("CheckBoxes.png",0,16,16,16) - _GuiPro.CH=gui:getTile("CheckBoxes.png",16,16,16,16) -end -function gui:newCheckBox(name,x,y) - if not(_GuiPro.UC) then error("CheckBoxes.png not found! Cannot currently use checkbox without the data") end - if type(name)~="String" then - x,y,name=name,x,"CheckBox" - end - local c=self:newImageLabel(_GuiPro.UC,name, x, y, 16,16) - c.Visibility=0 - c.check=false - c:OnEnter(function(self) - if self.check then - self:SetImage(_GuiPro.CH) - else - self:SetImage(_GuiPro.UCH) - end - end) - function c:isChecked() - return self.check - end - c:OnExit(function(self) - if self.check then - self:SetImage(_GuiPro.C) - else - self:SetImage(_GuiPro.UC) - end - end) - c:OnReleased(function(b,self) - self.check=not(self.check) - if self.check then - self:SetImage(_GuiPro.CH) - else - self:SetImage(_GuiPro.UCH) - end - end) - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newMessageBox.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newMessageBox.int deleted file mode 100644 index 6b11a5a..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newMessageBox.int +++ /dev/null @@ -1,36 +0,0 @@ -function gui:newMessageBox(txt,x,y,w,h,sx,sy,sw,sh) - name="MessageBox" - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("MessageBoxFrame",name, x, y, w, 30, sx ,sy ,sw ,sh) - c.Draggable=true - c.dragbut="r" - c:ApplyGradient{Color.Blue,Color.sexy_purple} - c.BorderSize=0 - c:newTextLabel(txt,"Holder",0,0,0,h-30,0,1,1,0).Color=Color.sexy_purple - c.funcO={} - c.funcX={} - c:OnDragStart(function(self) - self:TopStack() - end) - local temp = c:newTextButton("X","Close",-25,5,20,20,1) - temp.Tween=-5 - temp.XTween=-2 - temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent) end end) - temp.Color=Color.Red - local temp=c:newTextButton("OK","Ok",0,h-65,0,30,.25,1,.5) - temp:OnReleased(function(b,self) for i=1,#self.Parent.funcO do self.Parent.funcO[i](self.Parent) end end) - temp.Color=Color.Green - function c:Close() - self.Visible=false - end - function c:Open() - self.Visible=true - end - function c:OnOk(func) - table.insert(self.funcO,func) - end - function c:OnX(func) - table.insert(self.funcX,func) - end - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newPart.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newPart.int deleted file mode 100644 index 79bd3e5..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newPart.int +++ /dev/null @@ -1,49 +0,0 @@ -function gui:newPart(x, y,w ,h , sx ,sy ,sw ,sh) - local c = {} - setmetatable(c, gui) - if self==gui then - c.Parent=_GuiPro - else - c.Parent=self - end - c.funcs={} - c.funcs2={} - c.funcs3={} - c.funcs4={} - c.funcs5={} - c.func6={} - c.func7={} - c.func8={} - c.func9={} - c.func10={} - c.form="rectangle" - c.Color = {255, 255, 255} - c.scale={} - c.scale.size={} - c.scale.size.x=sw or 0 - c.scale.size.y=sh or 0 - c.offset={} - c.offset.size={} - c.offset.size.x=w or 0 - c.offset.size.y=h or 0 - c.scale.pos={} - c.scale.pos.x=sx or 0 - c.scale.pos.y=sy or 0 - c.offset.pos={} - c.offset.pos.x=x or 0 - c.offset.pos.y=y or 0 - c.VIS=true - c.Visible=true - c.Visibility=1 - c.BorderColor={0,0,0} - c.BorderSize=0 - c.Type="Part" - c.Name="GuiPart" - _GuiPro.count=_GuiPro.count+1 - c.x=(c.Parent.width*c.scale.pos.x)+c.offset.pos.x+c.Parent.x - c.y=(c.Parent.height*c.scale.pos.y)+c.offset.pos.y+c.Parent.y - c.width=(c.Parent.width*c.scale.size.x)+c.offset.size.x - c.height=(c.Parent.height*c.scale.size.y)+c.offset.size.y - table.insert(c.Parent.Children,c) - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newProgressBar.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newProgressBar.int deleted file mode 100644 index 2f82f9f..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newProgressBar.int +++ /dev/null @@ -1,45 +0,0 @@ -function gui:newProgressBar(txt,x,y,w,h,sx,sy,sw,sh) - name="newProgressBar" - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("newProgressBarFrame",name, x, y, w, 30, sx ,sy ,sw ,sh) - c.Draggable=true - c.dragbut="r" - c.BorderSize=0 - c:ApplyGradient{Color.Blue,Color.sexy_purple} - c:newTextLabel(txt,"Holder",0,0,0,h-30,0,1,1,0).Color=Color.sexy_purple - c.funcO={} - c.funcX={} - c:OnDragStart(function(self) - self:TopStack() - end) - local temp = c:newTextButton("X","Close",-25,5,20,20,1) - temp.Tween=-5 - temp.XTween=-2 - temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent) end end) - temp.Color=Color.Red - c.BarBG=c:newTextButton("",5,h-65,-10,30,0,1,1) - c.BarBG:ApplyGradient{Color.Red,Color.light_red} - c.Bar=c.BarBG:newTextLabel("",0,0,0,0,0,0,0,1) - c.Bar:ApplyGradient{Color.Green,Color.light_green} - c.BarDisp=c.BarBG:newTextLabel("0%","0%",0,0,0,0,0,0,1,1) - c.BarDisp.Visibility=0 - c.BarDisp.Link=c.Bar - c.BarDisp:OnUpdate(function(self) - self.text=self.Link.scale.size.x*100 .."%" - end) - c.Func1={} - function c:On100(func) - table.insert(self.Func1,func) - end - c:OnUpdate(function(self) - if self.Bar.scale.size.x*100>=100 then - for P=1,#self.Func1 do - self.Func1[P](self) - end - end - end) - function c:SetPercentage(n) - self.Bar:SetDualDim(0,0,0,0,0,0,n/100,1) - end - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newScrollBar.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newScrollBar.int deleted file mode 100644 index 6fa810a..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newScrollBar.int +++ /dev/null @@ -1,42 +0,0 @@ -function gui:newScrollBar(color1,color2) - local scrollbar=self:newFrame(-20,0,20,0,1,0,0,1) - scrollbar.funcS={} - scrollbar.Color=color1 or Color.saddle_brown - scrollbar:OnClicked(function(b,self,x,y) - love.mouse.setX(self.x+10) - if y>=10 and y<=self.height-10 then - self.mover:SetDualDim(0,y-10) - end - if y<10 then - love.mouse.setY(10+self.y) - end - if y>self.height-10 then - love.mouse.setY((self.height-10)+self.y) - end - for i=1,#self.funcS do - self.funcS[i](self,self:getPosition()) - end - end) - scrollbar:OnEnter(function(self) - self:addDominance() - end) - scrollbar:OnExit(function(self) - self:removeDominance() - end) - scrollbar.mover=scrollbar:newTextButton("","",0,0,20,20) - scrollbar.mover.Color=color2 or Color.light_brown - function scrollbar:getPosition() - return ((self.mover.offset.pos.y)/(self.height-20))*100 - end - function scrollbar:setPosition(n) - print((self.height-20),n) - self.mover.offset.pos.y=((self.height-20)/(100/n)) - for i=1,#self.funcS do - self.funcS[i](self,self:getPosition()) - end - end - function scrollbar:OnScroll(func) - table.insert(self.funcS,func) - end - return scrollbar -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newScrollMenu.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newScrollMenu.int deleted file mode 100644 index 3dbfdaf..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/newScrollMenu.int +++ /dev/null @@ -1,98 +0,0 @@ -function gui:newScrollMenu(title,tabN,onloop,x, y, w, h, sx ,sy ,sw ,sh) - local Main = self:newFrame(x, y, w, h, sx ,sy ,sw ,sh) - local Title=Main:newTextButton(title,"Title",0,0,0,20,0,0,1) - Title.Tween=-4 - Title.FontSize=12 - Title:OnReleased(function(b,self) - self.Parent.Tick=not(self.Parent.Tick) - end) - local scroll=Main:newTextButton("","Scroll",-20,20,20,-20,1,0,0,1) - scroll:OnClicked(function(b,self,x,y) - self.Parent.Mover:SetDualDim(0,y-10,20,20) - if self.Parent.Mover.offset.pos.y<0 then - self.Parent.Mover:SetDualDim(0,0,20,20) - end - if self.Parent.Mover.offset.pos.y>self.Parent.height-40 then - self.Parent.Mover:SetDualDim(0,self.Parent.height-40,20,20) - end - local temp = #self.Parent.TList - self.Parent.pos=(math.floor((temp*self.Parent.Mover.offset.pos.y)/self.height))+1 - end) - Main:OnUpdate(function(self) - if self.Tick==false then - self.Visibility=0 - end - end) - scroll:OnUpdate(function(self) - self.Visible=self.Parent.Tick - end) - local Mover=scroll:newTextLabel("",0,0,20,20) - Main.Mover=Mover - Main.TList=tabN - Main.pos=1 - Main.Tick=true - function Main:Update(title,tabN,onloop) - ch=self:getChildren() - for i=#ch,1,-1 do - ch[i]:Destroy() - end - Title=Main:newTextButton(title,"Title",0,0,0,20,0,0,1) - Title.Tween=-4 - Title.FontSize=12 - Title:OnReleased(function(b,self) - self.Parent.Tick=not(self.Parent.Tick) - end) - scroll=Main:newTextButton("","Scroll",-20,20,20,-20,1,0,0,1) - scroll:OnClicked(function(b,self,x,y) - self.Parent.Mover:SetDualDim(0,y-10,20,20) - if self.Parent.Mover.offset.pos.y<0 then - self.Parent.Mover:SetDualDim(0,0,20,20) - end - if self.Parent.Mover.offset.pos.y>self.Parent.height-40 then - self.Parent.Mover:SetDualDim(0,self.Parent.height-40,20,20) - end - local temp = #self.Parent.TList - self.Parent.pos=(math.floor((temp*self.Parent.Mover.offset.pos.y)/self.height))+1 - end) - local Mover=scroll:newTextLabel("",0,0,20,20) - Main.Mover=Mover - Main.TList=tabN - Main.pos=1 - Main.Tick=true - scroll:OnUpdate(function(self) - self.Visible=self.Parent.Tick - end) - for i=1,math.floor(Main.height/20)-1 do - local temp=Main:newTextButton("","Item"..i,0,i*20,-20,20,0,0,1) - temp.FontSize=10 - temp.Tween=-4 - temp.pos=i - temp:OnUpdate(function(self) - self.text=self.Parent.TList[(self.Parent.pos+self.pos)-1] - self.Visible=self.Parent.Tick - end) - if onloop then - onloop(temp,i) - end - end - end - io.write(tostring(Main.height).."\n") - for i=1,math.floor(Main.height/20)-1 do - local temp=Main:newTextButton("Item"..i,0,i*20,-20,20,0,0,1) - temp.FontSize=10 - temp.Tween=-4 - temp.pos=i - temp:OnUpdate(function(self) - if self.Parent.TList[(self.Parent.pos+self.pos)-1]~=nil then - self.text=self.Parent.TList[(self.Parent.pos+self.pos)-1] - else - self.text="" - end - self.Visible=self.Parent.Tick - end) - if onloop then - onloop(temp,i) - end - end - return Main -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/removeAllChildren.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/removeAllChildren.int deleted file mode 100644 index 8d0d99e..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/removeAllChildren.int +++ /dev/null @@ -1,6 +0,0 @@ -function gui:destroyAllChildren() - local c=self.Children - for i=1,#c do - c[i]:Destroy() - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/removeDominance.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/removeDominance.int deleted file mode 100644 index c42b2e1..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/removeDominance.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:removeDominance() - _GuiPro.TopHovered=nil -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/respectHierarchy.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/respectHierarchy.int deleted file mode 100644 index 656a992..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/respectHierarchy.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:respectHierarchy() - _GuiPro.Hierarchy=true -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/round.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/round.int deleted file mode 100644 index f06ad57..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/round.int +++ /dev/null @@ -1,4 +0,0 @@ -function gui.round(num, idp) - local mult = 10^(idp or 0) - return math.floor(num * mult + 0.5) / mult -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setBG.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setBG.int deleted file mode 100644 index c82f045..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setBG.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui.setBG(i) - gui.ff:SetImage(i) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setColor.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setColor.int deleted file mode 100644 index 7a81a6f..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setColor.int +++ /dev/null @@ -1,14 +0,0 @@ -function gui:setColor(a,b,c) - if type(a)=="string" then - self.Color=Color[a] - elseif type(a)=="number" then - self.Color=Color.new(a,b,c) - end -end -function gui:setTextColor(a,b,c) - if type(a)=="string" then - self.TextColor=Color[a] - elseif type(a)=="number" then - self.TextColor=Color.new(a,b,c) - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setDefualtFont.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setDefualtFont.int deleted file mode 100644 index 001b9f7..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setDefualtFont.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:setDefualtFont(font) - _defaultfont = font -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setHotKey.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setHotKey.int deleted file mode 100644 index 5866cfc..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setHotKey.int +++ /dev/null @@ -1,24 +0,0 @@ -function gui:setHotKey(key) - local tab=key:split("+") - self.hotkeys=tab - self.cooldown=false - self.Alarm=multi:newAlarm(1) - self.Alarm.parent=self - self.args={} - self.funcHK=multi:newConnection() - self.Alarm:OnRing(function(alarm) alarm.parent.cooldown=false end) - function self:OnHotKey(func) - self.funcHK:connect(func) - end - self:OnUpdate(function(self) - if self.cooldown then return end - for i=1,#self.hotkeys do - if not(love.keyboard.isDown(self.hotkeys[i])) then - return - end - end - self.cooldown=true - self.funcHK:Fire(self) - self.Alarm:Reset() - end) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setNewFont.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setNewFont.int deleted file mode 100644 index 93d95c5..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setNewFont.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:setNewFont(FontSize) - self.Font=love.graphics.setNewFont(tonumber(FontSize)) -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setParent.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setParent.int deleted file mode 100644 index 37ddb6e..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setParent.int +++ /dev/null @@ -1,14 +0,0 @@ -function gui:setParent(parent,name)-- Needs fixing!!! - local temp=self.Parent:getChildren() - for i=1,#temp do - if temp[i]==self then - table.remove(self.Parent.Children,i) - break - end - end - table.insert(parent.Children,self) - self.Parent=parent - if name then - self:SetName(name) - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setVisibility.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setVisibility.int deleted file mode 100644 index ca6008c..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setVisibility.int +++ /dev/null @@ -1,14 +0,0 @@ -function gui:setVisiblity(val) - self.Visible=val - self.oV=val - doto=self:GetAllChildren() - if val==false then - for i=1,#doto do - doto[i].Visible=val - end - else - for i=1,#doto do - doto[i].Visible=doto[i].oV - end - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setgetText.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setgetText.int deleted file mode 100644 index bb4afc6..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Misc/setgetText.int +++ /dev/null @@ -1,6 +0,0 @@ -function gui:setText(txt) - self.text=txt -end -function gui:getText(txt) - return self.text -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Text/newTextBox.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Text/newTextBox.int deleted file mode 100644 index b243ca7..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Text/newTextBox.int +++ /dev/null @@ -1,178 +0,0 @@ -function string:insert(p,s) - return ("%s%s%s"):format(self:sub(1,p), s, self:sub(p+1)) -end -function string:remove(p,l) - l=l or 1 - return ("%s%s"):format(self:sub(1,p-1), self:sub(p+l)) -end -function gui:newTextBox(t,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("TextBox",name, x, y, w, h, sx ,sy ,sw ,sh) - c.ClearOnFocus=false - c.LoseFocusOnEnter=true - c.Tween=0 - c.XTween=0 - c.FontHeight=_defaultfont:getHeight() - c.Font=_defaultfont - c.FontSize=15 - c.TextFormat="center" - c.text = t - c.ttext= t - c.AutoScaleText=false - c.TextVisibility=1 - c.Color = {220, 220, 220} - c.TextColor = {0, 0, 0} - c.Active=false - c.hidden=false - c.cursor={0,1} - c.mark=nil - c.arrowkeys=false - c.funcF={function() - love.keyboard.setTextInput(true) - end} - c.cooldown=false - c.cooldown2=false - c.funcE={function() - love.keyboard.setTextInput(false) - end} - function c:triggerEnter() - for cc=1,#self.funcE do - self.funcE[cc](self,self.ttext) - end - self.text="" - self.ttext="" - end - c.Enter=true - c.Alarm=multi:newAlarm(.1) - c.Alarm.parent=c - c.Alarm:OnRing(function(alarm) alarm.parent.cooldown=false end) - c.Alarm2=multi:newAlarm(.5) - c.Alarm2.parent=c - c.Alarm2:OnRing(function(alarm) alarm.parent.cooldown2=false end) - c.ArrowAlarm=multi:newAlarm(.1) - c.ArrowAlarm.parent=c - c.ArrowAlarm:OnRing(function(alarm) alarm.parent.arrowkeys=false end) - function c:OnFocus(func) - table.insert(self.funcF,func) - end - function c:OnEnter(func) - table.insert(self.funcE,func) - end - c:OnClicked(function(b,self) - for cc=1,#self.funcF do - self.funcF[cc](self) - end - if self.Active==false then - if self.ClearOnFocus==true then - self.text="" - self.ttext="" - end - for tb=1,#gui.TB do - if gui.TB[tb]~=nil then - gui.TB[tb].Active=false - end - end - self.Active=true - end - end) - c:OnClicked(function(b,self,x,y) - local dwidth, wrappedtext = _defaultfont:getWrap(self.text:sub(1,self.cursor[1]), self.width) - local height = _defaultfont:getHeight() - if #wrappedtext>=1 then - width= _defaultfont:getWidth(wrappedtext[#wrappedtext]) - self.cursor[2]=#wrappedtext - else - self.cursor[2]=1 - width=0 - end - yc=math.ceil(((y/self.DPI)-(self.FontHeight/2)+self.Tween-self.y)/height) - xc=math.floor(x) - end) - c:AddDrawRuleE(function(self) - if self.Active then - local dwidth, wrappedtext = _defaultfont:getWrap(self.text:sub(1,self.cursor[1]), self.width) - local height = _defaultfont:getHeight() - if #wrappedtext>=1 then - width= _defaultfont:getWidth(wrappedtext[#wrappedtext]) - self.cursor[2]=#wrappedtext - else - self.cursor[2]=1 - width=0 - end - x1=width+2+self.x+self.XTween - y1=(self.y+(height*(self.cursor[2]-1))+(self.FontHeight/2)+self.Tween)*self.DPI - x2=width+2+self.x+self.XTween - y2=(self.y+(self.FontHeight/2)+self.Tween*self.DPI)+height*self.cursor[2] - love.graphics.line(x1,y1,x2,y2) - end - end) - c:OnUpdate(function(self) - if love.keyboard.isDown("backspace") and self.Active and self.cooldown==false then - if #self.text>0 then - self.text = self.text:remove(self.cursor[1]) - self.ttext = self.ttext:remove(self.cursor[1]) - self.cursor[1]=self.cursor[1]-1 - end - self.cooldown=true - self.Alarm:Reset() - elseif love.keyboard.isDown("backspace")==false then - self.cooldown=false - end - if love.keyboard.isDown("left") and self.arrowkeys==false and self.Active then - self.arrowkeys=true - self.cursor[1]=self.cursor[1]-1 - if self.cursor[1]<0 then - self.cursor[1]=0 - end - self.ArrowAlarm:Reset() - elseif love.keyboard.isDown("right") and self.arrowkeys==false and self.Active then - self.arrowkeys=true - self.cursor[1]=self.cursor[1]+1 - if self.cursor[1]>#self.text then - self.cursor[1]=#self.text - end - self.ArrowAlarm:Reset() - end - if love.keyboard.isDown("delete") and self.Active then - if #self.text>0 then - self.text = "" - self.ttext = "" - self.cursor[1]=1 - end - elseif (love.keyboard.isDown("lshift") or love.keyboard.isDown("rshift")) and love.keyboard.isDown("return") and self.cooldown2==false then - self.text=self.text.."\n" - self.ttext=self.ttext.."\n" - self.cooldown2=true - c.Alarm2:Reset() - elseif (love.keyboard.isDown("return") or love.keyboard.isDown("enter") or love.keyboard.isDown("kpenter")) and self.Active and self.Enter and not(love.keyboard.isDown("lshift") or love.keyboard.isDown("rshift")) then - if self.LoseFocusOnEnter then - self.Active=false - else - self.Active=true - end - for cc=1,#self.funcE do - self.funcE[cc](self,self.ttext) - end - end - end) - table.insert(gui.TB,c) - return c -end ---TEXT BOX HELPER FUNCTION -function love.textinput(t) - for tb=1,#gui.TB do - if gui.TB[tb]~=nil then - if gui.TB[tb].Active then - if gui.TB[tb].hidden then - --gui.TB[tb].text=gui.TB[tb].text.."*" - gui.TB[tb].text=gui.TB[tb].text:insert(gui.TB[tb].cursor[1],"*") - else - --gui.TB[tb].text=gui.TB[tb].text..t - gui.TB[tb].text=gui.TB[tb].text:insert(gui.TB[tb].cursor[1],t) - end - gui.TB[tb].ttext=gui.TB[tb].ttext:insert(gui.TB[tb].cursor[1],t) - gui.TB[tb].cursor[1]=gui.TB[tb].cursor[1]+1 - end - end - end -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Text/newTextButton.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Text/newTextButton.int deleted file mode 100644 index da2f3f6..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Text/newTextButton.int +++ /dev/null @@ -1,22 +0,0 @@ -function gui:newTextButton(t,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("TextButton",name, x, y, w, h, sx ,sy ,sw ,sh) - c.Tween=0 - c.XTween=0 - c.FontHeight=_defaultfont:getHeight() - c.Font=_defaultfont - c.FontSize=15 - c.TextFormat="center" - c.text = t - c.AutoScaleText=false - c.TextVisibility=1 -- 0=invisible,1=solid (self.TextVisibility*254+1) - c.Color = {220, 220, 220} - c.TextColor = {0, 0, 0} - c:OnEnter(function() - love.mouse.setCursor(_GuiPro.CursorH) - end) - c:OnExit(function() - love.mouse.setCursor(_GuiPro.CursorN) - end) - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/Text/newTextLabel.int b/mulit/examples/love2d Threading Example/GuiManagerDebug/Text/newTextLabel.int deleted file mode 100644 index 4424d0e..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/Text/newTextLabel.int +++ /dev/null @@ -1,16 +0,0 @@ -function gui:newTextLabel(t,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("TextLabel",name, x, y, w, h, sx ,sy ,sw ,sh) - c.Tween=0 - c.XTween=0 - c.FontHeight=_defaultfont:getHeight() - c.Font=_defaultfont - c.FontSize=15 - c.TextFormat="center" - c.text = t - c.AutoScaleText=false - c.TextVisibility=1 -- 0=invisible,1=solid (self.TextVisibility*254+1) - c.Color = {220, 220, 220} - c.TextColor = {0, 0, 0} - return c -end \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/GuiManagerDebug/init.lua b/mulit/examples/love2d Threading Example/GuiManagerDebug/init.lua deleted file mode 100644 index 2060ee7..0000000 --- a/mulit/examples/love2d Threading Example/GuiManagerDebug/init.lua +++ /dev/null @@ -1,58 +0,0 @@ -utf8 = require("utf8") -_defaultfont = love.graphics.getFont() -gui = {} -gui.__index = gui -gui.TB={} -gui.Version="VERSION" -- Is it really ready for release? -_GuiPro={GBoost=true,hasDrag=false,DragItem={},Children={},Visible=true,count=0,x=0,y=0,height=0,width=0,update=function(self) local things=GetAllChildren2(self) UpdateThings(things) end,draw=function(self) local things=GetAllChildren(self) DrawThings(things) end,getChildren=function(self) return self.Children end} -_GuiPro.Clips={} -_GuiPro.rotate=0 -setmetatable(_GuiPro, gui) -function gui:LoadInterface(file) - local add=".int" - if string.find(file,".",1,true) then add="" end - if love.filesystem.exists(file..add) then - a,b=pcall(love.filesystem.load(file..add)) - if a then - print("Loaded: "..file) - else - print("Error loading file: "..file) - print(a,b) - end - else - print("File does not exist!") - return false - end -end -function gui.LoadAll(dir) - files=love.filesystem.getDirectoryItems(dir) - for i=1,#files do - if string.sub(files[i],-4)==".int" then - gui:LoadInterface(dir.."/"..files[i]) - end - end -end --- Start Of Load - ---gui.LoadAll("GuiManager/LibCore") -gui.LoadAll("GuiManager/Core") -gui.LoadAll("GuiManager/Image-Animation") -gui.LoadAll("GuiManager/Frame") -gui.LoadAll("GuiManager/Item") -gui.LoadAll("GuiManager/Misc") -gui.LoadAll("GuiManager/Text") -gui.LoadAll("GuiManager/Drawing") -gui.LoadAll("GuiManager/Combos") ---gui.LoadAll("GuiManager/WIP") -multi.boost=2 - --- End of Load -gui:respectHierarchy() -_GuiPro.width,_GuiPro.height=love.graphics.getDimensions() -multi:newLoop():OnLoop(function() _GuiPro.width,_GuiPro.height=love.graphics.getDimensions() _GuiPro:update() end) -multi:onDraw(function() _GuiPro:draw() end) -gui.ff=gui:newFrame("",0,0,0,0,0,0,1,1) -gui.ff.Color={255,255,255} -gui.ff:OnUpdate(function(self) - self:BottomStack() -end) diff --git a/mulit/examples/love2d Threading Example/Menus/newselectMenu.int b/mulit/examples/love2d Threading Example/Menus/newselectMenu.int deleted file mode 100644 index e69de29..0000000 diff --git a/mulit/examples/love2d Threading Example/Res/Parallax100.png b/mulit/examples/love2d Threading Example/Res/Parallax100.png deleted file mode 100644 index b4b79bc..0000000 Binary files a/mulit/examples/love2d Threading Example/Res/Parallax100.png and /dev/null differ diff --git a/mulit/examples/love2d Threading Example/Res/Parallax60.png b/mulit/examples/love2d Threading Example/Res/Parallax60.png deleted file mode 100644 index d6c501a..0000000 Binary files a/mulit/examples/love2d Threading Example/Res/Parallax60.png and /dev/null differ diff --git a/mulit/examples/love2d Threading Example/Res/Parallax80.png b/mulit/examples/love2d Threading Example/Res/Parallax80.png deleted file mode 100644 index a7fbb25..0000000 Binary files a/mulit/examples/love2d Threading Example/Res/Parallax80.png and /dev/null differ diff --git a/mulit/examples/love2d Threading Example/Res/ship.png b/mulit/examples/love2d Threading Example/Res/ship.png deleted file mode 100644 index 242ca2b..0000000 Binary files a/mulit/examples/love2d Threading Example/Res/ship.png and /dev/null differ diff --git a/mulit/examples/love2d Threading Example/conf.lua b/mulit/examples/love2d Threading Example/conf.lua deleted file mode 100644 index e9fd241..0000000 --- a/mulit/examples/love2d Threading Example/conf.lua +++ /dev/null @@ -1,39 +0,0 @@ -function love.conf(t) - t.identity = nil -- The name of the save directory (string) - t.version = "0.10.2" -- The LOVE version this game was made for (string) - t.console = true -- Attach a console (boolean, Windows only) - - t.window.title = "Chat Client" -- The window title (string) - t.window.icon = nil -- Filepath to an image to use as the window's icon (string) - t.window.width = 500 -- The window width (number) - t.window.height = 500 -- The window height (number) - t.window.borderless = false -- Remove all border visuals from the window (boolean) - t.window.resizable = false -- Let the window be user-resizable (boolean) - t.window.minwidth = 1 -- Minimum window width if the window is resizable (number) - t.window.minheight = 1 -- Minimum window height if the window is resizable (number) - t.window.fullscreen = false -- Enable fullscreen (boolean) - t.window.fullscreentype = "desktop" -- Standard fullscreen or desktop fullscreen mode (string) - t.window.vsync = false -- Enable vertical sync (boolean) - t.window.fsaa = 0 -- The number of samples to use with multi-sampled antialiasing (number) - t.window.display = 1 -- Index of the monitor to show the window in (number) - t.window.highdpi = false -- Enable high-dpi mode for the window on a Retina display (boolean) - t.window.srgb = false -- Enable sRGB gamma correction when drawing to the screen (boolean) - t.window.x = nil -- The x-coordinate of the window's position in the specified display (number) - t.window.y = nil -- The y-coordinate of the window's position in the specified display (number) - - t.modules.audio = true -- Enable the audio module (boolean) - t.modules.event = true -- Enable the event module (boolean) - t.modules.graphics = true -- Enable the graphics module (boolean) - t.modules.image = true -- Enable the image module (boolean) - t.modules.joystick = true -- Enable the joystick module (boolean) - t.modules.keyboard = true -- Enable the keyboard module (boolean) - t.modules.math = true -- Enable the math module (boolean) - t.modules.mouse = true -- Enable the mouse module (boolean) - t.modules.physics = true -- Enable the physics module (boolean) - t.modules.sound = true -- Enable the sound module (boolean) - t.modules.system = true -- Enable the system module (boolean) - t.modules.timer = true -- Enable the timer module (boolean) - t.modules.window = true -- Enable the window module (boolean) - t.modules.thread = true -- Enable the thread module (boolean) -end ---1440 x 2560 diff --git a/mulit/examples/love2d Threading Example/core/AudioManager.lua b/mulit/examples/love2d Threading Example/core/AudioManager.lua deleted file mode 100644 index fceda6c..0000000 --- a/mulit/examples/love2d Threading Example/core/AudioManager.lua +++ /dev/null @@ -1,212 +0,0 @@ -audio = {} -audio.__index = audio -function audio:new(f,t) - local obj={} - setmetatable(obj, audio) - obj.source=love.audio.newSource(f,t) - obj.f=f - obj.t=t or "stream" - obj.endEvent=multi:newLoop() - obj.endEvent.Pare=obj - obj.wasPlaying=false - obj.func={} - obj.func2={} - obj.func3={} - obj.func4={} - obj.endEvent:OnLoop(function(time,loop) - if not(loop.Pare:isPlaying()) and loop.Pare.wasPlaying==true and not(loop.Pare:isPaused()) then - for i=1,#loop.Pare.func do - loop.Pare:stop() - loop.Pare.wasPlaying=false - loop.Pare.endEvent:Pause() - loop.Pare.func[i](loop.Pare) - end - end - end) - obj.endEvent:Pause() - return obj -end -function audio:clone() - local _temp=audio:new(self.f,self.t) - _temp.source=self.source:clone() - return _temp -end ---Mutators -function audio:play() - if self:isPaused() then - for i=1,#self.func4 do - self.func4[i](self) - end - self:resume() - else - for i=1,#self.func3 do - self.func3[i](self) - end - self.source:play() - self.wasPlaying=true - self.endEvent:Resume() - end -end -function audio:stop() - self.source:stop() - self.wasPlaying=true - self.endEvent:Pause() -end -function audio:pause() - for i=1,#self.func2 do - self.func2[i](self) - end - self.source:pause() -end -function audio:resume() - self.source:resume() -end -function audio:rewind() - self.source:rewind() -end -function audio:setAttenuationDistances(r,m) - self.source:setAttenuationDistances(r,m) -end -function audio:setCone(innerAngle, outerAngle, outerVolume) - self.source:setCone(innerAngle, outerAngle, outerVolume) -end -function audio:setDirection(x, y, z) - self.source:setDirection(x, y, z) -end -function audio:setLooping(loop) - self.source:setLooping(loop) -end -function audio:setPitch(pitch) - self.source:setPitch(pitch) -end -function audio:setPosition(x, y, z) - self.source:setPosition(x, y, z) -end -function audio:setRelative(enable) - self.source:setRelative(enable) -end -function audio:setRolloff(rolloff) - self.source:setRolloff(rolloff) -end -function audio:setVelocity(x, y, z) - self.source:setVelocity(x, y, z) -end -function audio:setVolume(volume) - self.source:setVolume(volume) -end -function audio:setVolumeLimits(min, max) - self.source:setVolumeLimits(min, max) -end -function audio:seek(offset,unit) - self.source:seek(offset,unit) -end ---Assessors -function audio:isPlaying() - return self.source:isPlaying() -end -function audio:isPaused() - return self.source:isPaused() -end -function audio:isStopped() - return self.source:isStopped() -end -function audio:isLooping() - return self.source:isLooping() -end -function audio:isStatic() - return self.source:isStatic() -end -function audio:isRelative() - return self.source:isRelative() -end -function audio:getAttenuationDistances() - return self.source:getAttenuationDistances() -end -function audio:getChannels() - return self.source:getChannels() -end -function audio:getCone() - return self.source:getCone() -end -function audio:getDirection() - return self.source:getDirection() -end -function audio:getPitch() - return self.source:getPitch() -end -function audio:getPosition() - return self.source:getPosition() -end -function audio:getRolloff() - return self.source:getRolloff() -end -function audio:getVelocity() - return self.source:getVelocity() -end -function audio:getVolume() - return self.source:getVolume() -end -function audio:getVolumeLimits() - return self.source:getVolumeLimits() -end -function audio:tell(unit) - return self.source:tell(unit) -end -function audio:type() - return self.source:type() -end -function audio:typeOf() - return self.source:typeOf() -end ---Events -function audio:onResume(func) - table.insert(self.func4,func) -end -function audio:onPlay(func) - table.insert(self.func3,func) -end -function audio:onPause(func) - table.insert(self.func2,func) -end -function audio:onStop(func) - table.insert(self.func,func) -end ---[[ -Object:type |Done -Object:typeOf |Done -Source:clone |Done -Source:getAttenuationDistances |Done -Source:getChannels |Done -Source:getCone |Done -Source:getDirection |Done -Source:getPitch |Done -Source:getPosition |Done -Source:getRolloff |Done -Source:getVelocity |Done -Source:getVolume |Done -Source:getVolumeLimits |Done -Source:isLooping |Done -Source:isPaused |Done -Source:isPlaying |Done -Source:isRelative |Done -Source:isStatic |Done -Source:isStopped |Done -Source:pause |Done -Source:play |Done -Source:resume |Done -Source:rewind |Done -Source:seek |Done -Source:setAttenuationDistances |Done -Source:setCone |Done -Source:setDirection |Done -Source:setLooping |Done -Source:setPitch |Done -Source:setPosition |Done -Source:setRelative |Done -Source:setRolloff |Done -Source:setVelocity |Done -Source:setVolume |Done -Source:setVolumeLimits |Done -Source:stop |Done -Source:tell |Done -]] diff --git a/mulit/examples/love2d Threading Example/core/GuiManager.lua b/mulit/examples/love2d Threading Example/core/GuiManager.lua deleted file mode 100644 index f86fa69..0000000 --- a/mulit/examples/love2d Threading Example/core/GuiManager.lua +++ /dev/null @@ -1,4027 +0,0 @@ -utf8 = require("utf8") -_defaultfont = love.graphics.getFont() -gui = {} -gui.__index = gui -gui.TB={} -gui.Version="8.0.0" -- Is it really ready for release? -_GuiPro={GBoost=true,hasDrag=false,DragItem={},Children={},Visible=true,count=0,x=0,y=0,height=0,width=0,update=function(self) local things=GetAllChildren2(self) UpdateThings(things) end,draw=function(self) local things=GetAllChildren(self) DrawThings(things) end,getChildren=function(self) return self.Children end} -_GuiPro.Clips={} -_GuiPro.rotate=0 -setmetatable(_GuiPro, gui) -function gui:LoadInterface(file) - local add=".int" - if string.find(file,".",1,true) then add="" end - if love.filesystem.exists(file..add) then - a,b=pcall(love.filesystem.load(file..add)) - if a then - print("Loaded: "..file) - else - print("Error loading file: "..file) - print(a,b) - end - else - print("File does not exist!") - return false - end -end -function gui.LoadAll(dir) - files=love.filesystem.getDirectoryItems(dir) - for i=1,#files do - if string.sub(files[i],-4)==".int" then - gui:LoadInterface(dir.."/"..files[i]) - end - end -end - -function gui:Clickable() - local x,y,w,h=love.graphics.getScissor() - local mx=love.mouse.getX() - local my=love.mouse.getY() - if _GuiPro.HasStencel then - local obj=_GuiPro.StencelHolder - if self:isDescendant(obj) then - return math.sqrt((mx-obj.x)^2+(my-obj.y)^2)<=(obj.offset.size.x or 0) - end - end - if not(x) then - return true - end - return not(mx>x+w or mxy+h or myx+w or mxy+h or my self.x and x < self.x+self.width and y > self.y and y < self.y+self.height and self:TClickable(x,y) and self:eventable()) - end - end - self.id=-1 -end -multi:newTask(function() -- A bit of post-loading haha - gui.touchpressed=multi:newConnection() - gui.touchreleased=multi:newConnection() - gui.touchmoved=multi:newConnection() - love.touchpressed=Library.convert(love.touchpressed or function() end) - love.touchreleased=Library.convert(love.touchreleased or function() end) - love.touchmoved=Library.convert(love.touchmoved or function() end) - love.touchpressed:inject(function(id, x, y, dx, dy, pressure) gui.touchpressed:Fire(id, x, y, dx, dy, pressure) return {id, x, y, dx, dy, pressure} end,1) - love.touchreleased:inject(function(id, x, y, dx, dy, pressure) gui.touchreleased:Fire(id, x, y, dx, dy, pressure) return {id, x, y, dx, dy, pressure} end,1) - love.touchmoved:inject(function(id, x, y, dx, dy, pressure) gui.touchmoved:Fire(id, x, y, dx, dy, pressure) return {id, x, y, dx, dy, pressure} end,1) - _GuiPro.TouchReady=true - _GuiPro.TouchRegister={} - gui.touchpressed:connect(function(id, x, y, dx, dy, pressure) - for i,v in pairs(_GuiPro.TouchRegister) do - if #v.tid==0 then - if (x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable()) then - v:addTID(id) - v.touchcount=1 - for i=1,#v.ToFuncP do - v.ToFuncP[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) - end - end - elseif not(v:hasTID(id)) then - if (x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable()) then - v:addTID(id) - v.touchcount=v.touchcount+1 - for i=1,#v.ToFuncP do - v.ToFuncP[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) - end - end - end - end - end) - gui.touchreleased:connect(function(id, x, y, dx, dy, pressure) - for i,v in pairs(_GuiPro.TouchRegister) do - if v:hasTID(id) then - v:removeTID(id) - for i=1,#v.ToFuncR do - v.ToFuncR[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) - end - end - end - end) - gui.touchmoved:connect(function(id, x, y, dx, dy, pressure) - for i,v in pairs(_GuiPro.TouchRegister) do - if v:hasTID(id) and (x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable()) then - for i=1,#v.ToFuncM do - v.ToFuncM[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) - end - elseif v:hasTID(id) and not((x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable())) then - v:removeTID(id) - for i=1,#v.ToFuncR do - v.ToFuncR[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) - end - end - end - end) -end) --- now that that is done lets set up some more post loading checks -_GuiPro.int=multi:newProcess() -_GuiPro.int:Start() -_GuiPro.int:setJobSpeed(.001) -_GuiPro.EXACT=0 -_GuiPro.LAX=.01 -_GuiPro.LAZY=.05 --- now lets define the reg function -function gui.Compare(a,b,v,tp) - if tp==">" then - if (a+v>b or a-v>b) then - return true - end - elseif tp=="<" then - if (a+v=" then - if (a+v>=b or a-v>=b) then - return true - end - elseif tp=="==" then -- this one is gonna be tricky - if (a>=b-v and a<=b+v) or (b>=a-v and b<=a+v) then - return true - end - end - return false -end -function gui:regesterTouch() - local obj=self - obj.ToFuncP={} - obj.ToFuncM={} - obj.ToFuncR={} - obj.To2Func={} - obj.ToDTFunc={} - obj.touchRendering =_GuiPro.EXACT -- exact(0), lax(), # - function obj:removeTID(id) - for i=1,#self.tid do - if self.tid[i]==id then - table.remove(self.tid,i) - self.touchcount=self.touchcount-1 - return - end - end - end - function obj:hasTID(id) - for i=1,#self.tid do - if self.tid[i]==id then - return true - end - end - return false - end - obj.txl1=0 - obj.tyl1=0 - obj.txl2=0 - obj.tyl2=0 - obj.LS=0 - obj:OnUpdate(function(self) - if self.touchcount==2 then - local x1,y1=love.touch.getPosition( self.tid[1] ) - local x2,y2=love.touch.getPosition( self.tid[2] ) - local CS=math.sqrt((x2-x1)^2+(y2-y1)^2) - if gui.Compare(CS,self.LS,self.touchRendering,">") then - for i=1,#self.To2Func do - self.To2Func[i](self,CS,x1-self.x,y1-self.y,x2-self.x,y2-self.y) - end - elseif gui.Compare(CS,self.LS,self.touchRendering,"<") then - for i=1,#self.To2Func do - self.To2Func[i](self,-CS,x1-self.x,y1-self.y,x2-self.x,y2-self.y) - end - elseif gui.Compare(CS,self.LS,self.touchRendering,"==") then - for i=1,#self.To2Func do - self.To2Func[i](self,0,x1-self.x,y1-self.y,x2-self.x,y2-self.y) - end - end - -- if self.txl1~=x1 or self.txl2~=x2 or self.tyl1~=y1 or self.tyl2~=y2 then - -- for i=1,#self.To2Func do - -- self.To2Func[i](self,0,x1-self.x,y1-self.y,x2-self.x,y2-self.y) - -- end - -- end - self.LS=CS - self.txl1=x1 - self.txl2=x2 - self.tyl1=y1 - self.tyl2=y2 - end - end) - function obj:OnDoubleTap(func) - table.insert(self.ToDTFunc,func) - end - function obj:On2TouchMoved(func) - table.insert(self.To2Func,func) - end - function obj:addTID(id) - table.insert(self.tid,id) - end - function obj:OnTouchPressed(func) - table.insert(self.ToFuncP,func) -- event for touches - end - function obj:OnTouchReleased(func) -- event for touches - table.insert(self.ToFuncR,func) - end - function obj:OnTouchMoved(func) -- event for touches - table.insert(self.ToFuncM,func) - end - if _GuiPro.TouchReady then -- my sneaky test - print("Registred: "..tostring(obj)) - table.insert(_GuiPro.TouchRegister,obj) - else - print("Attempting to register: "..tostring(obj)) - _GuiPro.int:newJob(function() table.insert(_GuiPro.TouchRegister,obj) end) -- a sneaky way to ensure that your object gets registered eventually, even if you call the method before the touch patch was activated. - end -end - -function UpdateThings(items) - for i=#items,1,-1 do - if items[i]:LClicked() then - for g=1,#items[i].funcs do - items[i].funcs[g]("l",items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) - end - elseif items[i]:RClicked() then - for g=1,#items[i].funcs do - items[i].funcs[g]("r",items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) - end - elseif items[i]:MClicked() then - for g=1,#items[i].funcs do - items[i].funcs[g]("m",items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) - end - end - if not(items[i]:LClicked()) and items[i].LRE then - for g=1,#items[i].funcs2 do - items[i].funcs2[g]("l",items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) - end - elseif not(items[i]:RClicked()) and items[i].RRE then - for g=1,#items[i].funcs2 do - items[i].funcs2[g]("r",items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) - end - elseif not(items[i]:MClicked()) and items[i].MRE then - for g=1,#items[i].funcs2 do - items[i].funcs2[g]("m",items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) - end - end - if items[i]:Hovering() and items[i].HE==false then - for g=1,#items[i].funcs3 do - items[i].funcs3[g](items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) - end - elseif not(items[i]:Hovering()) and items[i].HE==true then - for g=1,#items[i].funcs4 do - items[i].funcs4[g](items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) - end - elseif items[i]:Hovering() then - for g=1,#items[i].func9 do - items[i].func9[g](items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) - end - end - for g=1,#items[i].funcs5 do - items[i].funcs5[g](items[i]) - end - end -end -function GetAllChildren(Object) - local Stuff = {} - function Seek(Items) - for i=1,#Items do - if Items[i].Visible==true then - table.insert(Stuff,Items[i]) - local NItems = Items[i]:getChildren() - if NItems ~= nil then - Seek(NItems) - end - end - end - end - local Objs = Object:getChildren() - for i=1,#Objs do - if Objs[i].Visible==true then - table.insert(Stuff,Objs[i]) - local Items = Objs[i]:getChildren() - if Items ~= nil then - Seek(Items) - end - end - end - return Stuff -end -function GetAllChildren2(Object) - local Stuff = {} - function Seek(Items) - for i=1,#Items do - table.insert(Stuff,Items[i]) - local NItems = Items[i]:getChildren() - if NItems ~= nil then - Seek(NItems) - end - end - end - local Objs = Object:getChildren() - for i=1,#Objs do - table.insert(Stuff,Objs[i]) - local Items = Objs[i]:getChildren() - if Items ~= nil then - Seek(Items) - end - end - return Stuff -end -function gui:getTile(i,x,y,w,h)-- returns imagedata - if type(i)=="string" then - i=love.graphics.newImage(i) - elseif type(i)=="userdata" then - -- do nothing - elseif string.find(self.Type,"Image",1,true) then - local i,x,y,w,h=self.Image,i,x,y,w - else - error("getTile invalid args!!! Usage: ImageElement:getTile(x,y,w,h) or gui:getTile(imagedata,x,y,w,h)") - end - local iw,ih=i:getDimensions() - local id,_id=i:getData(),love.image.newImageData(w,h) - for _x=x,w+x-1 do - for _y=y,h+y-1 do - -- - _id:setPixel(_x-x,_y-y,id:getPixel(_x,_y)) - end - end - return love.graphics.newImage(_id) -end -function gui:newAnim(file,delay, x, y, w, h, sx ,sy ,sw ,sh) - local x,y,w,h,sx,sy,sw,sh=filter(file, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("ImageAnimation",file, x, y, w, h, sx ,sy ,sw ,sh) - c.Visibility=0 - c.ImageVisibility=1 - c.delay=delay or .05 - c.files={} - c.AnimStart={} - c.AnimEnd={} - local _files=alphanumsort(love.filesystem.getDirectoryItems(file)) - for i=1,#_files do - if string.sub(_files[i],-1,-1)~="b" then - table.insert(c.files,love.graphics.newImage(file.."/".._files[i])) - end - end - c.step=multi:newTStep(1,#c.files,1,c.delay) - c.step.parent=c - c.rotation=0 - c.step:OnStart(function(step) - for i=1,#step.parent.AnimStart do - step.parent.AnimStart[i](step.parent) - end - end) - c.step:OnStep(function(pos,step) - step.parent:SetImage(step.parent.files[pos]) - end) - c.step:OnEnd(function(step) - for i=1,#step.parent.AnimEnd do - step.parent.AnimEnd[i](step.parent) - end - end) - function c:OnAnimStart(func) - table.insert(self.AnimStart,func) - end - function c:OnAnimEnd(func) - table.insert(self.AnimEnd,func) - end - function c:Pause() - self.step:Pause() - end - function c:Resume() - self.step:Resume() - end - function c:Reset() - self.step.pos=1 - end - function c:getFrames() - return #self.files - end - function c:getFrame() - return self.step.pos - end - function c:setFrame(n) - return self:SetImage(self.files[n]) - end - return c -end -function gui:newAnimFromData(data,delay, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("ImageAnimation","FromFile", x, y, w, h, sx ,sy ,sw ,sh) - c.Visibility=0 - c.ImageVisibility=1 - c.delay=delay or .05 - c.files=data - c.AnimStart={} - c.AnimEnd={} - c:SetImage(c.files[1]) - c.step=multi:newTStep(1,#c.files,1,c.delay) - c.step.parent=c - c.rotation=0 - c.step:OnStart(function(step) - for i=1,#step.parent.AnimStart do - step.parent.AnimStart[i](step.parent) - end - end) - c.step:OnStep(function(pos,step) - step.parent:SetImage(step.parent.files[pos]) - end) - c.step:OnEnd(function(step) - for i=1,#step.parent.AnimEnd do - step.parent.AnimEnd[i](step.parent) - end - end) - function c:OnAnimStart(func) - table.insert(self.AnimStart,func) - end - function c:OnAnimEnd(func) - table.insert(self.AnimEnd,func) - end - function c:Pause() - self.step:Pause() - end - function c:Resume() - self.step:Resume() - end - function c:Reset() - self.step.pos=1 - end - function c:getFrames() - return #self.files - end - function c:getFrame() - return self.step.pos - end - function c:setFrame(n) - return self:SetImage(self.files[n]) - end - return c -end -function gui:newAnimFromTiles(file,xd,yd,delay, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(file, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("ImageAnimation",file, x, y, w, h, sx ,sy ,sw ,sh) - local im=love.graphics.newImage(file) - local _x,_y=im:getDimensions() - c.Visibility=0 - c.ImageVisibility=1 - c.delay=delay or .05 - c.files={} - c.AnimStart={} - c.AnimEnd={} - for i=0,_y/yd-1 do - for j=0,_x/xd-1 do - table.insert(c.files,gui:getTile(im,j*xd,i*yd,xd,yd)) - end - end - c:SetImage(c.files[1]) - c.step=multi:newTStep(1,#c.files,1,c.delay) - c.step.parent=c - c.rotation=0 - c.step:OnStart(function(step) - for i=1,#step.parent.AnimStart do - step.parent.AnimStart[i](step.parent) - end - end) - c.step:OnStep(function(pos,step) - step.parent:SetImage(step.parent.files[pos]) - end) - c.step:OnEnd(function(step) - for i=1,#step.parent.AnimEnd do - step.parent.AnimEnd[i](step.parent) - end - end) - function c:OnAnimStart(func) - table.insert(self.AnimStart,func) - end - function c:OnAnimEnd(func) - table.insert(self.AnimEnd,func) - end - function c:Pause() - self.step:Pause() - end - function c:Resume() - self.step:Resume() - end - function c:Reset() - self.step.pos=1 - end - function c:getFrames() - return #self.files - end - function c:getFrame() - return self.step.pos - end - function c:setFrame(n) - return self:SetImage(self.files[n]) - end - return c -end -function gui:newFullImageLabel(i,name) - return self:newImageLabel(i,name,0,0,0,0,0,0,1,1) -end -function gui:newImageButton(i,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("ImageButton",name, x, y, w, h, sx ,sy ,sw ,sh) - if type(i)=="string" then - c.Image=love.graphics.newImage(i) - else - c.Image=i - end - c.Visibility=0 - c.ImageVisibility=1 - c.rotation=0 - if c.Image~=nil then - c.ImageHeigth=c.Image:getHeight() - c.ImageHeight=c.Image:getHeight() - c.ImageWidth=c.Image:getWidth() - c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) - end - c:OnEnter(function() - --love.mouse.setCursor(_GuiPro.CursorH) - end) - c:OnExit(function() - --love.mouse.setCursor(_GuiPro.CursorN) - end) - return c -end -function gui:newImageLabel(i,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("ImageLabel",name, x, y, w, h, sx ,sy ,sw ,sh) - if type(i)=="string" then - c.Image=love.graphics.newImage(i) - else - c.Image=i - end - c.Visibility=0 - c.ImageVisibility=1 - c.rotation=0 - if c.Image~=nil then - c.ImageHeigth=c.Image:getHeight() - c.ImageWidth=c.Image:getWidth() - c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) - end - return c -end -function gui:newVideo(name,i,x,y,w,h,sx,sy,sw,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("Video",name, x, y, w, h, sx ,sy ,sw ,sh) - if type(i)=="string" then - c.Video=love.graphics.newVideo(i) - else - c.Video=i - end - c.Visibility=0 - c.VideoVisibility=1 - c.rotation=0 - if c.Video~=nil then - c.VideoHeigth=c.Video:getHeight() - c.VideoWidth=c.Video:getWidth() - c.Quad=love.graphics.newQuad(0,0,w,h,c.VideoWidth,c.VideoHeigth) - end - c.funcV={} - function c:Play() - self.handStart=true - self.Video:play() - end - function c:Pause() - self.Video:pause() - end - c.Resume=c.Play - function c:Stop() - self.handStart=false - self:Pause() - self:Rewind() - for i=1,# self.funcV do - self.funcV[i](self) - end - end - function c:OnVideoStopped(func) - table.insert(self.funcV,func) - end - function c:Rewind() - self.Video:rewind() - end - function c:Restart() - self:Rewind() - self:Play() - end - function c:Seek(o) - self.Video:seek(o) - end - function c:Tell() - self.Video:tell() - end - function c:SetFilter(min, mag, anisotropy) - self.Video:setFilter(min, mag, anisotropy) - end - function c:IsPlaying() - return self.Video:isPlaying() - end - c:OnUpdate(function(self) - if self.Video:isPlaying()==false and self.handStart == true then - self:Stop() - end - end) - return c -end -function gui:SetImage(i) - if type(i)=="string" then - self.Image=love.graphics.newImage(i) - else - self.Image=i - end - if self.Image~=nil then - self.ImageHeigth=self.Image:getHeight() - self.ImageWidth=self.Image:getWidth() - self.Quad=love.graphics.newQuad(0,0,self.width,self.height,self.ImageWidth,self.ImageHeigth) - end - return self.ImageWidth,self.ImageHeigth -end -function gui:UpdateImage() - self.ImageHeigth=self.Image:getHeight() - self.ImageWidth=self.Image:getWidth() - self.Quad=love.graphics.newQuad(0,0,self.width,self.height,self.ImageWidth,self.ImageHeigth) -end -function gui:newDropFrame(name,x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("DropFrame",name, x, y, w, h, sx ,sy ,sw ,sh) - c.WasBeingDragged=false - c.IsBeingDragged=false - c.Draggable=false - c.funcD={} - function c:GetDroppedItems() - local t=self:getChildren() - local tab={} - for i=1,#t do - if t[i].Type=="TextImageButtonFrameDrag" then - table.insert(tab,t[i]) - end - end - return tab - end - function c:OnDropped(func) - table.insert(self.funcD,func) - end - c:OnUpdate(function(self) - if _GuiPro.DragItem then - if _GuiPro.DragItem.Type=="TextImageButtonFrameDrag" and love.mouse.isDown(_GuiPro.DragItem.dragbut or "m")==false and self:IsHovering() then - local t=_GuiPro.DragItem - _GuiPro.DragItem={} - for i=1,#t.funcD do - t.funcD[i](self,t) - end - for i=1,#self.funcD do - self.funcD[i](self,t) - end - _GuiPro.hasDrag=false - end - end - end) - return c -end -function gui:newFrame(name,x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("Frame",name, x, y, w, h, sx ,sy ,sw ,sh) - c.WasBeingDragged=false - c.IsBeingDragged=false - c.Draggable=false - return c -end -function gui:newFullFrame(name) - name=name or "" - return self:newFrame(name,0,0,0,0,0,0,1,1) -end - -function gui:newTabFrame(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=gui:newFrame(name, x, y, w, h, sx ,sy ,sw ,sh) - c.tabheight=20 - c.Holder=c:newFrame("Holder",0,c.tabheight,0,0,0,0,1,1) - c.TabHolder=c:newFrame("TabHolder",0,0,0,c.tabheight,0,0,1) - function c:setTabHeight(n) - self.tabheight=n - self.Holder:SetDualDim(0,-self.tabheight,0,0,0,0,1,1) - end - function c:addTab(name,colorT,colorH) - if colorT and not(colorH) then - colorH=colorT - end - local tab=self.TabHolder:newTextButton(name,name,0,0,0,0,0,0,0,1) - tab.Tween=-3 - if colorT then - tab.Color=colorT - end - local holder=self.Holder:newFrame(name,0,0,0,0,0,0,1,1) - if colorH then - holder.Color=colorH - end - tab.frame=holder - tab:OnReleased(function(b,self) - if b=="l" then - local tt=self.Parent:getChildren() - local th=self.Parent.Parent.Holder:getChildren() - for i=1,#th do - th[i].Visible=false - end - for i=1,#tt do - tt[i].frame.Visible=false - tt[i].BorderSize=1 - end - self.BorderSize=0 - self.frame.Visible=true - end - end) - local tt=self.TabHolder:getChildren() - for i=1,#tt do - tt[i].frame.Visible=false - tt[i].BorderSize=1 - end - tab.frame.Visible=true - tab.BorderSize=0 - return tab,holder - end - c:OnUpdate(function(self) - local th=self.TabHolder:getChildren() - local l=self.width/#th - for i=1,#th do - th[i]:SetDualDim(l*(i-1),0,l) - end - if #th==0 then - self:Destroy() - end - end) - return c -end -function gui:newDragItem(t,i,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("TextImageButtonFrameDrag",name, x, y, w, h, sx ,sy ,sw ,sh) - c.WasBeingDragged=false - c.IsBeingDragged=false - c.Draggable=true - c.funcD={} - if type(i)=="string" then - c.Image=love.graphics.newImage(i) - c.ImageVisibility=1 - c.ImageHeigth=c.Image:getHeight() - c.ImageWidth=c.Image:getWidth() - c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) - elseif type(i)=="image" then - c.Image=i - c.ImageVisibility=1 - c.ImageHeigth=c.Image:getHeight() - c.ImageWidth=c.Image:getWidth() - c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) - end - c:OnDragStart(function(self,x,y) - if _GuiPro.hasDrag==false then - self:setParent(_GuiPro) - self:SetDualDim(x,y) - self:TopStack() - end - end) - c.rotation=0 - c.Tween=0 - c.XTween=0 - c.text = t - c.AutoScaleText=false - c.FontHeight=_defaultfont:getHeight() - c.Font=_defaultfont - c.FontSize=15 - c.TextFormat="center" - c.TextVisibility=1 - c.TextColor = {0, 0, 0} - function c:OnDropped(func) - table.insert(self.funcD,func) - end - c:OnUpdate(function(self) - if love.mouse.isDown("m" or self.dragbut)==false and self==_GuiPro.DragItem and self.hovering==false then - _GuiPro.DragItem={} - for i=1,#self.func7 do - self.func7[i](self,(love.mouse.getX())-self.width/2,(love.mouse.getY())-self.height/2) - end - end - end) - return c -end -function gui:newItem(t,i,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("TextImageButtonFrame",name, x, y, w, h, sx ,sy ,sw ,sh) - if type(i)=="string" then - c.Image=love.graphics.newImage(i) - else - c.Image=i - end - c.rotation=0 - c.ImageVisibility=1 - c.Draggable=false - if c.Image~=nil then - c.ImageHeigth=c.Image:getHeight() - c.ImageWidth=c.Image:getWidth() - c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) - end - c.Tween=0 - c.XTween=0 - c.text = t - c.AutoScaleText=false - c.FontHeight=_defaultfont:getHeight() - c.Font=_defaultfont - c.FontSize=15 - c.TextFormat="center" - c.TextVisibility=1 -- 0=invisible,1=solid (self.TextVisibility*254+1) - c.TextColor = {0, 0, 0} - return c -end -function gui:addDominance() - _GuiPro.TopHovered=self -end -function gui:addHotKey(key) - local temp=self:newFrame(0,0,0,0) - temp.Visible=false - temp:setHotKey(key) - return temp -end -function gui:AdvTextBox(txt,x,y,w,h,sx,sy,sw,sh) - name="AdvTextBox" - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("AdvTextBoxFrame",name, x, y, w, 30, sx ,sy ,sw ,sh) - c.Draggable=true - c.dragbut="r" - c.BorderSize=0 - c:ApplyGradient{Color.Blue,Color.sexy_purple} - c:newTextLabel(txt,"Holder",0,0,0,h-30,0,1,1,0).Color=Color.sexy_purple - c.funcO={} - c.funcX={} - c:OnDragStart(function(self) - self:TopStack() - end) - --local temp = c:newTextButton("X","Close",-25,5,20,20,1) - --temp.Tween=-5 - --temp.XTween=-2 - --temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent) end end) - --temp.Color=Color.Red - c.tLink=c:newTextBox("puttext","TextBox",5,h-95,-40,30,0,1,1,1) - c.tLink.Color=Color.light_gray - c.tLink.ClearOnFocus=true - c.tLink:OnFocus(function(self) self.ClearOnFocus=false end) - local temp=c:newTextButton("OK","Ok",-35,h-65,30,30,1,1) - temp:OnReleased(function(b,self) for i=1,#self.Parent.funcO do self.Parent.funcO[i](self.Parent,self.Parent.tLink.text) end end) - temp.Color=Color.Green - temp.XTween=-2 - local temp=c:newTextButton("X","Cancel",-35,h-95,30,30,1,1) - temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent,self.Parent.tLink.text) end end) - temp.Color=Color.Red - temp.XTween=-2 - function c:Close() - self.Visible=false - end - function c:Open() - self.Visible=true - end - function c:OnOk(func) - table.insert(self.funcO,func) - end - function c:OnX(func) - table.insert(self.funcX,func) - end - return c -end -function alphanumsort(o) - local function padnum(d) local dec, n = string.match(d, "(%.?)0*(.+)") - return #dec > 0 and ("%.12f"):format(d) or ("%s%03d%s"):format(dec, #n, n) - end - table.sort(o, function(a,b) return tostring(a):gsub("%.?%d+",padnum)..("%3d"):format(#b)< tostring(b):gsub("%.?%d+",padnum)..("%3d"):format(#a) end) - return o -end -function gui:anchorRight(n) - self:SetDualDim(-(self.width+n),nil,nil,nil,1) -end -function _GuiPro.gradient(colors) - local direction = colors.direction or "horizontal" - colors.direction=nil - trans = colors.trans or 255 - trans=math.floor(trans) - if direction == "horizontal" then - direction = true - elseif direction == "vertical" then - direction = false - else - error("Invalid direction '" .. tostring(direction) "' for gradient. Horizontal or vertical expected.") - end - local result = love.image.newImageData(direction and 1 or #colors, direction and #colors or 1) - for __i, color in ipairs(colors) do - local x, y - if direction then - x, y = 0, __i - 1 - else - x, y = __i - 1, 0 - end - result:setPixel(x, y, color[1], color[2], color[3], trans) - end - result = love.graphics.newImage(result) - result:setFilter('linear', 'linear') - return result -end -function _GuiPro.drawinrect(img, x, y, w, h, r, ox, oy, kx, ky) - love.graphics.draw(img, x, y, r, w / img:getWidth(), h / img:getHeight(), ox, oy, kx, ky) -end -function gui:ApplyGradient(rules) - self.Image=nil - self.Type=self.Type.."w/GradImage" - self.rotation=0 - self.ImageVisibility=rules.visibility or 1 - self:SetImage(_GuiPro.gradient(rules)) -end -function gui:BottomStack() - childs=self.Parent:getChildren() - for i=1,#childs do - if childs[i]==self then - table.remove(self.Parent.Children,i) - table.insert(self.Parent.Children,1,self) - break - end - end -end -function gui:Center() - local x,y=self:getFullSize() - self:SetDualDim(-math.floor(x/2),-math.floor(y/2),nil,nil,.5,.5) -end -function gui:centerX() - self:SetDualDim(-(self.width/2),nil,nil,nil,.5) -end -function gui:centerY() - self:SetDualDim(nil,-(self.height/2),nil,nil,nil,.5) -end -function gui:Destroy() - check=self.Parent:getChildren() - local cc=0 - for cc=1,#check do - if check[cc]==self then - table.remove(self.Parent.Children,cc) - end - end -end -function gui:disrespectHierarchy() - _GuiPro.Hierarchy=false -end -function gui:GetAllChildren() - local Stuff = {} - function Seek(Items) - for i=1,#Items do - if Items[i].Visible==true then - table.insert(Stuff,Items[i]) - local NItems = Items[i]:getChildren() - if NItems ~= nil then - Seek(NItems) - end - end - end - end - local Objs = self:getChildren() - for i=1,#Objs do - if Objs[i].Visible==true then - table.insert(Stuff,Objs[i]) - local Items = Objs[i]:getChildren() - if Items ~= nil then - Seek(Items) - end - end - end - return Stuff -end -function gui:GetChild(name) - return self.Children[name] or self -end -function gui:getChildren() - return self.Children -end -function gui:getColor(cindex) - return Color[cindex] -end -function gui:getFullSize() - local maxx,maxy=-math.huge,-math.huge - local temp = self:GetAllChildren() - for i=1,#temp do - if temp[i].width>maxx then - maxx=temp[i].width+temp[i].offset.pos.x - elseif temp[i].height>maxy then - maxy=temp[i].height+temp[i].offset.pos.y - end - end - return maxx,maxy -end -function gui:getHighest() - if self.Children[#self.Children]~=nil then - return self.Children[#self.Children] - end -end -function gui:getLowest() - if self.Children[1]~=nil then - return self.Children[1] - end -end -function InGrid(i,x,y,s) - return math.floor((i-1)/x)*s,(i-1)*s-(math.floor((i-1)/y)*(s*x)) -end -function InGridX(i,w,h,xs,ys) - local xc,yc=math.floor(w/xs),math.floor(h/ys) - local xi,yi=(i-1)%xc,math.floor((i-1)/xc) - return xi*xs,yi*ys -end -function InGridY(i,w,h,xs,ys) - local xc,yc=math.floor(w/xs),math.floor(h/ys) - local xi,yi=math.floor((i-1)/yc),(i-1)%yc - return xi*xs,yi*ys -end -function gui:isDescendant(obj) - local things=obj:GetAllChildren() - for i=1,#things do - if things[i]==self then - return true - end - end - return false -end -function gui:isHighest() - return (self==self.Parent:getHighest()) -end -function gui:IsHovering() - return (love.mouse.getX() > self.x and love.mouse.getX() < self.x+self.width and love.mouse.getY() > self.y and love.mouse.getY() < self.y+self.height) -end -function gui:isLowest() - return (self==self.Parent:getLowest()) -end -function gui.massMutate(t,...) - local mut={...} - for i=1,#mut do - mut[i]:Mutate(t) - end -end -function gui:Move(x,y) - self.offset.pos.x=self.offset.pos.x+x - self.offset.pos.y=self.offset.pos.y+y -end -if love.filesystem.exists("CheckBoxes.png") then - _GuiPro.UC=gui:getTile("CheckBoxes.png",0,0,16,16) - _GuiPro.C=gui:getTile("CheckBoxes.png",16,0,16,16) - _GuiPro.UCH=gui:getTile("CheckBoxes.png",0,16,16,16) - _GuiPro.CH=gui:getTile("CheckBoxes.png",16,16,16,16) -end -function gui:newCheckBox(name,x,y) - if not(_GuiPro.UC) then error("CheckBoxes.png not found! Cannot currently use checkbox without the data") end - if type(name)~="String" then - x,y,name=name,x,"CheckBox" - end - local c=self:newImageLabel(_GuiPro.UC,name, x, y, 16,16) - c.Visibility=0 - c.check=false - c:OnEnter(function(self) - if self.check then - self:SetImage(_GuiPro.CH) - else - self:SetImage(_GuiPro.UCH) - end - end) - function c:isChecked() - return self.check - end - c:OnExit(function(self) - if self.check then - self:SetImage(_GuiPro.C) - else - self:SetImage(_GuiPro.UC) - end - end) - c:OnReleased(function(b,self) - self.check=not(self.check) - if self.check then - self:SetImage(_GuiPro.CH) - else - self:SetImage(_GuiPro.UCH) - end - end) - return c -end -function gui:newMessageBox(txt,x,y,w,h,sx,sy,sw,sh) - name="MessageBox" - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("MessageBoxFrame",name, x, y, w, 30, sx ,sy ,sw ,sh) - c.Draggable=true - c.dragbut="r" - c:ApplyGradient{Color.Blue,Color.sexy_purple} - c.BorderSize=0 - c:newTextLabel(txt,"Holder",0,0,0,h-30,0,1,1,0).Color=Color.sexy_purple - c.funcO={} - c.funcX={} - c:OnDragStart(function(self) - self:TopStack() - end) - local temp = c:newTextButton("X","Close",-25,5,20,20,1) - temp.Tween=-5 - temp.XTween=-2 - temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent) end end) - temp.Color=Color.Red - local temp=c:newTextButton("OK","Ok",0,h-65,0,30,.25,1,.5) - temp:OnReleased(function(b,self) for i=1,#self.Parent.funcO do self.Parent.funcO[i](self.Parent) end end) - temp.Color=Color.Green - function c:Close() - self.Visible=false - end - function c:Open() - self.Visible=true - end - function c:OnOk(func) - table.insert(self.funcO,func) - end - function c:OnX(func) - table.insert(self.funcX,func) - end - return c -end -function gui:newPart(x, y,w ,h , sx ,sy ,sw ,sh) - local c = {} - setmetatable(c, gui) - if self==gui then - c.Parent=_GuiPro - else - c.Parent=self - end - c.funcs={} - c.funcs2={} - c.funcs3={} - c.funcs4={} - c.funcs5={} - c.func6={} - c.func7={} - c.func8={} - c.func9={} - c.func10={} - c.form="rectangle" - c.Color = {255, 255, 255} - c.scale={} - c.scale.size={} - c.scale.size.x=sw or 0 - c.scale.size.y=sh or 0 - c.offset={} - c.offset.size={} - c.offset.size.x=w or 0 - c.offset.size.y=h or 0 - c.scale.pos={} - c.scale.pos.x=sx or 0 - c.scale.pos.y=sy or 0 - c.offset.pos={} - c.offset.pos.x=x or 0 - c.offset.pos.y=y or 0 - c.VIS=true - c.Visible=true - c.Visibility=1 - c.BorderColor={0,0,0} - c.BorderSize=0 - c.Type="Part" - c.Name="GuiPart" - _GuiPro.count=_GuiPro.count+1 - c.x=(c.Parent.width*c.scale.pos.x)+c.offset.pos.x+c.Parent.x - c.y=(c.Parent.height*c.scale.pos.y)+c.offset.pos.y+c.Parent.y - c.width=(c.Parent.width*c.scale.size.x)+c.offset.size.x - c.height=(c.Parent.height*c.scale.size.y)+c.offset.size.y - table.insert(c.Parent.Children,c) - return c -end -function gui:newProgressBar(txt,x,y,w,h,sx,sy,sw,sh) - name="newProgressBar" - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("newProgressBarFrame",name, x, y, w, 30, sx ,sy ,sw ,sh) - c.Draggable=true - c.dragbut="r" - c.BorderSize=0 - c:ApplyGradient{Color.Blue,Color.sexy_purple} - c:newTextLabel(txt,"Holder",0,0,0,h-30,0,1,1,0).Color=Color.sexy_purple - c.funcO={} - c.funcX={} - c:OnDragStart(function(self) - self:TopStack() - end) - local temp = c:newTextButton("X","Close",-25,5,20,20,1) - temp.Tween=-5 - temp.XTween=-2 - temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent) end end) - temp.Color=Color.Red - c.BarBG=c:newTextButton("",5,h-65,-10,30,0,1,1) - c.BarBG:ApplyGradient{Color.Red,Color.light_red} - c.Bar=c.BarBG:newTextLabel("",0,0,0,0,0,0,0,1) - c.Bar:ApplyGradient{Color.Green,Color.light_green} - c.BarDisp=c.BarBG:newTextLabel("0%","0%",0,0,0,0,0,0,1,1) - c.BarDisp.Visibility=0 - c.BarDisp.Link=c.Bar - c.BarDisp:OnUpdate(function(self) - self.text=self.Link.scale.size.x*100 .."%" - end) - c.Func1={} - function c:On100(func) - table.insert(self.Func1,func) - end - c:OnUpdate(function(self) - if self.Bar.scale.size.x*100>=100 then - for P=1,#self.Func1 do - self.Func1[P](self) - end - end - end) - function c:SetPercentage(n) - self.Bar:SetDualDim(0,0,0,0,0,0,n/100,1) - end - return c -end -function gui:newScrollBar(color1,color2) - local scrollbar=self:newFrame(-20,0,20,0,1,0,0,1) - scrollbar.funcS={} - scrollbar.Color=color1 or Color.saddle_brown - scrollbar:OnClicked(function(b,self,x,y) - love.mouse.setX(self.x+10) - if y>=10 and y<=self.height-10 then - self.mover:SetDualDim(0,y-10) - end - if y<10 then - love.mouse.setY(10+self.y) - end - if y>self.height-10 then - love.mouse.setY((self.height-10)+self.y) - end - for i=1,#self.funcS do - self.funcS[i](self,self:getPosition()) - end - end) - scrollbar:OnEnter(function(self) - self:addDominance() - end) - scrollbar:OnExit(function(self) - self:removeDominance() - end) - scrollbar.mover=scrollbar:newTextButton("","",0,0,20,20) - scrollbar.mover.Color=color2 or Color.light_brown - function scrollbar:getPosition() - return ((self.mover.offset.pos.y)/(self.height-20))*100 - end - function scrollbar:setPosition(n) - print((self.height-20),n) - self.mover.offset.pos.y=((self.height-20)/(100/n)) - for i=1,#self.funcS do - self.funcS[i](self,self:getPosition()) - end - end - function scrollbar:OnScroll(func) - table.insert(self.funcS,func) - end - return scrollbar -end -function gui:newScrollMenu(title,tabN,onloop,x, y, w, h, sx ,sy ,sw ,sh) - local Main = self:newFrame(x, y, w, h, sx ,sy ,sw ,sh) - local Title=Main:newTextButton(title,"Title",0,0,0,20,0,0,1) - Title.Tween=-4 - Title.FontSize=12 - Title:OnReleased(function(b,self) - self.Parent.Tick=not(self.Parent.Tick) - end) - local scroll=Main:newTextButton("","Scroll",-20,20,20,-20,1,0,0,1) - scroll:OnClicked(function(b,self,x,y) - self.Parent.Mover:SetDualDim(0,y-10,20,20) - if self.Parent.Mover.offset.pos.y<0 then - self.Parent.Mover:SetDualDim(0,0,20,20) - end - if self.Parent.Mover.offset.pos.y>self.Parent.height-40 then - self.Parent.Mover:SetDualDim(0,self.Parent.height-40,20,20) - end - local temp = #self.Parent.TList - self.Parent.pos=(math.floor((temp*self.Parent.Mover.offset.pos.y)/self.height))+1 - end) - Main:OnUpdate(function(self) - if self.Tick==false then - self.Visibility=0 - end - end) - scroll:OnUpdate(function(self) - self.Visible=self.Parent.Tick - end) - local Mover=scroll:newTextLabel("",0,0,20,20) - Main.Mover=Mover - Main.TList=tabN - Main.pos=1 - Main.Tick=true - function Main:Update(title,tabN,onloop) - ch=self:getChildren() - for i=#ch,1,-1 do - ch[i]:Destroy() - end - Title=Main:newTextButton(title,"Title",0,0,0,20,0,0,1) - Title.Tween=-4 - Title.FontSize=12 - Title:OnReleased(function(b,self) - self.Parent.Tick=not(self.Parent.Tick) - end) - scroll=Main:newTextButton("","Scroll",-20,20,20,-20,1,0,0,1) - scroll:OnClicked(function(b,self,x,y) - self.Parent.Mover:SetDualDim(0,y-10,20,20) - if self.Parent.Mover.offset.pos.y<0 then - self.Parent.Mover:SetDualDim(0,0,20,20) - end - if self.Parent.Mover.offset.pos.y>self.Parent.height-40 then - self.Parent.Mover:SetDualDim(0,self.Parent.height-40,20,20) - end - local temp = #self.Parent.TList - self.Parent.pos=(math.floor((temp*self.Parent.Mover.offset.pos.y)/self.height))+1 - end) - local Mover=scroll:newTextLabel("",0,0,20,20) - Main.Mover=Mover - Main.TList=tabN - Main.pos=1 - Main.Tick=true - scroll:OnUpdate(function(self) - self.Visible=self.Parent.Tick - end) - for i=1,math.floor(Main.height/20)-1 do - local temp=Main:newTextButton("","Item"..i,0,i*20,-20,20,0,0,1) - temp.FontSize=10 - temp.Tween=-4 - temp.pos=i - temp:OnUpdate(function(self) - self.text=self.Parent.TList[(self.Parent.pos+self.pos)-1] - self.Visible=self.Parent.Tick - end) - if onloop then - onloop(temp,i) - end - end - end - io.write(tostring(Main.height).."\n") - for i=1,math.floor(Main.height/20)-1 do - local temp=Main:newTextButton("Item"..i,0,i*20,-20,20,0,0,1) - temp.FontSize=10 - temp.Tween=-4 - temp.pos=i - temp:OnUpdate(function(self) - if self.Parent.TList[(self.Parent.pos+self.pos)-1]~=nil then - self.text=self.Parent.TList[(self.Parent.pos+self.pos)-1] - else - self.text="" - end - self.Visible=self.Parent.Tick - end) - if onloop then - onloop(temp,i) - end - end - return Main -end -function gui:destroyAllChildren() - local c=self.Children - for i=1,#c do - c[i]:Destroy() - end -end -function gui:removeDominance() - _GuiPro.TopHovered=nil -end -function gui:respectHierarchy() - _GuiPro.Hierarchy=true -end -function gui.round(num, idp) - local mult = 10^(idp or 0) - return math.floor(num * mult + 0.5) / mult -end -function gui.setBG(i) - gui.ff:SetImage(i) -end -function gui:setColor(a,b,c) - if type(a)=="string" then - self.Color=Color[a] - elseif type(a)=="number" then - self.Color=Color.new(a,b,c) - end -end -function gui:setTextColor(a,b,c) - if type(a)=="string" then - self.TextColor=Color[a] - elseif type(a)=="number" then - self.TextColor=Color.new(a,b,c) - end -end -function gui:setDefualtFont(font) - _defaultfont = font -end -function gui:SetDualDim(x, y, w, h, sx ,sy ,sw ,sh) - if _GuiPro.DPI_ENABLED then - if x then - x=self.DPI*x - end - if y then - y=self.DPI*y - end - if w then - w=self.DPI*w - end - if h then - h=self.DPI*h - end - end - if sx then - self.scale.pos.x=sx - end - if sy then - self.scale.pos.y=sy - end - if x then - self.offset.pos.x=x - end - if y then - self.offset.pos.y=y - end - if sw then - self.scale.size.x=sw - end - if sh then - self.scale.size.y=sh - end - if w then - self.offset.size.x=w - end - if h then - self.offset.size.y=h - end - if self.Image then - self:SetImage(self.Image) - end -end -function gui:setDualDim(...) - self:SetDualDim(...) -end -function gui:setText(txt) - self.text=txt -end -function gui:getText(txt) - return self.text -end ---_GuiPro.CursorN=love.mouse.getSystemCursor("arrow") ---_GuiPro.CursorH=love.mouse.getSystemCursor("hand") -function gui:SetHand(img,x,y) - --_GuiPro.CursorN=love.mouse.newCursor(img,x,y) -end -function gui:setHotKey(key) - local tab=key:split("+") - self.hotkeys=tab - self.cooldown=false - self.Alarm=multi:newAlarm(1) - self.Alarm.parent=self - self.args={} - self.funcHK=multi:newConnection() - self.Alarm:OnRing(function(alarm) alarm.parent.cooldown=false end) - function self:OnHotKey(func) - self.funcHK:connect(func) - end - self:OnUpdate(function(self) - if self.cooldown then return end - for i=1,#self.hotkeys do - if not(love.keyboard.isDown(self.hotkeys[i])) then - return - end - end - self.cooldown=true - self.funcHK:Fire(self) - self.Alarm:Reset() - end) -end -function gui:SetHover(img,x,y) - --_GuiPro.CursorH=love.mouse.newCursor(img,x,y) -end -function gui:SetName(name) - self.Parent.Children[name]=self - self.Name=name -end -function gui:setNewFont(FontSize) - self.Font=love.graphics.setNewFont(tonumber(FontSize)) -end -function gui:setParent(parent,name)-- Needs fixing!!! - local temp=self.Parent:getChildren() - for i=1,#temp do - if temp[i]==self then - table.remove(self.Parent.Children,i) - break - end - end - table.insert(parent.Children,self) - self.Parent=parent - if name then - self:SetName(name) - end -end -function gui:setVisiblity(val) - self.Visible=val - self.oV=val - doto=self:GetAllChildren() - if val==false then - for i=1,#doto do - doto[i].Visible=val - end - else - for i=1,#doto do - doto[i].Visible=doto[i].oV - end - end -end -function gui:TopStack() - childs=self.Parent:getChildren() - for i=1,#childs do - if childs[i]==self then - table.remove(self.Parent.Children,i) - table.insert(self.Parent.Children,self) - break - end - end -end -function string:insert(p,s) - return ("%s%s%s"):format(self:sub(1,p), s, self:sub(p+1)) -end -function string:remove(p,l) - l=l or 1 - return ("%s%s"):format(self:sub(1,p-1), self:sub(p+l)) -end -function gui:newTextBox(t,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("TextBox",name, x, y, w, h, sx ,sy ,sw ,sh) - c.ClearOnFocus=false - c.LoseFocusOnEnter=true - c.Tween=0 - c.XTween=0 - c.FontHeight=_defaultfont:getHeight() - c.Font=_defaultfont - c.FontSize=15 - c.TextFormat="center" - c.text = t - c.ttext= t - c.AutoScaleText=false - c.TextVisibility=1 - c.Color = {220, 220, 220} - c.TextColor = {0, 0, 0} - c.Active=false - c.hidden=false - c.cursor={0,1} - c.mark=nil - c.arrowkeys=false - c.funcF={function() - love.keyboard.setTextInput(true) - end} - c.cooldown=false - c.cooldown2=false - c.funcE={function() - love.keyboard.setTextInput(false) - end} - function c:triggerEnter() - for cc=1,#self.funcE do - self.funcE[cc](self,self.ttext) - end - self.text="" - self.ttext="" - end - c.Enter=true - c.Alarm=multi:newAlarm(.1) - c.Alarm.parent=c - c.Alarm:OnRing(function(alarm) alarm.parent.cooldown=false end) - c.Alarm2=multi:newAlarm(.5) - c.Alarm2.parent=c - c.Alarm2:OnRing(function(alarm) alarm.parent.cooldown2=false end) - c.ArrowAlarm=multi:newAlarm(.1) - c.ArrowAlarm.parent=c - c.ArrowAlarm:OnRing(function(alarm) alarm.parent.arrowkeys=false end) - function c:OnFocus(func) - table.insert(self.funcF,func) - end - function c:OnEnter(func) - table.insert(self.funcE,func) - end - c:OnClicked(function(b,self) - for cc=1,#self.funcF do - self.funcF[cc](self) - end - if self.Active==false then - if self.ClearOnFocus==true then - self.text="" - self.ttext="" - end - for tb=1,#gui.TB do - if gui.TB[tb]~=nil then - gui.TB[tb].Active=false - end - end - self.Active=true - end - end) - c:OnClicked(function(b,self,x,y) - local dwidth, wrappedtext = _defaultfont:getWrap(self.text:sub(1,self.cursor[1]), self.width) - local height = _defaultfont:getHeight() - if #wrappedtext>=1 then - width= _defaultfont:getWidth(wrappedtext[#wrappedtext]) - self.cursor[2]=#wrappedtext - else - self.cursor[2]=1 - width=0 - end - yc=math.ceil(((y/self.DPI)-(self.FontHeight/2)+self.Tween-self.y)/height) - xc=math.floor(x) - end) - c:AddDrawRuleE(function(self) - if self.Active then - local dwidth, wrappedtext = _defaultfont:getWrap(self.text:sub(1,self.cursor[1]), self.width) - local height = _defaultfont:getHeight() - if #wrappedtext>=1 then - width= _defaultfont:getWidth(wrappedtext[#wrappedtext]) - self.cursor[2]=#wrappedtext - else - self.cursor[2]=1 - width=0 - end - x1=width+2+self.x+self.XTween - y1=(self.y+(height*(self.cursor[2]-1))+(self.FontHeight/2)+self.Tween)*self.DPI - x2=width+2+self.x+self.XTween - y2=(self.y+(self.FontHeight/2)+self.Tween*self.DPI)+height*self.cursor[2] - love.graphics.line(x1,y1,x2,y2) - end - end) - c:OnUpdate(function(self) - if love.keyboard.isDown("backspace") and self.Active and self.cooldown==false then - if #self.text>0 then - self.text = self.text:remove(self.cursor[1]) - self.ttext = self.ttext:remove(self.cursor[1]) - self.cursor[1]=self.cursor[1]-1 - end - self.cooldown=true - self.Alarm:Reset() - elseif love.keyboard.isDown("backspace")==false then - self.cooldown=false - end - if love.keyboard.isDown("left") and self.arrowkeys==false and self.Active then - self.arrowkeys=true - self.cursor[1]=self.cursor[1]-1 - if self.cursor[1]<0 then - self.cursor[1]=0 - end - self.ArrowAlarm:Reset() - elseif love.keyboard.isDown("right") and self.arrowkeys==false and self.Active then - self.arrowkeys=true - self.cursor[1]=self.cursor[1]+1 - if self.cursor[1]>#self.text then - self.cursor[1]=#self.text - end - self.ArrowAlarm:Reset() - end - if love.keyboard.isDown("delete") and self.Active then - if #self.text>0 then - self.text = "" - self.ttext = "" - self.cursor[1]=1 - end - elseif (love.keyboard.isDown("lshift") or love.keyboard.isDown("rshift")) and love.keyboard.isDown("return") and self.cooldown2==false then - self.text=self.text.."\n" - self.ttext=self.ttext.."\n" - self.cooldown2=true - c.Alarm2:Reset() - elseif (love.keyboard.isDown("return") or love.keyboard.isDown("enter") or love.keyboard.isDown("kpenter")) and self.Active and self.Enter and not(love.keyboard.isDown("lshift") or love.keyboard.isDown("rshift")) then - if self.LoseFocusOnEnter then - self.Active=false - else - self.Active=true - end - for cc=1,#self.funcE do - self.funcE[cc](self,self.ttext) - end - end - end) - table.insert(gui.TB,c) - return c -end ---TEXT BOX HELPER FUNCTION -function love.textinput(t) - for tb=1,#gui.TB do - if gui.TB[tb]~=nil then - if gui.TB[tb].Active then - if gui.TB[tb].hidden then - --gui.TB[tb].text=gui.TB[tb].text.."*" - gui.TB[tb].text=gui.TB[tb].text:insert(gui.TB[tb].cursor[1],"*") - else - --gui.TB[tb].text=gui.TB[tb].text..t - gui.TB[tb].text=gui.TB[tb].text:insert(gui.TB[tb].cursor[1],t) - end - gui.TB[tb].ttext=gui.TB[tb].ttext:insert(gui.TB[tb].cursor[1],t) - gui.TB[tb].cursor[1]=gui.TB[tb].cursor[1]+1 - end - end - end -end -function gui:newTextButton(t,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("TextButton",name, x, y, w, h, sx ,sy ,sw ,sh) - c.Tween=0 - c.XTween=0 - c.FontHeight=_defaultfont:getHeight() - c.Font=_defaultfont - c.FontSize=15 - c.TextFormat="center" - c.text = t - c.AutoScaleText=false - c.TextVisibility=1 -- 0=invisible,1=solid (self.TextVisibility*254+1) - c.Color = {220, 220, 220} - c.TextColor = {0, 0, 0} - c:OnEnter(function() - --love.mouse.setCursor(_GuiPro.CursorH) - end) - c:OnExit(function() - --love.mouse.setCursor(_GuiPro.CursorN) - end) - return c -end -function gui:newTextLabel(t,name, x, y, w, h, sx ,sy ,sw ,sh) - x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) - local c=self:newBase("TextLabel",name, x, y, w, h, sx ,sy ,sw ,sh) - c.Tween=0 - c.XTween=0 - c.FontHeight=_defaultfont:getHeight() - c.Font=_defaultfont - c.FontSize=15 - c.TextFormat="center" - c.text = t - c.AutoScaleText=false - c.TextVisibility=1 -- 0=invisible,1=solid (self.TextVisibility*254+1) - c.Color = {220, 220, 220} - c.TextColor = {0, 0, 0} - return c -end -function gui:AddDrawRuleB(rule) - if not(self.DrawRulesB) then self.DrawRulesB={} end - table.insert(self.DrawRulesB,rule) -end -function gui:AddDrawRuleE(rule) - if not(self.DrawRulesE) then self.DrawRulesE={} end - table.insert(self.DrawRulesE,rule) -end -function gui:draw() - if _GuiPro.rotate~=0 then - love.graphics.rotate(math.rad(_GuiPro.rotate)) - end - if self.FormFactor:lower()=="rectangle" then - self:drawR() - elseif self.FormFactor:lower()=="circle" then - self:drawC() - else - error("Unsupported FormFactor: "..self.FormFactor.."!") - end -end -function gui:drawC() - if love.mouse.isDown("l")==false and love.mouse.isDown("m")==false and love.mouse.isDown("r")==false then - _GuiPro.DragItem={} - _GuiPro.hasDrag=false - end - if self.Visible==true and self.VIS==true then - local b=true - for i,v in pairs(_GuiPro.Clips) do - if self:isDescendant(v)==true then - b=false - end - end - if b then - love.graphics.setStencilTest( ) - _GuiPro.HasStencel=false - _GuiPro.StencelHolder=nil - end - local x,y,r,s=(self.offset.pos.x or 0)+self.Parent.x,(self.offset.pos.y or 0)+self.Parent.y,self.offset.size.x or 0,self.offset.size.y or 360 - if self.CC then - x,y=x+r,y+r - end - self.x,self.y=x,y - _GuiPro.circleStencilFunction = function() - love.graphics.circle("fill",x,y,r,s) - end - if math.sqrt((love.mouse.getX()-x)^2+(love.mouse.getY()-y)^2)<=r and self:eventable() and self:Clickable() and self.Active==true then - self.hovering=true - if love.mouse.isDown("l") and _GuiPro.hasDrag==false then - if string.find(self.Type, "Button") then - love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.lclicked=true - elseif love.mouse.isDown("r") and _GuiPro.hasDrag==false then - if string.find(self.Type, "Button") then - love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.rclicked=true - elseif love.mouse.isDown("m") and _GuiPro.hasDrag==false then - if string.find(self.Type, "Button") then - love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.mclicked=true - else - if string.find(self.Type, "Button") and _GuiPro.hasDrag==false then - love.graphics.setColor(self.Color[1]-5, self.Color[2]-5, self.Color[3]-5,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.rclicked=false - self.lclicked=false - self.mclicked=false - end - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - self.hovering=false - self.rclicked=false - self.lclicked=false - self.mclicked=false - end - if self.ClipDescendants==true then - _GuiPro.Clips[tostring(self)]=self - _GuiPro.HasStencel=true - _GuiPro.StencelHolder=self - love.graphics.stencil(_GuiPro.circleStencilFunction) - love.graphics.setStencilTest("notequal",0) - end - love.graphics.circle("fill",x,y,r,s) - love.graphics.setColor(self.BorderColor[1], self.BorderColor[2], self.BorderColor[3],self.Visibility*254) - for b=0,self.BorderSize-1 do - love.graphics.circle("line",x,y,r+b,s) - end - if string.find(self.Type, "Text") then - if self.text~=nil then - if self.AutoScaleText then - self.FontSize=math.floor(self.height/1.45833) - end - love.graphics.setColor(self.TextColor[1],self.TextColor[2],self.TextColor[3],self.TextVisibility*254) - love.graphics.setFont(self.Font) - love.graphics.printf(self.text, x-(r/2)+(self.XTween), y-(r/2)+self.Tween, r, self.TextFormat) - end - end - end -end -function gui:drawR() - if love.mouse.isDown("l")==false and love.mouse.isDown("m")==false and love.mouse.isDown("r")==false then - _GuiPro.DragItem={} - _GuiPro.hasDrag=false - end - if self.Visible==true and self.VIS==true then - local b=true - for i,v in pairs(_GuiPro.Clips) do - if self:isDescendant(v)==true then - b=false - end - end - if b==true then - love.graphics.setStencilTest() - love.graphics.setScissor() - end - self.x=(self.Parent.width*self.scale.pos.x)+self.offset.pos.x+self.Parent.x - self.y=(self.Parent.height*self.scale.pos.y)+self.offset.pos.y+self.Parent.y - self.width=(self.Parent.width*self.scale.size.x)+self.offset.size.x - self.height=(self.Parent.height*self.scale.size.y)+self.offset.size.y - if self.DrawRulesB then - for dr=1,#self.DrawRulesB do - self.DrawRulesB[dr](self) - end - end - if (love.mouse.getX() > self.x and love.mouse.getX() < self.x+self.width and love.mouse.getY() > self.y and love.mouse.getY() < self.y+self.height and self:Clickable() and self:eventable()) or self:touchable("r") and self.Active==true then - self.hovering=true - if love.mouse.isDown("l") or self:touchable("r") and _GuiPro.hasDrag==false then - if string.find(self.Type, "Button") then - love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.lclicked=true - elseif love.mouse.isDown("r") or self:touchable("r") and _GuiPro.hasDrag==false then - if string.find(self.Type, "Button") then - love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.rclicked=true - elseif love.mouse.isDown("m") or self:touchable("r") and _GuiPro.hasDrag==false then - if string.find(self.Type, "Button") then - love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.mclicked=true - else - if string.find(self.Type, "Button") or self:touchable("r") and _GuiPro.hasDrag==false then - love.graphics.setColor(self.Color[1]-5, self.Color[2]-5, self.Color[3]-5,self.Visibility*254) - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - end - self.rclicked=false - self.lclicked=false - self.mclicked=false - end - else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) - self.hovering=false - self.rclicked=false - self.lclicked=false - self.mclicked=false - end - if self.ClipDescendants==true then - _GuiPro.Clips[tostring(self)]=self - love.graphics.setScissor(self.x, self.y, self.width, self.height) - end - if self:hasRoundness() then - love.graphics.stencil(self.stfunc, "replace", 1) - love.graphics.setStencilTest("greater", 0) - end - love.graphics.rectangle("fill", self.x, self.y, self.width, self.height,(self.rx or 1)*self.DPI,(self.ry or 1)*self.DPI,(self.segments or 1)*self.DPI) - if string.find(self.Type, "Image") then - self:ImageRule() - end - if self.Type=="Video" then - self:VideoRule() - end - if self:hasRoundness() then - love.graphics.setStencilTest() - end - love.graphics.setColor(self.BorderColor[1], self.BorderColor[2], self.BorderColor[3],self.Visibility*254) - for b=0,self.BorderSize-1 do - love.graphics.rectangle("line", self.x-(b/2), self.y-(b/2), self.width+b, self.height+b,(self.rx or 1)*self.DPI,(self.ry or 1)*self.DPI,(self.segments or 1)*self.DPI) - end - if string.find(self.Type, "Text") then - if self.text~=nil then - if self.AutoScaleText then - self.FontSize=math.floor(self.height/1.45833) - end - love.graphics.setColor(self.TextColor[1],self.TextColor[2],self.TextColor[3],self.TextVisibility*254) - if self.Font==_defaultfont then - love.graphics.setFont(self.Font) - love.graphics.printf(self.text, self.x+2+(self.XTween*self.DPI)+((self.marginL or 0)*self.DPI or self.XTween*self.DPI), self.y+(self.FontHeight/2)+self.Tween*self.DPI, self.width+(0 or (self.marginR or 0)*self.DPI), self.TextFormat) - else - if type(self.Font)=="string" then - self.Font=love.graphics.newFont(self.Font,self.FontSize) - self.FontHeight=self.Font:getHeight() - else - love.graphics.setFont(self.Font) - end - if type(self.FontSize)=="string" then - self.FontSize=tonumber(self.FontSize) - love.graphics.setNewFont(self.FontSize) - end - love.graphics.printf(self.text, self.x+2+((self.marginL or 0)*self.DPI or self.XTween*self.DPI), self.y+math.floor((self.FontHeight-self.FontSize)/2)+self.Tween*self.DPI, self.width+(0 or (self.marginR or 0)*self.DPI), self.TextFormat) - end - end - end - if self.DrawRulesE then - for dr=1,#self.DrawRulesE do - self.DrawRulesE[dr](self) - end - end - end -end - -gui:respectHierarchy() -_GuiPro.width,_GuiPro.height=love.graphics.getDimensions() -multi:newLoop():OnLoop(function() _GuiPro.width,_GuiPro.height=love.graphics.getDimensions() _GuiPro:update() end) -multi:onDraw(function() _GuiPro:draw() end) -gui.ff=gui:newFrame("",0,0,0,0,0,0,1,1) -gui.ff.Color={255,255,255} -gui.ff:OnUpdate(function(self) - self:BottomStack() -end) - diff --git a/mulit/examples/love2d Threading Example/core/Library.lua b/mulit/examples/love2d Threading Example/core/Library.lua deleted file mode 100644 index 8260136..0000000 --- a/mulit/examples/love2d Threading Example/core/Library.lua +++ /dev/null @@ -1,319 +0,0 @@ -if table.unpack then - unpack=table.unpack -end -function table.val_to_str ( v ) - if "string" == type( v ) then - v = string.gsub( v, "\n", "\\n" ) - if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then - return "'" .. v .. "'" - end - return '"' .. string.gsub(v,'"', '\\"' ) .. '"' - else - return "table" == type( v ) and table.tostring( v ) or - tostring( v ) - end -end - -function table.key_to_str ( k ) - if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then - return k - else - return "[" .. table.val_to_str( k ) .. "]" - end -end - -function table.tostring( tbl ) - local result, done = {}, {} - for k, v in ipairs( tbl ) do - table.insert( result, table.val_to_str( v ) ) - done[ k ] = true - end - for k, v in pairs( tbl ) do - if not done[ k ] then - table.insert( result, - table.key_to_str( k ) .. "=" .. table.val_to_str( v ) ) - end - end - return "{" .. table.concat( result, "," ) .. "}" -end -function table.merge(t1, t2) - t1,t2= t1 or {},t2 or {} - for k,v in pairs(t2) do - if type(v) == "table" then - if type(t1[k] or false) == "table" then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -Library={} -function Library.optimize(func) - local test=Library.convert(func) - rawset(test,"link",{}) - rawset(test,"last","") - rawset(test,"org",func) - test:inject(function(...) - rawset(test,"last",table.tostring({...})) - if test.link[test.last]~=nil then - return Library.forceReturn(unpack(test.link[test.last])) - end - return {...} - end,1) - test:inject(function(...) - test.link[test.last]={test.org(...)} - return test.org(...) - end) - return test -end -function Library.forceReturn(...) - return {[0]="\1\7\6\3\2\99\125",...} -end -function Library.inject(lib,dat,arg) - if type(lib)=="table" then - if type(dat)=="table" then - table.merge(lib,dat) - elseif type(dat)=="string" then - if lib.Version and dat:match("(%d-)%.(%d-)%.(%d-)") then - lib.Version={dat:match("(%d+)%.(%d+)%.(%d+)")} - elseif dat=="meta" and type(arg)=="table" then - local _mt=getmetatable(lib) or {} - local mt={} - table.merge(mt,arg) - table.merge(_mt,mt) - setmetatable(lib,_mt) - elseif dat=="compat" then - lib["getVersion"]=function(self) return self.Version[1].."."..self.Version[2].."."..self.Version[3] end - if not lib.Version then - lib.Version={1,0,0} - end - elseif dat=="inhert" then - if not(lib["!%"..arg.."%!"]) then print("Wrong Password!!") return end - lib["!%"..arg.."%!"].__index=lib["!!%"..arg.."%!!"] - end - elseif type(dat)=="function" then - for i,v in pairs(lib) do - dat(lib,i,v) - end - end - elseif type(lib)=="function" or type(lib)=="userdata" then - if lib==unpack then - print("function unpack cannot yet be injected!") - return unpack - elseif lib==pairs then - print("function pairs cannot yet be injected!") - return lib - elseif lib==ipairs then - print("function ipairs cannot yet be injected!") - return lib - elseif lib==type then - print("function type cannot yet be injected!") - return lib - end - temp={} - local mt={ - __call=function(t,...) - local consume,MainRet,init={},{},{...} - local tt={} - for i=1,#t.__Link do - tt={} - if t.__Link[i]==t.__Main then - if #consume~=0 then - MainRet={t.__Link[i](unpack(consume))} - else - MainRet={t.__Link[i](unpack(init))} - end - else - if i==1 then - consume=(t.__Link[i](unpack(init))) - else - if type(MainRet)=="table" then - table.merge(tt,MainRet) - end - if type(consume)=="table" then - table.merge(tt,consume) - end - consume={t.__Link[i](unpack(tt))} - end - if i==#t.__Link then - return unpack(consume) - end - if consume then if consume[0]=="\1\7\6\3\2\99\125" then consume[0]=nil return unpack(consume) end end - end - end - if type(MainRet)=="table" then - table.merge(tt,MainRet) - end - if type(consume)=="table" then - table.merge(tt,consume) - end - return unpack(tt) - end, - } - temp.__Link={lib} - temp.__Main=lib - temp.__self=temp - function temp:inject(func,i) - if i then - table.insert(self.__Link,i,func) - else - table.insert(self.__Link,func) - end - end - function temp:consume(func) - for i=1,#self.__Link do - if self.__Link[i]==self.__Main then - self.__Link[i]=func - self.__self.__Main=func - return true - end - end - return false - end - setmetatable(temp,mt) - Library.protect(temp,"lolz") - return temp - else - return "arg1 must be a table or a function" - end -end -function Library.parse(lib) - for i,v in pairs(lib) do - print(i,v) - end -end -function Library.protect(lib,pass) - pass=pass or "*" - local mt={} - local test={ - __index = lib, - __newindex = function(tab, key, value) - local t,b=key:find(tab["!%"..pass.."%!"].__pass,1,true) - if t then - local _k=key:sub(b+1) - rawset(tab,_k,value) - else - error("Cannot alter a protected library!") - end - end, - __metatable = false, - __pass=pass or "*" - } - local _mt=getmetatable(lib) or {} - table.merge(mt,_mt) - table.merge(mt,test) - lib["!%"..pass.."%!"]=test - lib["!!%"..pass.."%!!"]=lib - local temp=setmetatable({},mt) - for i,v in pairs(_G) do - if v==lib then - _G[i]=temp - Library(function(link) - link[i]=v - end) - end - end -end -function Library.unprotect(lib,pass) - if not(lib["!%"..pass.."%!"]) then print("Wrong Password or Library is not Protected!") return end - if lib["!%"..pass.."%!"].__pass==pass then - lib["!%"..pass.."%!"].__newindex=lib["!!%"..pass.."%!!"] - lib["!%"..pass.."%!"].__index=nil - lib["!%"..pass.."%!"].__newindex=nil - lib["!%"..pass.."%!"].__metatable = true - setmetatable(lib["!!%"..pass.."%!!"],lib["!%"..pass.."%!"]) - for i,v in pairs(_G) do - if v==lib then - _G[i]=lib["!!%"..pass.."%!!"] - end - end - lib["!!%"..pass.."%!!"]["!%"..pass.."%!"]=nil - lib["!!%"..pass.."%!!"]["!!%"..pass.."%!!"]=nil - else - print("Wrong Password!!!") - end -end -function Library.addPoll(lib,polldata,ref) - lib.__polldata={} - Library.inject(lib.__polldata,polldata) - if type(ref)=="table" then - Library.inject(ref,"meta",{__newindex=function(t,k,v) - t[k].__polldata=polldata - end}) - end -end -function Library.newPollData(t) - local temp={} - temp.__onPolled=function() end - temp.__pollData=false - temp.__advDisc="" - temp.__pollcalls=-1 -- infinte - for i,v in pairs(t) do - if type(v)=="string" then - temp.__advDisc=v - elseif type(v)=="number" then - temp.__pollcalls=v - elseif type(v)=="table" then - temp[v[1]]=v[2] - elseif type(v)=="function" then - temp.__onPolled=v - elseif type(v)=="boolean" then - temp.__pollData=v - else - temp.__userdata=v - end - end - return temp -end -function Library.convert(...) - local temp,rets={...},{} - for i=1,#temp do - if type(temp[i])=="function" then - table.insert(rets,Library.inject(temp[i])) - else - error("Takes only functions and returns in order from functions given. arg # "..i.." is not a function!!! It is a "..type(temp[i])) - end - end - return unpack(rets) -end -function Library.convertIn(...) - local temp,list={...},{} - for i=1,#temp do - if type(temp[i])=="table" then - for k,v in pairs(temp[i]) do - if type(v)=="function" then - temp[i][k]=Library.inject(temp[i][k]) - end - end - else - error("Takes only tables! Arg "..i.." isn't it is a "..type(temp[i])) - end - end -end -function Library.newInjectedFunction() - return Library.convert(function(...) return unpack{...} end) -end -function Library.capulate(lib) - Library.inject(lib,"meta",{ - __index=function(t,k,v) - for i,_v in pairs(t) do - if k:lower()==i:lower() then - return t[i] - end - end - end, - __newindex=function(t,k,v) - rawset(t,k:lower(),v) - end - }) -end -local link={MainLibrary=Library} -Library.inject(Library,"meta",{ - __Link=link, - __call=function(self,func) func(link) end, -}) ---Library.protect(Library,"N@#P!KLkk1(93320") diff --git a/mulit/examples/love2d Threading Example/core/README.txt b/mulit/examples/love2d Threading Example/core/README.txt deleted file mode 100644 index 02b5fb6..0000000 --- a/mulit/examples/love2d Threading Example/core/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -These libraries Namely the MultiManager, bin, and the Library, libraries will be documented because i plan on sharing them -everything else will mostlikely not be documented \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/core/T1.lua b/mulit/examples/love2d Threading Example/core/T1.lua deleted file mode 100644 index f861efa..0000000 --- a/mulit/examples/love2d Threading Example/core/T1.lua +++ /dev/null @@ -1,598 +0,0 @@ -require("love.timer") -require("love.system") -require("love.sound") -require("love.physics") -require("love.mouse") -require("love.math") -require("love.keyboard") -require("love.joystick") -require("love.image") -require("love.font") -require("love.filesystem") -require("love.event") -require("love.audio") -require("love.graphics") -require("love.window") -_defaultfont = love.graphics.getFont() -gui = {} -function gui.getTile(i,x,y,w,h)-- returns imagedata - if type(i)=="userdata" then - -- do nothing - else - error("getTile invalid args!!! Usage: ImageElement:getTile(x,y,w,h) or gui:getTile(imagedata,x,y,w,h)") - end - local iw,ih=i:getDimensions() - local id,_id=i:getData(),love.image.newImageData(w,h) - for _x=x,w+x-1 do - for _y=y,h+y-1 do - _id:setPixel(_x-x,_y-y,id:getPixel(_x,_y)) - end - end - return love.graphics.newImage(_id) -end -multi = {} -multi.Version="4.0.0" -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.Children={} -multi.Paused={} -multi.MasterId=0 -multi.Active=true -multi.Id=-1 -multi.Type="MainInt" -multi.Rest=0 --- System -os.sleep=love.timer.sleep -function multi:newBase(ins) - if not(self.Type=="MainInt" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.Act=function() end - c.Parent=self - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - self.MasterId=self.MasterId+1 - return c -end -function multi:reboot(r) - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.MasterId=0 - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=="table" then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:Do_Order() - for _D=#self.Mainloop,1,-1 do - if self.Mainloop[_D]~=nil then - self.Mainloop[_D].Id=_D - self.Mainloop[_D]:Act() - end - if self.Mainloop[_D].rem then - table.remove(self.Mainloop,_D) - end - end - if self.Rest>0 then - os.sleep(self.Rest) - end -end -function multi:benchMark(sec) - local temp=self:newLoop(function(t,self) - if os.clock()-self.init>self.sec then - print(self.c.." steps in "..self.sec.." second(s)") - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=os.clock() - temp.c=0 - return temp -end -function multi:newInterface() - if not(self.Type=="MainInt") then error("Can only create an interface on the multi obj") return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type="int" - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.MasterId=0 - c.Active=true - c.Id=-1 - c.Rest=0 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Stop() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - return c -end ---Helpers -function multi:FreeMainEvent() - self.func={} -end -function multi:isPaused() - return not(self.Active) -end -function multi:Pause(n) - if self.Type=="int" or self.Type=="MainInt" then - self.Active=false - if not(n) then - local c=self:getChildren() - for i=1,#c do - c[i]:Pause() - end - else - self:hold(n) - end - else - if not(n) then - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.Id=#self.Parent.Paused - end - else - self:hold(n) - end - end -end -function multi:Resume() - if self.Type=="int" or self.Type=="MainInt" then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - self.Active=true - for i=1,#self.Parent.Paused do - if self.Parent.Paused[i]==self then - table.remove(self.Parent.Paused,i) - return - end - end - table.insert(self.Parent.Mainloop,self) - end - end -end -function multi:Destroy() - if self.Type=="int" or self.Type=="MainInt" then - local c=self:getChildren() - for i=1,#c do - c[i]:Destroy() - end - else - self.rem=true - end -end -function multi:hold(task) - self:Pause() - if type(task)=="number" then - local alarm=self:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent.lManager() - else - self.Parent.Do_Order() - end - end - alarm:Destroy() - self:Resume() - elseif type(task)=="function" then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt:Stop() end) - while env.Active do - if love then - self.Parent.lManager() - else - self.Parent.Do_Order() - end - end - env:Destroy() - self:Resume() - else - print("Error Data Type!!!") - end -end -function multi:oneTime(func,...) - if not(self.Type=="MainInt" or self.Type=="int") then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end ---Constructors -function multi:newEvent(task) - local c=self:newBase() - c.Type="Event" - c.Task=task or function() end - function c:Act() - if self.Task(self) and self.Active==true then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - return c -end -function multi:newAlarm(set) - local c=self:newBase() - c.Type="Alarm" - c.timer=os.clock() - c.set=set or 0 - function c:Act() - if self.Active==true then - if os.clock()-self.timer>=self.set then - self:Pause() - for i=1,#self.func do - self.func[i](self) - end - end - end - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - function c:OnRing(func) - table.insert(self.func,func) - end - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newLoop(func) - local c=self:newBase() - c.Type="Loop" - if func then - c.func={func} - end - function c:Act() - if self.Active==true then - for i=1,#self.func do - self.func[i](os.clock()-self.Parent.Start,self) - end - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - return c -end -function multi:newStep(start,reset,count,skip) - local c=self:newBase() - think=1 - c.Type="Step" - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.Active==true then - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - c:OnStep(function(p,s) - if s.count>0 and s.endAt==p then - for fe=1,#s.funcE do - s.funcE[fe](s) - end - s.pos=s.start-1 - elseif s.count<0 and s.endAt==p then - for fe=1,#s.funcE do - s.funcE[fe](s) - end - s.pos=s.start-1 - end - end) - return c -end -function multi:newTStep(start,reset,count,set) - local c=self:newBase() - think=1 - c.Type="TStep" - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=os.clock() - c.set=set or 1 - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=os.clock() - self:Resume() - end - function c:Act() - if self.Active then - if os.clock()-self.timer>=self.set then - self:Reset() - for i=1,#self.func do - self.func[i](self.pos,self) - end - if self.endAt==self.pos then - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start-1 - end - self.pos=self.pos+self.count - end - end - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - function c:OnStep(func) - table.insert(self.func,func) - end - return c -end -function multi:newTrigger(func) - local c=self:newBase() - c.Type="Trigger" - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - return c -end ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - self.Start=os.clock() - while self.Active do - self:Do_Order() - end -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - print("once!") - if dt then - self.pump=true - end - self.pumpvar=dt - self.Start=os.clock() -end -function multi:uManager(dt) - self:oneTime(self._tFunc,self,dt) - self:Do_Order() -end -multi.drawF={} -function multi:dManager() - for ii=1,#multi.drawF do - multi.drawF[ii]() - end -end -function multi:onDraw(func) - table.insert(self.drawF,func) -end -function multi:lManager() - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return nil - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - multi:uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - multi.dManager() - love.graphics.setColor(255,255,255,255) - if multi.draw then multi.draw() end - love.graphics.present() - end -end -Thread={} -Thread.Name="Thread 1" -Thread.ChannelThread = love.thread.getChannel("Easy1") -Thread.ChannelMain = love.thread.getChannel("EasyMain") -Thread.Global = {} -function Thread:packTable(G) - function escapeStr(str) - local temp="" - for i=1,#str do - temp=temp.."\\"..string.byte(string.sub(str,i,i)) - end - return temp - end - function ToStr(t) - local dat="{" - for i,v in pairs(t) do - if type(i)=="number" then - i="["..i.."]=" - else - i=i.."=" - end - if type(v)=="string" then - dat=dat..i.."\""..v.."\"," - elseif type(v)=="number" then - dat=dat..i..v.."," - elseif type(v)=="boolean" then - dat=dat..i..tostring(v).."," - elseif type(v)=="table" and not(G==v) then - dat=dat..i..ToStr(v).."," - --elseif type(v)=="table" and G==v then - -- dat=dat..i.."assert(loadstring(\"return self\"))," - elseif type(v)=="function" then - dat=dat..i.."assert(loadstring(\""..escapeStr(string.dump(v)).."\"))," - end - end - return string.sub(dat,1,-2).."}" - end - return "return "..ToStr(G) -end -function Thread:Send(name,var) - arg3="1" - if type(var)=="table" then - var=Thread:packTable(var) - arg3="table" - end - self.ChannelMain:push({name,var,arg3}) -end -function Thread:UnPackChannel() - local c=self.ChannelThread:getCount() - for i=1,c do - local temp=self.ChannelThread:pop() - if temp[1] and temp[2] then - if temp[1]=="func" and type(temp[2])=="string" then - loadstring(temp[2])(temp[3]) - elseif temp[1]=="table" then - _G[temp[3]]=loadstring(temp[2])() - else - _G[temp[1]]=temp[2] - end - end - end - if #multi:getChildren()<2 then - os.sleep(.05) - end -end -function Thread:boost(func,name) - self:Send(name,string.dump(func)) -end -function Thread.mainloop() - Thread:UnPackChannel() -end -Thread.MainThread=false -multi:newLoop():OnLoop(Thread.mainloop) -multi:mainloop() diff --git a/mulit/examples/love2d Threading Example/core/T2.lua b/mulit/examples/love2d Threading Example/core/T2.lua deleted file mode 100644 index 44e2fbf..0000000 --- a/mulit/examples/love2d Threading Example/core/T2.lua +++ /dev/null @@ -1,598 +0,0 @@ -require("love.timer") -require("love.system") -require("love.sound") -require("love.physics") -require("love.mouse") -require("love.math") -require("love.keyboard") -require("love.joystick") -require("love.image") -require("love.font") -require("love.filesystem") -require("love.event") -require("love.audio") -require("love.graphics") -require("love.window") -_defaultfont = love.graphics.getFont() -gui = {} -function gui.getTile(i,x,y,w,h)-- returns imagedata - if type(i)=="userdata" then - -- do nothing - else - error("getTile invalid args!!! Usage: ImageElement:getTile(x,y,w,h) or gui:getTile(imagedata,x,y,w,h)") - end - local iw,ih=i:getDimensions() - local id,_id=i:getData(),love.image.newImageData(w,h) - for _x=x,w+x-1 do - for _y=y,h+y-1 do - _id:setPixel(_x-x,_y-y,id:getPixel(_x,_y)) - end - end - return love.graphics.newImage(_id) -end -multi = {} -multi.Version="4.0.0" -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.Children={} -multi.Paused={} -multi.MasterId=0 -multi.Active=true -multi.Id=-1 -multi.Type="MainInt" -multi.Rest=0 --- System -os.sleep=love.timer.sleep -function multi:newBase(ins) - if not(self.Type=="MainInt" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.Act=function() end - c.Parent=self - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - self.MasterId=self.MasterId+1 - return c -end -function multi:reboot(r) - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.MasterId=0 - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=="table" then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:Do_Order() - for _D=#self.Mainloop,1,-1 do - if self.Mainloop[_D]~=nil then - self.Mainloop[_D].Id=_D - self.Mainloop[_D]:Act() - end - if self.Mainloop[_D].rem then - table.remove(self.Mainloop,_D) - end - end - if self.Rest>0 then - os.sleep(self.Rest) - end -end -function multi:benchMark(sec) - local temp=self:newLoop(function(t,self) - if os.clock()-self.init>self.sec then - print(self.c.." steps in "..self.sec.." second(s)") - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=os.clock() - temp.c=0 - return temp -end -function multi:newInterface() - if not(self.Type=="MainInt") then error("Can only create an interface on the multi obj") return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type="int" - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.MasterId=0 - c.Active=true - c.Id=-1 - c.Rest=0 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Stop() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - return c -end ---Helpers -function multi:FreeMainEvent() - self.func={} -end -function multi:isPaused() - return not(self.Active) -end -function multi:Pause(n) - if self.Type=="int" or self.Type=="MainInt" then - self.Active=false - if not(n) then - local c=self:getChildren() - for i=1,#c do - c[i]:Pause() - end - else - self:hold(n) - end - else - if not(n) then - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.Id=#self.Parent.Paused - end - else - self:hold(n) - end - end -end -function multi:Resume() - if self.Type=="int" or self.Type=="MainInt" then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - self.Active=true - for i=1,#self.Parent.Paused do - if self.Parent.Paused[i]==self then - table.remove(self.Parent.Paused,i) - return - end - end - table.insert(self.Parent.Mainloop,self) - end - end -end -function multi:Destroy() - if self.Type=="int" or self.Type=="MainInt" then - local c=self:getChildren() - for i=1,#c do - c[i]:Destroy() - end - else - self.rem=true - end -end -function multi:hold(task) - self:Pause() - if type(task)=="number" then - local alarm=self:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent.lManager() - else - self.Parent.Do_Order() - end - end - alarm:Destroy() - self:Resume() - elseif type(task)=="function" then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt:Stop() end) - while env.Active do - if love then - self.Parent.lManager() - else - self.Parent.Do_Order() - end - end - env:Destroy() - self:Resume() - else - print("Error Data Type!!!") - end -end -function multi:oneTime(func,...) - if not(self.Type=="MainInt" or self.Type=="int") then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end ---Constructors -function multi:newEvent(task) - local c=self:newBase() - c.Type="Event" - c.Task=task or function() end - function c:Act() - if self.Task(self) and self.Active==true then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - return c -end -function multi:newAlarm(set) - local c=self:newBase() - c.Type="Alarm" - c.timer=os.clock() - c.set=set or 0 - function c:Act() - if self.Active==true then - if os.clock()-self.timer>=self.set then - self:Pause() - for i=1,#self.func do - self.func[i](self) - end - end - end - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - function c:OnRing(func) - table.insert(self.func,func) - end - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newLoop(func) - local c=self:newBase() - c.Type="Loop" - if func then - c.func={func} - end - function c:Act() - if self.Active==true then - for i=1,#self.func do - self.func[i](os.clock()-self.Parent.Start,self) - end - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - return c -end -function multi:newStep(start,reset,count,skip) - local c=self:newBase() - think=1 - c.Type="Step" - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.Active==true then - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - c:OnStep(function(p,s) - if s.count>0 and s.endAt==p then - for fe=1,#s.funcE do - s.funcE[fe](s) - end - s.pos=s.start-1 - elseif s.count<0 and s.endAt==p then - for fe=1,#s.funcE do - s.funcE[fe](s) - end - s.pos=s.start-1 - end - end) - return c -end -function multi:newTStep(start,reset,count,set) - local c=self:newBase() - think=1 - c.Type="TStep" - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=os.clock() - c.set=set or 1 - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=os.clock() - self:Resume() - end - function c:Act() - if self.Active then - if os.clock()-self.timer>=self.set then - self:Reset() - for i=1,#self.func do - self.func[i](self.pos,self) - end - if self.endAt==self.pos then - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start-1 - end - self.pos=self.pos+self.count - end - end - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - function c:OnStep(func) - table.insert(self.func,func) - end - return c -end -function multi:newTrigger(func) - local c=self:newBase() - c.Type="Trigger" - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - return c -end ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - self.Start=os.clock() - while self.Active do - self:Do_Order() - end -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - print("once!") - if dt then - self.pump=true - end - self.pumpvar=dt - self.Start=os.clock() -end -function multi:uManager(dt) - self:oneTime(self._tFunc,self,dt) - self:Do_Order() -end -multi.drawF={} -function multi:dManager() - for ii=1,#multi.drawF do - multi.drawF[ii]() - end -end -function multi:onDraw(func) - table.insert(self.drawF,func) -end -function multi:lManager() - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return nil - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - multi:uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - multi.dManager() - love.graphics.setColor(255,255,255,255) - if multi.draw then multi.draw() end - love.graphics.present() - end -end -Thread={} -Thread.Name="Thread 2" -Thread.ChannelThread = love.thread.getChannel("Easy2") -Thread.ChannelMain = love.thread.getChannel("EasyMain") -Thread.Global = {} -function Thread:packTable(G) - function escapeStr(str) - local temp="" - for i=1,#str do - temp=temp.."\\"..string.byte(string.sub(str,i,i)) - end - return temp - end - function ToStr(t) - local dat="{" - for i,v in pairs(t) do - if type(i)=="number" then - i="["..i.."]=" - else - i=i.."=" - end - if type(v)=="string" then - dat=dat..i.."\""..v.."\"," - elseif type(v)=="number" then - dat=dat..i..v.."," - elseif type(v)=="boolean" then - dat=dat..i..tostring(v).."," - elseif type(v)=="table" and not(G==v) then - dat=dat..i..ToStr(v).."," - --elseif type(v)=="table" and G==v then - -- dat=dat..i.."assert(loadstring(\"return self\"))," - elseif type(v)=="function" then - dat=dat..i.."assert(loadstring(\""..escapeStr(string.dump(v)).."\"))," - end - end - return string.sub(dat,1,-2).."}" - end - return "return "..ToStr(G) -end -function Thread:Send(name,var) - arg3="2" - if type(var)=="table" then - var=Thread:packTable(var) - arg3="table" - end - self.ChannelMain:push({name,var,arg3}) -end -function Thread:UnPackChannel() - local c=self.ChannelThread:getCount() - for i=1,c do - local temp=self.ChannelThread:pop() - if temp[1] and temp[2] then - if temp[1]=="func" and type(temp[2])=="string" then - loadstring(temp[2])(temp[3]) - elseif temp[1]=="table" then - _G[temp[3]]=loadstring(temp[2])() - else - _G[temp[1]]=temp[2] - end - end - end - if #multi:getChildren()<2 then - os.sleep(.05) - end -end -function Thread:boost(func,name) - self:Send(name,string.dump(func)) -end -function Thread.mainloop() - Thread:UnPackChannel() -end -Thread.MainThread=false -multi:newLoop():OnLoop(Thread.mainloop) -multi:mainloop() diff --git a/mulit/examples/love2d Threading Example/core/T3.lua b/mulit/examples/love2d Threading Example/core/T3.lua deleted file mode 100644 index 171eff0..0000000 --- a/mulit/examples/love2d Threading Example/core/T3.lua +++ /dev/null @@ -1,596 +0,0 @@ -require("love.timer") -require("love.system") -require("love.sound") -require("love.physics") -require("love.mouse") -require("love.math") -require("love.keyboard") -require("love.joystick") -require("love.image") -require("love.font") -require("love.filesystem") -require("love.event") -require("love.audio") -require("love.graphics") -require("love.window") -_defaultfont = love.graphics.getFont() -gui = {} -function gui.getTile(i,x,y,w,h)-- returns imagedata - if type(i)=="userdata" then - -- do nothing - else - error("getTile invalid args!!! Usage: ImageElement:getTile(x,y,w,h) or gui:getTile(imagedata,x,y,w,h)") - end - local iw,ih=i:getDimensions() - local id,_id=i:getData(),love.image.newImageData(w,h) - for _x=x,w+x-1 do - for _y=y,h+y-1 do - _id:setPixel(_x-x,_y-y,id:getPixel(_x,_y)) - end - end - return love.graphics.newImage(_id) -end -multi = {} -multi.Version="4.0.0" -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.Children={} -multi.Paused={} -multi.MasterId=0 -multi.Active=true -multi.Id=-1 -multi.Type="MainInt" -multi.Rest=0 --- System -os.sleep=love.timer.sleep -function multi:newBase(ins) - if not(self.Type=="MainInt" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.Act=function() end - c.Parent=self - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - self.MasterId=self.MasterId+1 - return c -end -function multi:reboot(r) - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.MasterId=0 - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=="table" then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:Do_Order() - for _D=#self.Mainloop,1,-1 do - if self.Mainloop[_D]~=nil then - self.Mainloop[_D].Id=_D - self.Mainloop[_D]:Act() - end - if self.Mainloop[_D].rem then - table.remove(self.Mainloop,_D) - end - end - if self.Rest>0 then - os.sleep(self.Rest) - end -end -function multi:benchMark(sec) - local temp=self:newLoop(function(t,self) - if os.clock()-self.init>self.sec then - print(self.c.." steps in "..self.sec.." second(s)") - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=os.clock() - temp.c=0 - return temp -end -function multi:newInterface() - if not(self.Type=="MainInt") then error("Can only create an interface on the multi obj") return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type="int" - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.MasterId=0 - c.Active=true - c.Id=-1 - c.Rest=0 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Stop() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - return c -end ---Helpers -function multi:FreeMainEvent() - self.func={} -end -function multi:isPaused() - return not(self.Active) -end -function multi:Pause(n) - if self.Type=="int" or self.Type=="MainInt" then - self.Active=false - if not(n) then - local c=self:getChildren() - for i=1,#c do - c[i]:Pause() - end - else - self:hold(n) - end - else - if not(n) then - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.Id=#self.Parent.Paused - end - else - self:hold(n) - end - end -end -function multi:Resume() - if self.Type=="int" or self.Type=="MainInt" then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - self.Active=true - for i=1,#self.Parent.Paused do - if self.Parent.Paused[i]==self then - table.remove(self.Parent.Paused,i) - return - end - end - table.insert(self.Parent.Mainloop,self) - end - end -end -function multi:Destroy() - if self.Type=="int" or self.Type=="MainInt" then - local c=self:getChildren() - for i=1,#c do - c[i]:Destroy() - end - else - self.rem=true - end -end -function multi:hold(task) - self:Pause() - if type(task)=="number" then - local alarm=self:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent.lManager() - else - self.Parent.Do_Order() - end - end - alarm:Destroy() - self:Resume() - elseif type(task)=="function" then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt:Stop() end) - while env.Active do - if love then - self.Parent.lManager() - else - self.Parent.Do_Order() - end - end - env:Destroy() - self:Resume() - else - print("Error Data Type!!!") - end -end -function multi:oneTime(func,...) - if not(self.Type=="MainInt" or self.Type=="int") then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end ---Constructors -function multi:newEvent(task) - local c=self:newBase() - c.Type="Event" - c.Task=task or function() end - function c:Act() - if self.Task(self) and self.Active==true then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - return c -end -function multi:newAlarm(set) - local c=self:newBase() - c.Type="Alarm" - c.timer=os.clock() - c.set=set or 0 - function c:Act() - if self.Active==true then - if os.clock()-self.timer>=self.set then - self:Pause() - for i=1,#self.func do - self.func[i](self) - end - end - end - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - function c:OnRing(func) - table.insert(self.func,func) - end - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newLoop(func) - local c=self:newBase() - c.Type="Loop" - if func then - c.func={func} - end - function c:Act() - if self.Active==true then - for i=1,#self.func do - self.func[i](os.clock()-self.Parent.Start,self) - end - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - return c -end -function multi:newStep(start,reset,count,skip) - local c=self:newBase() - think=1 - c.Type="Step" - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.Active==true then - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - c:OnStep(function(p,s) - if s.count>0 and s.endAt==p then - for fe=1,#s.funcE do - s.funcE[fe](s) - end - s.pos=s.start-1 - elseif s.count<0 and s.endAt==p then - for fe=1,#s.funcE do - s.funcE[fe](s) - end - s.pos=s.start-1 - end - end) - return c -end -function multi:newTStep(start,reset,count,set) - local c=self:newBase() - think=1 - c.Type="TStep" - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=os.clock() - c.set=set or 1 - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=os.clock() - self:Resume() - end - function c:Act() - if self.Active then - if os.clock()-self.timer>=self.set then - self:Reset() - for i=1,#self.func do - self.func[i](self.pos,self) - end - if self.endAt==self.pos then - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start-1 - end - self.pos=self.pos+self.count - end - end - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - function c:OnStep(func) - table.insert(self.func,func) - end - return c -end -function multi:newTrigger(func) - local c=self:newBase() - c.Type="Trigger" - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - return c -end ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - self.Start=os.clock() - while self.Active do - self:Do_Order() - end -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - print("once!") - if dt then - self.pump=true - end - self.pumpvar=dt - self.Start=os.clock() -end -function multi:uManager(dt) - self:oneTime(self._tFunc,self,dt) - self:Do_Order() -end -multi.drawF={} -function multi:dManager() - for ii=1,#multi.drawF do - multi.drawF[ii]() - end -end -function multi:onDraw(func) - table.insert(self.drawF,func) -end -function multi:lManager() - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return nil - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - multi:uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - multi.dManager() - love.graphics.setColor(255,255,255,255) - if multi.draw then multi.draw() end - love.graphics.present() - end -end -Thread={} -Thread.Name="Thread 3" -Thread.ChannelThread = love.thread.getChannel("Easy3") -Thread.ChannelMain = love.thread.getChannel("EasyMain") -Thread.Global = {} -function Thread:packTable(G) - function escapeStr(str) - local temp="" - for i=1,#str do - temp=temp.."\\"..string.byte(string.sub(str,i,i)) - end - return temp - end - function ToStr(t) - local dat="{" - for i,v in pairs(t) do - if type(i)=="number" then - i="["..i.."]=" - else - i=i.."=" - end - if type(v)=="string" then - dat=dat..i.."\""..v.."\"," - elseif type(v)=="number" then - dat=dat..i..v.."," - elseif type(v)=="boolean" then - dat=dat..i..tostring(v).."," - elseif type(v)=="table" and not(G==v) then - dat=dat..i..ToStr(v).."," - --elseif type(v)=="table" and G==v then - -- dat=dat..i.."assert(loadstring(\"return self\"))," - elseif type(v)=="function" then - dat=dat..i.."assert(loadstring(\""..escapeStr(string.dump(v)).."\"))," - end - end - return string.sub(dat,1,-2).."}" - end - return "return "..ToStr(G) -end -function Thread:Send(name,var) - arg3="3" - if type(var)=="table" then - var=Thread:packTable(var) - arg3="table" - end - self.ChannelMain:push({name,var,arg3}) -end -function Thread:UnPackChannel() - local c=self.ChannelThread:getCount() - for i=1,c do - local temp=self.ChannelThread:pop() - if temp[1] and temp[2] then - if temp[1]=="func" and type(temp[2])=="string" then - loadstring(temp[2])(temp[3]) - else - _G[temp[1]]=temp[2] - end - end - end - if #multi:getChildren()<2 then - os.sleep(.05) - end -end -function Thread:boost(func,name) - self:Send(name,string.dump(func)) -end -function Thread.mainloop() - Thread:UnPackChannel() -end -Thread.MainThread=false -multi:newLoop():OnLoop(Thread.mainloop) -multi:mainloop() diff --git a/mulit/examples/love2d Threading Example/core/T4.lua b/mulit/examples/love2d Threading Example/core/T4.lua deleted file mode 100644 index a8d3203..0000000 --- a/mulit/examples/love2d Threading Example/core/T4.lua +++ /dev/null @@ -1,596 +0,0 @@ -require("love.timer") -require("love.system") -require("love.sound") -require("love.physics") -require("love.mouse") -require("love.math") -require("love.keyboard") -require("love.joystick") -require("love.image") -require("love.font") -require("love.filesystem") -require("love.event") -require("love.audio") -require("love.graphics") -require("love.window") -_defaultfont = love.graphics.getFont() -gui = {} -function gui.getTile(i,x,y,w,h)-- returns imagedata - if type(i)=="userdata" then - -- do nothing - else - error("getTile invalid args!!! Usage: ImageElement:getTile(x,y,w,h) or gui:getTile(imagedata,x,y,w,h)") - end - local iw,ih=i:getDimensions() - local id,_id=i:getData(),love.image.newImageData(w,h) - for _x=x,w+x-1 do - for _y=y,h+y-1 do - _id:setPixel(_x-x,_y-y,id:getPixel(_x,_y)) - end - end - return love.graphics.newImage(_id) -end -multi = {} -multi.Version="4.0.0" -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.Children={} -multi.Paused={} -multi.MasterId=0 -multi.Active=true -multi.Id=-1 -multi.Type="MainInt" -multi.Rest=0 --- System -os.sleep=love.timer.sleep -function multi:newBase(ins) - if not(self.Type=="MainInt" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.Act=function() end - c.Parent=self - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - self.MasterId=self.MasterId+1 - return c -end -function multi:reboot(r) - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.MasterId=0 - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=="table" then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:Do_Order() - for _D=#self.Mainloop,1,-1 do - if self.Mainloop[_D]~=nil then - self.Mainloop[_D].Id=_D - self.Mainloop[_D]:Act() - end - if self.Mainloop[_D].rem then - table.remove(self.Mainloop,_D) - end - end - if self.Rest>0 then - os.sleep(self.Rest) - end -end -function multi:benchMark(sec) - local temp=self:newLoop(function(t,self) - if os.clock()-self.init>self.sec then - print(self.c.." steps in "..self.sec.." second(s)") - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=os.clock() - temp.c=0 - return temp -end -function multi:newInterface() - if not(self.Type=="MainInt") then error("Can only create an interface on the multi obj") return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type="int" - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.MasterId=0 - c.Active=true - c.Id=-1 - c.Rest=0 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Stop() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - return c -end ---Helpers -function multi:FreeMainEvent() - self.func={} -end -function multi:isPaused() - return not(self.Active) -end -function multi:Pause(n) - if self.Type=="int" or self.Type=="MainInt" then - self.Active=false - if not(n) then - local c=self:getChildren() - for i=1,#c do - c[i]:Pause() - end - else - self:hold(n) - end - else - if not(n) then - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.Id=#self.Parent.Paused - end - else - self:hold(n) - end - end -end -function multi:Resume() - if self.Type=="int" or self.Type=="MainInt" then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - self.Active=true - for i=1,#self.Parent.Paused do - if self.Parent.Paused[i]==self then - table.remove(self.Parent.Paused,i) - return - end - end - table.insert(self.Parent.Mainloop,self) - end - end -end -function multi:Destroy() - if self.Type=="int" or self.Type=="MainInt" then - local c=self:getChildren() - for i=1,#c do - c[i]:Destroy() - end - else - self.rem=true - end -end -function multi:hold(task) - self:Pause() - if type(task)=="number" then - local alarm=self:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent.lManager() - else - self.Parent.Do_Order() - end - end - alarm:Destroy() - self:Resume() - elseif type(task)=="function" then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt:Stop() end) - while env.Active do - if love then - self.Parent.lManager() - else - self.Parent.Do_Order() - end - end - env:Destroy() - self:Resume() - else - print("Error Data Type!!!") - end -end -function multi:oneTime(func,...) - if not(self.Type=="MainInt" or self.Type=="int") then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end ---Constructors -function multi:newEvent(task) - local c=self:newBase() - c.Type="Event" - c.Task=task or function() end - function c:Act() - if self.Task(self) and self.Active==true then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - return c -end -function multi:newAlarm(set) - local c=self:newBase() - c.Type="Alarm" - c.timer=os.clock() - c.set=set or 0 - function c:Act() - if self.Active==true then - if os.clock()-self.timer>=self.set then - self:Pause() - for i=1,#self.func do - self.func[i](self) - end - end - end - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - function c:OnRing(func) - table.insert(self.func,func) - end - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newLoop(func) - local c=self:newBase() - c.Type="Loop" - if func then - c.func={func} - end - function c:Act() - if self.Active==true then - for i=1,#self.func do - self.func[i](os.clock()-self.Parent.Start,self) - end - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - return c -end -function multi:newStep(start,reset,count,skip) - local c=self:newBase() - think=1 - c.Type="Step" - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.Active==true then - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - c:OnStep(function(p,s) - if s.count>0 and s.endAt==p then - for fe=1,#s.funcE do - s.funcE[fe](s) - end - s.pos=s.start-1 - elseif s.count<0 and s.endAt==p then - for fe=1,#s.funcE do - s.funcE[fe](s) - end - s.pos=s.start-1 - end - end) - return c -end -function multi:newTStep(start,reset,count,set) - local c=self:newBase() - think=1 - c.Type="TStep" - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=os.clock() - c.set=set or 1 - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=os.clock() - self:Resume() - end - function c:Act() - if self.Active then - if os.clock()-self.timer>=self.set then - self:Reset() - for i=1,#self.func do - self.func[i](self.pos,self) - end - if self.endAt==self.pos then - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start-1 - end - self.pos=self.pos+self.count - end - end - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - function c:OnStep(func) - table.insert(self.func,func) - end - return c -end -function multi:newTrigger(func) - local c=self:newBase() - c.Type="Trigger" - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - return c -end ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - self.Start=os.clock() - while self.Active do - self:Do_Order() - end -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - print("once!") - if dt then - self.pump=true - end - self.pumpvar=dt - self.Start=os.clock() -end -function multi:uManager(dt) - self:oneTime(self._tFunc,self,dt) - self:Do_Order() -end -multi.drawF={} -function multi:dManager() - for ii=1,#multi.drawF do - multi.drawF[ii]() - end -end -function multi:onDraw(func) - table.insert(self.drawF,func) -end -function multi:lManager() - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return nil - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - multi:uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - multi.dManager() - love.graphics.setColor(255,255,255,255) - if multi.draw then multi.draw() end - love.graphics.present() - end -end -Thread={} -Thread.Name="Thread 4" -Thread.ChannelThread = love.thread.getChannel("Easy4") -Thread.ChannelMain = love.thread.getChannel("EasyMain") -Thread.Global = {} -function Thread:packTable(G) - function escapeStr(str) - local temp="" - for i=1,#str do - temp=temp.."\\"..string.byte(string.sub(str,i,i)) - end - return temp - end - function ToStr(t) - local dat="{" - for i,v in pairs(t) do - if type(i)=="number" then - i="["..i.."]=" - else - i=i.."=" - end - if type(v)=="string" then - dat=dat..i.."\""..v.."\"," - elseif type(v)=="number" then - dat=dat..i..v.."," - elseif type(v)=="boolean" then - dat=dat..i..tostring(v).."," - elseif type(v)=="table" and not(G==v) then - dat=dat..i..ToStr(v).."," - --elseif type(v)=="table" and G==v then - -- dat=dat..i.."assert(loadstring(\"return self\"))," - elseif type(v)=="function" then - dat=dat..i.."assert(loadstring(\""..escapeStr(string.dump(v)).."\"))," - end - end - return string.sub(dat,1,-2).."}" - end - return "return "..ToStr(G) -end -function Thread:Send(name,var) - arg3="4" - if type(var)=="table" then - var=Thread:packTable(var) - arg3="table" - end - self.ChannelMain:push({name,var,arg3}) -end -function Thread:UnPackChannel() - local c=self.ChannelThread:getCount() - for i=1,c do - local temp=self.ChannelThread:pop() - if temp[1] and temp[2] then - if temp[1]=="func" and type(temp[2])=="string" then - loadstring(temp[2])(temp[3]) - else - _G[temp[1]]=temp[2] - end - end - end - if #multi:getChildren()<2 then - os.sleep(.05) - end -end -function Thread:boost(func,name) - self:Send(name,string.dump(func)) -end -function Thread.mainloop() - Thread:UnPackChannel() -end -Thread.MainThread=false -multi:newLoop():OnLoop(Thread.mainloop) -multi:mainloop() diff --git a/mulit/examples/love2d Threading Example/core/ThreadManager.lua b/mulit/examples/love2d Threading Example/core/ThreadManager.lua deleted file mode 100644 index de6434d..0000000 --- a/mulit/examples/love2d Threading Example/core/ThreadManager.lua +++ /dev/null @@ -1,158 +0,0 @@ -Thread={} -Thread.ChannelT1 = love.thread.getChannel("Easy1") -Thread.ChannelT2 = love.thread.getChannel("Easy2") -Thread.ChannelT3 = love.thread.getChannel("Easy3") -Thread.ChannelT4 = love.thread.getChannel("Easy4") -Thread.ChannelMain = love.thread.getChannel("EasyMain") -Thread.Name = "Thread Main" -Thread.n=0 -Thread.count=1 -function Thread:packTable(G) - function escapeStr(str) - local temp="" - for i=1,#str do - temp=temp.."\\"..string.byte(string.sub(str,i,i)) - end - return temp - end - function ToStr(t) - local dat="{" - for i,v in pairs(t) do - if type(i)=="number" then - i="["..i.."]=" - else - i=i.."=" - end - if type(v)=="string" then - dat=dat..i.."\""..v.."\"," - elseif type(v)=="number" then - dat=dat..i..v.."," - elseif type(v)=="boolean" then - dat=dat..i..tostring(v).."," - elseif type(v)=="table" and not(G==v) then - dat=dat..i..bin.ToStr(v).."," - --elseif type(v)=="table" and G==v then - -- dat=dat..i.."assert(loadstring(\"return self\"))," - elseif type(v)=="function" then - dat=dat..i.."assert(loadstring(\""..escapeStr(string.dump(v)).."\"))," - end - end - return string.sub(dat,1,-2).."}" - end - return ToStr(G) -end -Thread.last={} -function Thread:GetStatus() - print(self.n.." Threads Exist!!!") - for i=1,self.n do - print("\tThread "..i.." Running: "..tostring(self["Thread"..i]:isRunning())) - if not(self["Thread"..i]:isRunning()) then - print("\t\t"..self["Thread"..i]:getError()) - end - end -end -function Thread:Start(n) - local x=love.system.getProcessorCount() - if x>1 then - x=x-1 - else - x=1 - end - n=n or x - if n<1 then - print("Must be atleast 1 thread running!!!") - return - end - if n>4 then - print("Must be no more than 4 threads running!!!") - return - end - for i=1,n do - self["Thread"..i]=love.thread.newThread("Libs/T"..i..".lua") - self["Thread"..i]:start() - end - Thread.n=n -end -function Thread:RestartBroken() - for i=1,self.n do - if self["Thread"..i]:isRunning()==false then - self["Thread"..i]:start() - end - Thread:Boost(Thread.last[1],Thread.last[2]) - end -end -function Thread:Send(name,var,arg3) - if self.n>0 then - if type(var)=="table" then - var=Thread:packTable(var) - arg3=name - name="table" - end - self["ChannelT"..((self.count-1)%self.n)+1]:push({name,var,arg3}) - self.count=self.count+1 - end -end -function Thread:SendAll(name,var,arg3) - if self.n>0 then - for i=1,self.n do - if type(var)=="table" then - var=Thread:packTable(var) - arg3=name - name="table" - end - self["ChannelT"..i]:push({name,var,arg3}) - end - end -end -function Thread:UnPackChannel() - local c=self.ChannelMain:getCount() - for i=1,c do - local temp=self.ChannelMain:pop() - if temp[3]=="table" then - _G[temp[1]]=assert(loadstring(temp[2]))() - else - if Thread.OnDataRecieved then - Thread.OnDataRecieved(temp[1],temp[2],temp[3]) - end - _G[temp[1]]=temp[2] - end - end -end -function Thread:Boost(func,name) - if Thread.last[1]==nil then - return - end - Thread.last={func,name} - name=name or "nil" - if self.n>0 then - self:Send("func",string.dump(func),name) - end -end -function Thread:SendLibs(func,name) - name=name or "nil" - if self.n>0 then - self:SendAll("func",string.dump(func),name) - end -end -function Thread.mainloop() - if Thread.n>0 then - Thread:UnPackChannel() - end -end -Thread.MainThread=true -local loop = multi:newLoop() -loop:OnLoop(Thread.mainloop) -OnThreadError=multi:newConnection() -function love.threaderror(thread, errorstr) - Thread:GetStatus() - Thread:RestartBroken() - Thread:GetStatus() - OnThreadError:Fire(thread,errorstr) -end -multi:newTask(function() - math.randomseed(math.floor(os.time()/2)) - for i=1,Thread.n do - Thread["ChannelT"..i]:push({"randseed",math.random(-1000000,1000000)}) - Thread["ChannelT"..i]:push({"func",string.dump(function() math.randomseed(randseed) end),"randomizing"}) - end -end) diff --git a/mulit/examples/love2d Threading Example/core/Utils.lua b/mulit/examples/love2d Threading Example/core/Utils.lua deleted file mode 100644 index c80b4bc..0000000 --- a/mulit/examples/love2d Threading Example/core/Utils.lua +++ /dev/null @@ -1,797 +0,0 @@ --- os Additions -function os.getSystemBit() - if (os.getenv('PROCESSOR_ARCHITEW6432')=='AMD64' or os.getenv('PROCESSOR_ARCHITECTURE')=='AMD64') then - return 64 - else - return 32 - end -end -function os.sleep(n) - if not n then n=0 end - local t0 = os.clock() - while os.clock() - t0 <= n do end -end -function os.pause(msg) - if msg ~= nil then - print(msg) - end - io.read() -end -function os.batCmd(cmd) - io.mkFile('temp.bat',cmd) - local temp = os.execute([[temp.bat]]) - io.delFile('temp.bat') - return temp -end -function os._getOS() - if package.config:sub(1,1)=='\\' then - return 'windows' - else - return 'unix' - end -end -function os.getOS(t) - if not t then - return os._getOS() - end - if os._getOS()=='unix' then - fh,err = io.popen('uname -o 2>/dev/null','r') - if fh then - osname = fh:read() - end - if osname then return osname end - end - local winver='Unknown Version' - local a,b,c=os.capture('ver'):match('(%d+).(%d+).(%d+)') - local win=a..'.'..b..'.'..c - if type(t)=='string' then - win=t - end - if win=='4.00.950' then - winver='95' - elseif win=='4.00.1111' then - winver='95 OSR2' - elseif win=='4.00.1381' then - winver='NT 4.0' - elseif win=='4.10.1998' then - winver='98' - elseif win=='4.10.2222' then - winver='98 SE' - elseif win=='4.90.3000' then - winver='ME' - elseif win=='5.00.2195' then - winver='2000' - elseif win=='5.1.2600' then - winver='XP' - elseif win=='5.2.3790' then - winver='Server 2003' - elseif win=='6.0.6000' then - winver='Vista/Windows Server 2008' - elseif win=='6.0.6002' then - winver='Vista SP2' - elseif win=='6.1.7600' then - winver='7/Windows Server 2008 R2' - elseif win=='6.1.7601' then - winver='7 SP1/Windows Server 2008 R2 SP1' - elseif win=='6.2.9200' then - winver='8/Windows Server 2012' - elseif win=='6.3.9600' then - winver='8.1/Windows Server 2012' - elseif win=='6.4.9841' then - winver='10 Technical Preview 1' - elseif win=='6.4.9860' then - winver='10 Technical Preview 2' - elseif win=='6.4.9879' then - winver='10 Technical Preview 3' - elseif win=='10.0.9926' then - winver='10 Technical Preview 4' - end - return 'Windows '..winver -end -function os.getLuaArch() - return (#tostring({})-7)*4 -end -if os.getOS()=='windows' then - function os.sleep(n) - if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end - end -else - function os.sleep(n) - os.execute('sleep ' .. tonumber(n)) - end -end -function os.capture(cmd, raw) - local f = assert(io.popen(cmd, 'r')) - local s = assert(f:read('*a')) - f:close() - if raw then return s end - s = string.gsub(s, '^%s+', '') - s = string.gsub(s, '%s+$', '') - s = string.gsub(s, '[\n\r]+', ' ') - return s -end -function os.getCurrentUser() - return os.getenv('$USER') or os.getenv('USERNAME') -end --- string Additions -function string.trim(s) - local from = s:match"^%s*()" - return from > #s and "" or s:match(".*%S", from) -end -function string.random(n) - local str = '' - strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'} - for i=1,n do - h = math.random(1,#strings) - str = str..''..strings[h] - end - return str -end -function string.linesToTable(s) - local t = {} - local i = 0 - while true do - i = string.find(s, '\n', i+1) - if i == nil then return t end - table.insert(t, i) - end -end -function string.lines(str) - local t = {} - local function helper(line) table.insert(t, line) return '' end - helper((str:gsub('(.-)\r?\n', helper))) - return t -end -function string.split(str, pat) - local t = {} -- NOTE: use {n = 0} in Lua-5.0 - local fpat = '(.-)' .. pat - local last_end = 1 - local s, e, cap = str:find(fpat, 1) - while s do - if s ~= 1 or cap ~= '' then - table.insert(t,cap) - end - last_end = e+1 - s, e, cap = str:find(fpat, last_end) - end - if last_end <= #str then - cap = str:sub(last_end) - table.insert(t, cap) - end - return t -end -function string.shuffle(inputStr) - math.randomseed(os.time()); - local outputStr = ''; - local strLength = string.len(inputStr); - while (strLength ~=0) do - local pos = math.random(strLength); - outputStr = outputStr..string.sub(inputStr,pos,pos); - inputStr = inputStr:sub(1, pos-1) .. inputStr:sub(pos+1); - strLength = string.len(inputStr); - end - return outputStr; -end -function string.genKeys(chars,a,f,s,GG) - if GG then - chars=string.rep(chars,a) - end - if s then - chars=string.shuffle(chars) - end - b=#chars - if a==0 then return end - local taken = {} local slots = {} - for i=1,a do slots[i]=0 end - for i=1,b do taken[i]=false end - local index = 1 - local tab={} - for i=1,#chars do - table.insert(tab,chars:sub(i,i)) - end - while index > 0 do repeat - repeat slots[index] = slots[index] + 1 - until slots[index] > b or not taken[slots[index]] - if slots[index] > b then - slots[index] = 0 - index = index - 1 - if index > 0 then - taken[slots[index]] = false - end - break - else - taken[slots[index]] = true - end - if index == a then - local tt={} - for i=1,a do - table.insert(tt,tab[slots[i]]) - end - f(table.concat(tt)) - taken[slots[index]] = false - break - end - index = index + 1 - until true end -end --- io Additions -function io.getInput(msg) - if msg ~= nil then - io.write(msg) - end - return io.read() -end -function io.scanDir(directory) - directory=directory or io.getDir() - local i, t, popen = 0, {}, io.popen - if os.getOS()=='unix' then - for filename in popen('ls -a \''..directory..'\''):lines() do - i = i + 1 - t[i] = filename - end - else - for filename in popen('dir \''..directory..'\' /b'):lines() do - i = i + 1 - t[i] = filename - end - end - return t -end -function io.buildFromTree(tbl, indent,folder) - if not indent then indent = 0 end - if not folder then folder = '' end - for k, v in pairs(tbl) do - formatting = string.rep(' ', indent) .. k .. ':' - if type(v) == 'table' then - if not(io.dirExists(folder..string.sub(formatting,1,-2))) then - io.mkDir(folder..string.sub(formatting,1,-2)) - end - io.buildFromTree(v,0,folder..string.sub(formatting,1,-2)..'\\') - else - a=string.find(tostring(v),':',1,true) - if a then - file=string.sub(tostring(v),1,a-1) - data=string.sub(tostring(v),a+1) - io.mkFile(folder..file,data,'wb') - else - io.mkFile(folder..v,'','wb') - end - end - end -end -function io.cpFile(path,topath) - if os.getOS()=='unix' then - os.execute('cp '..file1..' '..file2) - else - os.execute('Copy '..path..' '..topath) - end -end -function io.delDir(directoryname) - if os.getOS()=='unix' then - os.execute('rm -rf '..directoryname) - else - os.execute('rmdir '..directoryname..' /s /q') - end -end -function io.delFile(path) - os.remove(path) -end -function io.mkDir(dirname) - os.execute('mkdir "' .. dirname..'"') -end -function io.mkFile(filename,data,tp) - if not(tp) then tp='wb' end - if not(data) then data='' end - file = io.open(filename, tp) - if file==nil then return end - file:write(data) - file:close() -end -function io.movFile(path,topath) - io.cpFile(path,topath) - io.delFile(path) -end -function io.listFiles(dir) - if not(dir) then dir='' end - local f = io.popen('dir \''..dir..'\'') - if f then - return f:read('*a') - else - print('failed to read') - end -end -function io.getDir(dir) - if not dir then return io.getWorkingDir() end - if os.getOS()=='unix' then - return os.capture('cd '..dir..' ; cd') - else - return os.capture('cd '..dir..' & cd') - end -end -function io.getWorkingDir() - return io.popen'cd':read'*l' -end -function io.fileExists(path) - g=io.open(path or '','r') - if path =='' then - p='empty path' - return nil - end - if g~=nil and true or false then - p=(g~=nil and true or false) - end - if g~=nil then - io.close(g) - else - return false - end - return p -end -function io.fileCheck(file_name) - if not file_name then print('No path inputed') return false end - local file_found=io.open(file_name, 'r') - if file_found==nil then - file_found=false - else - file_found=true - end - return file_found -end -function io.dirExists(strFolderName) - strFolderName = strFolderName or io.getDir() - local fileHandle, strError = io.open(strFolderName..'\\*.*','r') - if fileHandle ~= nil then - io.close(fileHandle) - return true - else - if string.match(strError,'No such file or directory') then - return false - else - return true - end - end -end -function io.getAllItems(dir) - local t=os.capture("cd \""..dir.."\" & dir /a-d | find",true):lines() - return t -end -function io.listItems(dir) - if io.dirExists(dir) then - temp=io.listFiles(dir) -- current directory if blank - if io.getDir(dir)=='C:\\\n' then - a,b=string.find(temp,'C:\\',1,true) - a=a+2 - else - a,b=string.find(temp,'..',1,true) - end - temp=string.sub(temp,a+2) - list=string.linesToTable(temp) - temp=string.sub(temp,1,list[#list-2]) - slist=string.lines(temp) - table.remove(slist,1) - table.remove(slist,#slist) - temp={} - temp2={} - for i=1,#slist do - table.insert(temp,string.sub(slist[i],40,-1)) - end - return temp - else - return nil - end -end -function io.getDirectories(dir,l) - if dir then - dir=dir..'\\' - else - dir='' - end - local temp2=io.scanDir(dir) - for i=#temp2,1,-1 do - if io.fileExists(dir..temp2[i]) then - table.remove(temp2,i) - elseif l then - temp2[i]=dir..temp2[i] - end - end - return temp2 -end -function io.getFiles(dir,l) - if dir then - dir=dir..'\\' - else - dir='' - end - local temp2=io.scanDir(dir) - for i=#temp2,1,-1 do - if io.dirExists(dir..temp2[i]) then - table.remove(temp2,i) - elseif l then - temp2[i]=dir..temp2[i] - end - end - return temp2 -end -function io.getFullName(name) - local temp=name or arg[0] - if string.find(temp,'\\',1,true) or string.find(temp,'/',1,true) then - temp=string.reverse(temp) - a,b=string.find(temp,'\\',1,true) - if not(a) or not(b) then - a,b=string.find(temp,'/',1,true) - end - return string.reverse(string.sub(temp,1,b-1)) - end - return temp -end -function io.getName(file) - local name=io.getFullName(file) - name=string.reverse(name) - a,b=string.find(name,'.',1,true) - name=string.sub(name,a+1,-1) - return string.reverse(name) -end -function io.readFile(file) - local f = io.open(file, 'rb') - local content = f:read('*all') - f:close() - return content -end -function io.getExtension(file) - local file=io.getFullName(file) - file=string.reverse(file) - local a,b=string.find(file,'.',0,true) - local temp=string.sub(file,1,b) - return string.reverse(temp) -end -function io.pathToTable(path) - local p=io.splitPath(path) - local temp={} - temp[p[1]]={} - local last=temp[p[1]] - for i=2,#p do - snd=last - last[p[i]]={} - last=last[p[i]] - end - return temp,last,snd -end -function io.splitPath(str) - return string.split(str,'[\\/]+') -end - -function io.parseDir(dir,t) - io.tempFiles={} - function _p(dir) - local dirs=io.getDirectories(dir,true) - local files=io.getFiles(dir,true) - for i=1,#files do - p,l,s=io.pathToTable(files[i]) - if t then - s[io.getFullName(files[i])]=io.readFile(files[i]) - else - s[io.getFullName(files[i])]=io.open(files[i],'r+') - end - table.merge(io.tempFiles,p) - end - for i=1,#dirs do - table.merge(io.tempFiles,io.pathToTable(dirs[i])) - _p(dirs[i],t) - end - end - _p(dir) - return io.tempFiles -end -function io.parsedir(dir,f) - io.tempFiles={} - function _p(dir,f) - local dirs=io.getDirectories(dir,true) - local files=io.getFiles(dir,true) - for i=1,#files do - if not f then - table.insert(io.tempFiles,files[i]) - else - f(files[i]) - end - end - for i=1,#dirs do - _p(dirs[i],f) - end - end - _p(dir,f) - return io.tempFiles -end -function io.driveReady(drive) - drive=drive:upper() - if not(drive:find(':',1,true)) then - drive=drive..':' - end - drives=io.getDrives() - for i=1,#drives do - if drives[i]==drive then - return true - end - end - return false -end -function io.getDrives() - if os.getOS()=='windows' then - local temp={} - local t1=os.capture('wmic logicaldisk where drivetype=2 get deviceid, volumename',true) - local t2=os.capture('wmic logicaldisk where drivetype=3 get deviceid, volumename',true) - for drive,d2 in t1:gmatch('(.:)%s-(%w+)') do - if #d2>1 then - table.insert(temp,drive) - end - end - for drive in t2:gmatch('(.:)') do - table.insert(temp,drive) - end - return temp - end - error('Command is windows only!') -end --- table Additions -function table.dump(t,indent) - local names = {} - if not indent then indent = '' end - for n,g in pairs(t) do - table.insert(names,n) - end - table.sort(names) - for i,n in pairs(names) do - local v = t[n] - if type(v) == 'table' then - if(v==t) then - print(indent..tostring(n)..': <-') - else - print(indent..tostring(n)..':') - table.dump(v,indent..' ') - end - else - if type(v) == 'function' then - print(indent..tostring(n)..'()') - else - print(indent..tostring(n)..': '..tostring(v)) - end - end - end -end -function table.alphanumsort(o) - local function padnum(d) local dec, n = string.match(d, '(%.?)0*(.+)') - return #dec > 0 and ('%.12f'):format(d) or ('%s%03d%s'):format(dec, #n, n) - end - table.sort(o, function(a,b) return tostring(a):gsub('%.?%d+',padnum)..('%3d'):format(#b)< tostring(b):gsub('%.?%d+',padnum)..('%3d'):format(#a) end) - return o -end -function table.foreach(t,f) - for i,v in pairs(t) do - f(v) - end -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -function table.print(tbl, indent) - if not indent then indent = 0 end - for k, v in pairs(tbl) do - formatting = string.rep(' ', indent) .. k .. ': ' - if type(v) == 'table' then - print(formatting) - table.print(v, indent+1) - else - print(formatting .. tostring(v)) - end - end -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -function table.clear(t) - for k in pairs (t) do - t[k] = nil - end -end -function table.copy(t) - function deepcopy(orig) - local orig_type = type(orig) - local copy - if orig_type == 'table' then - copy = {} - for orig_key, orig_value in next, orig, nil do - copy[deepcopy(orig_key)] = deepcopy(orig_value) - end - setmetatable(copy, deepcopy(getmetatable(orig))) - else -- number, string, boolean, etc - copy = orig - end - return copy - end - return deepcopy(t) -end -function table.swap(tab,i1,i2) - tab[i1],tab[i2]=tab[i2],tab[i1] -end -function table.append(t1, ...) - t1,t2= t1 or {},{...} - for k,v in pairs(t2) do - t1[#t1+1]=t2[k] - end - return t1 -end -function table.compare(t1, t2,d) - if d then - return table.deepCompare(t1,t2) - end - --if #t1 ~= #t2 then return false end - if #t2>#t1 then - for i=1,#t2 do - if t1[i] ~= t2[i] then - return false,t2[i] - end - end - else - for i=1,#t1 do - if t1[i] ~= t2[i] then - return false,t2[i] - end - end - end - return true -end -function table.deepCompare(t1,t2) - if t1==t2 then return true end - if (type(t1)~='table') then return false end - local mt1 = getmetatable(t1) - local mt2 = getmetatable(t2) - if( not table.deepCompare(mt1,mt2) ) then return false end - for k1,v1 in pairs(t1) do - local v2 = t2[k1] - if( not table.deepCompare(v1,v2) ) then return false end - end - for k2,v2 in pairs(t2) do - local v1 = t1[k2] - if( not table.deepCompare(v1,v2) ) then return false end - end - return true -end -function table.has(t,_v) - for i,v in pairs(t) do - if v==_v then - return true - end - end - return false -end -function table.reverse(tab) - local size = #tab - local newTable = {} - for i,v in ipairs (tab) do - newTable[size-i] = v - end - for i=1,#newTable do - tab[i]=newTable[i] - end -end --- Math Additions -local Y = function(g) local a = function(f) return f(f) end return a(function(f) return g(function(x) local c=f(f) return c(x) end) end) end -local F = function(f) return function(n)if n == 0 then return 1 else return n*f(n-1) end end end -math.factorial = Y(F) -math.fib={} -math.fib.fibL={} -setmetatable(math.fib,{__call=function(self,n) - if n<=2 then - return 1 - else - if self.fibL[n] then - return self.fibL[n] - else - local t=math.fib(n-1)+math.fib(n-2) - self.fibL[n]=t - return t - end - end -end}) -local floor,insert = math.floor, table.insert -function math.basen(n,b) - n = floor(n) - if not b or b == 10 then return tostring(n) end - local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' - local t = {} - local sign = '' - if n < 0 then - sign = '-' - n = -n - end - repeat - local d = (n % b) + 1 - n = floor(n / b) - insert(t, 1, digits:sub(d,d)) - until n == 0 - return sign .. table.concat(t,'') -end -function math.convbase(n,b,tb) - return math.basen(tonumber(tostring(n),b),tb) -end -if BigNum then - function BigNum.mod(a,b) - return a-((a/b)*b) - end - local floor,insert = math.floor, table.insert - function math.basen(n,b) - n = BigNum.new(n) - if not b or b == 10 then return tostring(n) end - local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' - local t = {} - local sign = '' - if n < BigNum.new(0) then - sign = '-' - n = -n - end - repeat - local d = BigNum.mod(n , b) + 1 - n = n/b - d=tonumber(tostring(d)) - insert(t, 1, digits:sub(d,d)) - until tonumber(tostring(n)) == 0 - return sign .. table.concat(t,'') - end - function math.to10(n,b) - local num=tostring(n) - local sum=BigNum.new() - local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' - for i=1,#num do - local v=digits:find(num:sub(i,i),1,true) - sum=sum+BigNum.new(tonumber(v)-1)*BigNum.pow(BigNum.new(b),BigNum.new(#num-i)) - end - return sum - end - function math.convbase(n,b,tb) - return math.basen(math.to10(n,b),tb) - end -end -function math.numfix(n,x) - local str=tostring(n) - if #str olleh -nil = binobj:flipbits() -- flips the binary bits -nil** = binobj:segment(a,b) -- gets a segment of the binobj data works just like string.sub(a,b) without str -nil* = binobj:insert(a,i) -- inserts i (string or number(converts into string)) in position a -nil* = binobj:parseN(n) -- removes ever (nth) byte of data -nil = binobj:getlength() -- gets length or size of binary data -nil* = binobj:shift(n) -- shift the binary data by n positive --> negitive <-- -nil* = binobj:delete(a,b) -- deletes part of a binobj data Usage: binobj:delete(#) deletes at pos # binobj:delete(#1,#2) deletes from #1 to #2 binobj:delete('string') deletes all instances of 'byte' as a string Use string.char(#) or '\#' to get byte as a string -nil* = binobj:encrypt(seed) -- encrypts data using a seed, seed may be left blank -nil* = binobj:decrypt(seed) -- decrypts data encrypted with encrypt(seed) -nil* = binobj:shuffle() -- Shuffles the data randomly Note: there is no way to get it back!!! If original is needed clone beforehand -nil** = binobj:mutate(a,i) -- changes position a's value to i -nil = binobj:merge(o,t) -- o is the binobj you are merging if t is true it merges the new data to the left of the binobj EX: b:merge(o,true) b='yo' o='data' output: b='datayo' b:merge(o) b='yo' o='data' output: b='yodata' -nil* = binobj:parseA(n,a,t) -- n is every byte where you add, a is the data you are adding, t is true or false true before false after -nil = binobj:getHEX(a,b) -- returns the HEX of the bytes between a,b inclusive -nil = binobj:cryptM() -- a mirrorable encryptor/decryptor -nil = binobj:addBlock(d,n) -- adds a block of data to a binobj s is size d is data e is a bool if true then encrypts string values. if data is larger than 'n' then data is lost. n is the size of bytes the data is Note: n is no longer needed but you must use getBlock(type) to get it back -nil = binobj:getBlock(t,n) -- gets block of code by type -nil = binobj:seek(n) -- used with getBlock EX below with all 3 -nil* = binobj:morph(a,b,d) -- changes data between point a and b, inclusive, to d -nil = binobj:fill(n,d) -- fills binobj with data 'd' for n -nil = binobj:fillrandom(n) -- fills binobj with random data for n -nil = binobj:shiftbits(n) -- shifts all bits by n amount -nil = binobj:shiftbit(n,i) -- shifts a bit ai index i by n -nil# = binobj:streamwrite(d,n) -- writes to the streamable binobj d data n position -nil# = binobj:open() -- opens the streamable binobj -nil# = binobj:close() -- closes the streamable binobj -nil = binobj:wipe() -- erases all data in the file -nil* = binobj:tackB(d) -- adds data to the beginning of a file -nil = binobj:tackE(d) -- adds data to the end of a file -nil = binobj:parse(n,f) -- loops through each byte calling function 'f' with the args(i,binobj,data at i) -nil = binobj:flipbit(i) -- flips the binary bit at position i -nil* = binobj:gsub() -- just like string:gsub(), but mutates self -nil = blockWriter:addNamedBlock(name,value) -- writes a named block to the file with name 'name' and the value 'value' - -Note: numbers are written in Big-endian use bin.endianflop(d) to filp to Little-endian - -Note: binobj:tonumber() returns big,little endian so if printing do: b,l=binobj:tonumber() print(l) print(b) - -nil = bitobj:add(i) -- adds i to the bitobj i can be a number (base 10) or a bitobj -nil = bitobj:sub(i) -- subs i to the bitobj i can be a number (base 10) or a bitobj -nil = bitobj:multi(i) -- multiplys i to the bitobj i can be a number (base 10) or a bitobj -nil = bitobj:div(i) -- divides i to the bitobj i can be a number (base 10) or a bitobj -nil = bitobj:flipbits() -- filps the bits 1 --> 0, 0 --> 1 -string = bitobj:getBin() -- returns 1's & 0's of the bitobj - -# stream objects only -* not compatible with stream files -** works but do not use with large files or it works to some degree -*** in stream objects all changes are made directly to the file, so there is no need to do tofile() -*D -]] - -bin.Changelog=[[ -Version.Major.Minor -------------------------- -1.0.0 : initial release load/new/tofile/clone/closeto/compare/sub/reverse/flip/segment/insert/insert/parseN/getlength/shift -1.0.1 : update Delete/tonumber/getbyte/ -1.0.2 : update Changed how delete works. Added encrypt/decrypt/shuffle -1.0.3 : update Added bits class, Added in bin: tobit/mutate/parseA Added in bits: add/sub/multi/div/isover/tobyte/tonumber/flip -1.0.4 : update Changed tobyte() to tobytes()/flipbit() to flipbits() and it now returns a binobj not str Added bin:merge -1.0.5 : update Changed bin.new() now hex data can be inserted EX: bin.new('0xFFC353D') Added in bin: getHEX/cryptM/addBlock/getBlock/seek -1.0.6 : update Added bin.NumtoHEX/bin:getHEX/bin.HEXtoBin/bin.HEXtoStr/bin.tohex/bin.fromhex -1.0.7 : update Added bin:morph/bin.endianflop/bin:scan/bin.ToStr -1.0.8 : update Added bin:fill/bin:fillrandom -1.1.0 : update Added bin.packLLIB/bin.unpackLLIB -1.2.0 : update Updated llib files -1.3.0 : Update Changed bin.unpackLLIB and bin.load() Added: bin.fileExist -1.4.0 : Update Changed bin.unpackLLIB bin.packLLIB Added: bin:shiftbits(n) bin:shiftbit(n,i) - -Woot!!! Version 2 -2.0.0 HUGE UPDATE Added Streamable files!!! lua 5.1, 5.2 and 5.3 compatable!!! -#binobj is the same as binobj:getlength() but only works in 5.2 and 5.3, in 5.1 just use getlength() or getSize() for compatibility -Now you can work with gigabyte sized data without memory crashes(streamable files[WIP]). - -Stream Compatible methods: - sub(a,b) - getlength() - tofile(filename) - flipbits() - tonumber(a,b) - getbyte(n) - segment(a,b) - parse(n,f) - tobits(i) - reverse() - flipbit(i) - cryptM() - getBlock(t,n) - addBlock(d,n) - shiftbits(n) - shiftbit(n,i) - getHEX(a,b) - -Added functions in this version: - binobj:streamwrite(d,n) - binobj:open() - binobj:close() - binobj:tackB(d) - binobj:tackE(d) - binobj:parse(n,f) - binobj:flipbit(i) - bin.stream(file) - binobj:streamData(a,b) - bin.getVersion() - bin.escapeStr(str) - binobj:streamread(a,b) - binobj:canStreamWrite() - binobj:wipe() - -Woot!!! Version 3 -3.0.0 HUGE UPDATE!!! - Added: bin.newVFS() bin.loadVFS() bin.textToBinary(txt) bin.decodeBits(bindata) bitobj:getBin() - Updated: bin.addBlock() <-- Fixed error with added features to the bits.new() function that allow for new functions to work - Notice: The bin library now requires the utils library!!! Put utils.lua in the lua/ directory -3.1.0 - Added: bin.newTempFile(data) binobj:setEndOfFile(n) bin.randomName(n,ext) - Updated: bin:tackE() bin:fill() bin:fillrandom() are now stream compatible! - Notice: bin:setEndOfFile() only works on streamable files! -3.1.1 - Added: bin.trimNul(s) bin:gsub() -3.1.2 - Added: log(data,name,fmt) - In secret something is brewing... - -3.1.3 - Added: bin:getHash(n) -3.2.1 - Added: bin.encryptA(data,seed), bin.decryptA(data,seed), bin.encryptB(data,seed), bin.decryptB(data,seed), bin:flush() - Updated: bin:encrypt(seed) and bin:decrypt(seed) - Fixed: bin:shiftbit() not working right with streamable files -3.2.2 - Fixed: bits.new() -- minor mistake huge error -3.2.3 - General bug fixes - Changed how bin.ToStr(t) -- functions are no longer valid data types -3.3.0 - Added: - bin:getSize() -- same as bin:getlength() just makes more sense. bin:getlength() is still valid and always will be. - bin.newLink() -- creates a link to a file object... Its like opening a file without opening it... Lua can only open a maximum of 200 files so use links if you will be going beyond that or make sure to close your files - bin.getHash2(h,n) -- 'h' hash size 8bit,16bit,32bit,64bit, 128bit, 100000bit whatever. is a number 'n' is the segmentation size defualt is 1024 greater numbers result in faster hashes but eaiser to forge hashes -3.4.1:(7/22/2016) NOTE: I started to add dates so I can see my work flow - Added: - binobj:getData() -- returns bin object as a string - bin:newDataBuffer(s) - Fixed: binobj:tonumber(a,b) -4.0.0:(7/23/2016) - Added: - bin.bufferToBin(b) - bin.binToBuffer(b) - bin.getLuaVersion() - bin.newNamedBlock(indexSize) - bin.newStreamedNamedBlock(indexSize,path) - bin.loadNamedBlock(path) - bin.getIndexSize(tab) - bits.numToBytes(num,occ) -4.1.0:(11/2/2016) NOTE: I took quite a long break due to college lol - Added: - bin.namedBlockManager(name) - Allows for a new way to use NamedBlocks - Example usage: - test=bin.namedBlockManager() - test["name"]="Ryan" -- My name lol - test["age"]=21 -- my age lol - test:tofile("test.dat") - --Now lets load the data we created - test2=bin.namedBlockManager("test.dat") - print(test2["name"]) - print(test2["age"]) - Changed: - bin.newNamedBlock(indexSize) - Now allows for indexSize to be nil and dynamacally adds to the size of the index - Fixed: - bin.loadNamedBlock(name) - Issue with indexing - TODO: - Allow streamed files to have expanding indexes -4.2.0:(12/21/2016) - Added: - bin.gcd(m,n) *takes number types returns a number - gets the greatest common denominator between 2 numbers m and n - bin.numToFraction(num) *takes number type returns a string type - converts a decimal to a fraction - so 5.5 would become 11/2 - bin.doubleToString(double) *takes number type returns string - converts a double to a string - bin.stringToDouble(str) *takes string type returns number type - converts the doublestring into a number - NOTE: this string can be 2 lengths! Either 9 bytes or 25 bytes... depending on the precision needed the program will convert the data - Also: the miniheader -/+ is for 9byte doubles the miniheader _/=(same keys as -/+ on an American keyboard) is for 25byte doubles - Changed: - bits.numToBytes(n,fit,func) - added argument func which is called when the number n takes up more space than size 'fit' - passes a ref table with keys num and fit, modifying these effects the output. - Note: If you change ref.fit make sure to make ref.num fits by adding \0 to the beginning of the numberstring - TODO: - add more useful features :P -4.2.1:(12/23/2016) - Added: - bin.decompress(comp) lzw commpression - bin.compress(uncomp) lzw decommpression - bin:segmentedRead(size,func) -4.3.0:(12/26/2016) - Added: - bin.tob64(data) - converts string data to b64 data - bin.fromb64(data) - converts b64 data to string data - bin:getB64() - returns b64 data from binobj - bits.lsh(value,shift) bit lshift - bits.rsh(value,shift) bit rshift - bits.bit(x,b) bit thing - bits.lor(x,y) or - Changed: - bin.new(data,hex,b64) hex if true treats data as hexdata, b64 if true treats data like b64data - Now allows b64 data to be used in construction of a bin file -4.4.0:(1/1/2017) - Added: - sinkobj=bin:newSink() - nil=sinkobj:tackE(data) - adds data into the sink, same method that binobj and streamobjs have. This does what you would expest the binobj to do but much quicker - nil=sinkobj:tofile(path) - creates a file containing the contents of the sink - str=sinkobj:getData() - returns the data of the sink as a string - nil=sinkobj:reset() - Clears the sink -4.4.1:(1/2/2017) - Changed: - bin.stream(file,lock) - Modified stream files so that multiple streams can link to one file by sharing handles -4.4.2:(1/10/2017) - Added: - bin.freshStream(file) - creates a stream object that wipes all data if the file already exists and readys the object for writing. In short it's doing: bin.new():tofile(file) return bin.stream(file,false) - -- I found myself doing that so much I made a method to simplify the process -4.5.0:(3/31/2017) - Added: - bin:getDataBuffer(a,b) -- a and b are the location to open on the streamed object they are not required though - -- If left out the entire file is open to used as a buffer! Even a empty streamed file works. Be sure to fill the buffer before trying to write to a location without data - -- Index 1 is the start regardless of where you open up the file - Note: Only works on streamed files! Use bin:newDataBuffer(s) to use the non streamed version -]] -bin.data='' -bin.t='bin' -bin.__index = bin -bin.__tostring=function(self) return self:getData() end -bin.__len=function(self) return self:getlength() end -bits={} -bits.data='' -bits.t='bits' -bits.__index = bits -bits.__tostring=function(self) return self.data end -bits.__len=function(self) return (#self.data)/8 end -bin.lastBlockSize=0 -bin.streams={} -- allows for multiple stream objects on one file... tricky stuff lol ---[[---------------------------------------- -Links -------------------------------------------]] -function bin.newLink(path) - if not path then - error("Must include a path when using a link!") - end - local c={} - c.path=path - c.tempfile={} - local mt={ - __tostring=function(self) - if self:getlength()>2048 then - -- - end - end, - __len=function(self) - return self:getlength() - end - } - function c:getlength() - -- - end -end - - ---[[---------------------------------------- -utils -------------------------------------------]] -function cleanName(name) - name=name:gsub("\\","") - name=name:gsub("/","") - name=name:gsub(":","") - name=name:gsub("*","") - name=name:gsub("%?","") - name=name:gsub("\"","''") - name=name:gsub("<","") - name=name:gsub(">","") - name=name:gsub("|","") - return name -end -function math.numfix(n,x) - local str=tostring(n) - if #str/dev/null','r') - if fh then - osname = fh:read() - end - if osname then return osname end - end - local winver='Unknown Version' - local a,b,c=os.capture('ver'):match('(%d+).(%d+).(%d+)') - local win=a..'.'..b..'.'..c - if type(t)=='string' then - win=t - end - if win=='4.00.950' then - winver='95' - elseif win=='4.00.1111' then - winver='95 OSR2' - elseif win=='4.00.1381' then - winver='NT 4.0' - elseif win=='4.10.1998' then - winver='98' - elseif win=='4.10.2222' then - winver='98 SE' - elseif win=='4.90.3000' then - winver='ME' - elseif win=='5.00.2195' then - winver='2000' - elseif win=='5.1.2600' then - winver='XP' - elseif win=='5.2.3790' then - winver='Server 2003' - elseif win=='6.0.6000' then - winver='Vista/Windows Server 2008' - elseif win=='6.0.6002' then - winver='Vista SP2' - elseif win=='6.1.7600' then - winver='7/Windows Server 2008 R2' - elseif win=='6.1.7601' then - winver='7 SP1/Windows Server 2008 R2 SP1' - elseif win=='6.2.9200' then - winver='8/Windows Server 2012' - elseif win=='6.3.9600' then - winver='8.1/Windows Server 2012' - elseif win=='6.4.9841' then - winver='10 Technical Preview 1' - elseif win=='6.4.9860' then - winver='10 Technical Preview 2' - elseif win=='6.4.9879' then - winver='10 Technical Preview 3' - elseif win=='10.0.9926' then - winver='10 Technical Preview 4' - end - return 'Windows '..winver -end -function os.capture(cmd, raw) - local f = assert(io.popen(cmd, 'r')) - local s = assert(f:read('*a')) - f:close() - if raw then return s end - s = string.gsub(s, '^%s+', '') - s = string.gsub(s, '%s+$', '') - s = string.gsub(s, '[\n\r]+', ' ') - return s -end -function io.scanDir(directory) - directory=directory or io.getDir() - local i, t, popen = 0, {}, io.popen - if os.getOS()=='unix' then - for filename in popen('ls -a "'..directory..'"'):lines() do - i = i + 1 - t[i] = filename - end - else - for filename in popen('dir "'..directory..'" /b'):lines() do - i = i + 1 - t[i] = filename - end - end - return t -end -function io.getDir(dir) - if not dir then return io.getWorkingDir() end - if os.getOS()=='unix' then - return os.capture('cd '..dir..' ; cd') - else - return os.capture('cd '..dir..' & cd') - end -end -function string.split(str, pat) - local t = {} -- NOTE: use {n = 0} in Lua-5.0 - local fpat = '(.-)' .. pat - local last_end = 1 - local s, e, cap = str:find(fpat, 1) - while s do - if s ~= 1 or cap ~= '' then - table.insert(t,cap) - end - last_end = e+1 - s, e, cap = str:find(fpat, last_end) - end - if last_end <= #str then - cap = str:sub(last_end) - table.insert(t, cap) - end - return t -end -function io.fileExists(path) - g=io.open(path or '','r') - if path =='' then - p='empty path' - return nil - end - if g~=nil and true or false then - p=(g~=nil and true or false) - end - if g~=nil then - io.close(g) - else - return false - end - return p -end -function io.getDirectories(dir,l) - if dir then - dir=dir..'\\' - else - dir='' - end - local temp2=io.scanDir(dir) - for i=#temp2,1,-1 do - if io.fileExists(dir..temp2[i]) then - table.remove(temp2,i) - elseif l then - temp2[i]=dir..temp2[i] - end - end - return temp2 -end -function io.getFiles(dir,l) - if dir then - dir=dir..'\\' - else - dir='' - end - local temp2=io.scanDir(dir) - for i=#temp2,1,-1 do - if io.dirExists(dir..temp2[i]) then - table.remove(temp2,i) - elseif l then - temp2[i]=dir..temp2[i] - end - end - return temp2 -end -function io.readFile(file) - local f = io.open(file, 'rb') - local content = f:read('*all') - f:close() - return content -end -function table.print(tbl, indent) - if not indent then indent = 0 end - for k, v in pairs(tbl) do - formatting = string.rep(' ', indent) .. k .. ': ' - if type(v) == 'table' then - print(formatting) - table.print(v, indent+1) - else - print(formatting .. tostring(v)) - end - end -end -function io.dirExists(strFolderName) - strFolderName = strFolderName or io.getDir() - local fileHandle, strError = io.open(strFolderName..'\\*.*','r') - if fileHandle ~= nil then - io.close(fileHandle) - return true - else - if string.match(strError,'No such file or directory') then - return false - else - return true - end - end -end -function io.getFullName(name) - local temp=name or arg[0] - if string.find(temp,'\\',1,true) or string.find(temp,'/',1,true) then - temp=string.reverse(temp) - a,b=string.find(temp,'\\',1,true) - if not(a) or not(b) then - a,b=string.find(temp,'/',1,true) - end - return string.reverse(string.sub(temp,1,b-1)) - end - return temp -end -function io.getName(file) - local name=io.getFullName(file) - name=string.reverse(name) - a,b=string.find(name,'.',1,true) - name=string.sub(name,a+1,-1) - return string.reverse(name) -end -function io.getPathName(path) - return path:sub(1,#path-#io.getFullName(path)) -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -function io.splitPath(str) - return string.split(str,'[\\/]+') -end -function io.pathToTable(path) - local p=io.splitPath(path) - local temp={} - temp[p[1]]={} - local last=temp[p[1]] - for i=2,#p do - snd=last - last[p[i]]={} - last=last[p[i]] - end - return temp,last,snd -end -function io.parseDir(dir,t) - io.tempFiles={} - function _p(dir) - local dirs=io.getDirectories(dir,true) - local files=io.getFiles(dir,true) - for i=1,#files do - p,l,s=io.pathToTable(files[i]) - if t then - s[io.getFullName(files[i])]=io.readFile(files[i]) - else - s[io.getFullName(files[i])]=io.open(files[i],'r+') - end - table.merge(io.tempFiles,p) - end - for i=1,#dirs do - table.merge(io.tempFiles,io.pathToTable(dirs[i])) - _p(dirs[i],t) - end - end - _p(dir) - return io.tempFiles -end -function io.parsedir(dir,f) - io.tempFiles={} - function _p(dir,f) - local dirs=io.getDirectories(dir,true) - local files=io.getFiles(dir,true) - for i=1,#files do - if not f then - table.insert(io.tempFiles,files[i]) - else - f(files[i]) - end - end - for i=1,#dirs do - _p(dirs[i],f) - end - end - _p(dir,f) - return io.tempFiles -end ---[[---------------------------------------- -Random -Not all of this is mine -------------------------------------------]] ---[[------------------------------------ -RandomLua v0.3.1 -Pure Lua Pseudo-Random Numbers Generator -Under the MIT license. -copyright(c) 2011 linux-man ---]]------------------------------------ - -local math_floor = math.floor - -local function normalize(n) --keep numbers at (positive) 32 bits - return n % 0x80000000 -end - -local function bit_and(a, b) - local r = 0 - local m = 0 - for m = 0, 31 do - if (a % 2 == 1) and (b % 2 == 1) then r = r + 2^m end - if a % 2 ~= 0 then a = a - 1 end - if b % 2 ~= 0 then b = b - 1 end - a = a / 2 b = b / 2 - end - return normalize(r) -end - -local function bit_or(a, b) - local r = 0 - local m = 0 - for m = 0, 31 do - if (a % 2 == 1) or (b % 2 == 1) then r = r + 2^m end - if a % 2 ~= 0 then a = a - 1 end - if b % 2 ~= 0 then b = b - 1 end - a = a / 2 b = b / 2 - end - return normalize(r) -end - -local function bit_xor(a, b) - local r = 0 - local m = 0 - for m = 0, 31 do - if a % 2 ~= b % 2 then r = r + 2^m end - if a % 2 ~= 0 then a = a - 1 end - if b % 2 ~= 0 then b = b - 1 end - a = a / 2 b = b / 2 - end - return normalize(r) -end - -local function seed() - --return normalize(tonumber(tostring(os.time()):reverse())) - return normalize(os.time()) -end - ---Mersenne twister -mersenne_twister = {} -mersenne_twister.__index = mersenne_twister - -function mersenne_twister:randomseed(s) - if not s then s = seed() end - self.mt[0] = normalize(s) - for i = 1, 623 do - self.mt[i] = normalize(0x6c078965 * bit_xor(self.mt[i-1], math_floor(self.mt[i-1] / 0x40000000)) + i) - end -end - -function mersenne_twister:random(a, b) - local y - if self.index == 0 then - for i = 0, 623 do - --y = bit_or(math_floor(self.mt[i] / 0x80000000) * 0x80000000, self.mt[(i + 1) % 624] % 0x80000000) - y = self.mt[(i + 1) % 624] % 0x80000000 - self.mt[i] = bit_xor(self.mt[(i + 397) % 624], math_floor(y / 2)) - if y % 2 ~= 0 then self.mt[i] = bit_xor(self.mt[i], 0x9908b0df) end - end - end - y = self.mt[self.index] - y = bit_xor(y, math_floor(y / 0x800)) - y = bit_xor(y, bit_and(normalize(y * 0x80), 0x9d2c5680)) - y = bit_xor(y, bit_and(normalize(y * 0x8000), 0xefc60000)) - y = bit_xor(y, math_floor(y / 0x40000)) - self.index = (self.index + 1) % 624 - if not a then return y / 0x80000000 - elseif not b then - if a == 0 then return y - else return 1 + (y % a) - end - else - return a + (y % (b - a + 1)) - end -end - -function twister(s) - local temp = {} - setmetatable(temp, mersenne_twister) - temp.mt = {} - temp.index = 0 - temp:randomseed(s) - return temp -end - ---Linear Congruential Generator -linear_congruential_generator = {} -linear_congruential_generator.__index = linear_congruential_generator - -function linear_congruential_generator:random(a, b) - local y = (self.a * self.x + self.c) % self.m - self.x = y - if not a then return y / 0x10000 - elseif not b then - if a == 0 then return y - else return 1 + (y % a) end - else - return a + (y % (b - a + 1)) - end -end - -function linear_congruential_generator:randomseed(s) - if not s then s = seed() end - self.x = normalize(s) -end - -function lcg(s, r) - local temp = {} - setmetatable(temp, linear_congruential_generator) - temp.a, temp.c, temp.m = 1103515245, 12345, 0x10000 --from Ansi C - if r then - if r == 'nr' then temp.a, temp.c, temp.m = 1664525, 1013904223, 0x10000 --from Numerical Recipes. - elseif r == 'mvc' then temp.a, temp.c, temp.m = 214013, 2531011, 0x10000 end--from MVC - end - temp:randomseed(s) - return temp -end - --- Multiply-with-carry -multiply_with_carry = {} -multiply_with_carry.__index = multiply_with_carry - -function multiply_with_carry:random(a, b) - local m = self.m - local t = self.a * self.x + self.c - local y = t % m - self.x = y - self.c = math_floor(t / m) - if not a then return y / 0x10000 - elseif not b then - if a == 0 then return y - else return 1 + (y % a) end - else - return a + (y % (b - a + 1)) - end -end - -function multiply_with_carry:randomseed(s) - if not s then s = seed() end - self.c = self.ic - self.x = normalize(s) -end - -function mwc(s, r) - local temp = {} - setmetatable(temp, multiply_with_carry) - temp.a, temp.c, temp.m = 1103515245, 12345, 0x10000 --from Ansi C - if r then - if r == 'nr' then temp.a, temp.c, temp.m = 1664525, 1013904223, 0x10000 --from Numerical Recipes. - elseif r == 'mvc' then temp.a, temp.c, temp.m = 214013, 2531011, 0x10000 end--from MVC - end - temp.ic = temp.c - temp:randomseed(s) - return temp -end --- Little bind for the methods: My code starts -randomGen={} -randomGen.__index=randomGen -function randomGen:new(s) - local temp={} - setmetatable(temp,randomGen) - temp[1]=twister() - temp[2]=lcg() - temp[3]=mwc() - temp.pos=1 - for i=1,3 do - temp[i]:randomseed(s) - end - return temp -end -function randomGen:randomseed(s) - self.pos=1 - self[1]:randomseed(s) - self[2]:randomseed(s) - self[3]:randomseed(s) -end -function randomGen:randomInt(a,b) - local t=self[self.pos]:random(a,b) - self.pos=self.pos+1 - if self.pos>3 then - self.pos=1 - end - return t -end -function randomGen:newND(a,b,s) - if not(a) or not(b) then error('You must include a range!') end - local temp=randomGen:new(s) - temp.a=a - temp.b=b - temp.range=b-a+1 - temp.dups={no=0} - function temp:nextInt() - local t=self:randomInt(self.a,self.b) - if self.dups[t]==nil then - self.dups[t]=true - self.dups.no=self.dups.no+1 - else - return self:nextInt() - end - if self.dups.no==self.range then - function self:nextInt() - return 1,true - end - return t - else - return t - end - end - function temp:nextIInt() - return function() return self:nextInt() end - end - return temp -end -lzw = {} -function lzw.encode(uncompressed) -- string - local dictionary, result, dictSize, w, c = {}, {}, 255, "" - for i = 0, 255 do - dictionary[string.char(i)] = i - end - for i = 1, #uncompressed do - c = string.sub(uncompressed, i, i) - if dictionary[w .. c] then - w = w .. c - else - table.insert(result, dictionary[w]) - dictSize = dictSize + 1 - dictionary[w .. c] = dictSize - w = c - end - end - if w ~= "" then - table.insert(result, dictionary[w]) - end - return result -end - -function lzw.decode(compressed) -- table - local dictionary, dictSize, entry, result, w, k = {}, 255, "", "", "" - for i = 0, 255 do - dictionary[i] = string.char(i) - end - for i = 1, #compressed do - k = compressed[i] - if dictionary[k] then - entry = dictionary[k] - elseif k == dictSize then - entry = w .. string.sub(w, 1, 1) - else - return nil, i - end - result = result .. entry - dictionary[dictSize] = w .. string.sub(entry, 1, 1) - dictSize = dictSize + 1 - w = entry - end - return result -end ---[[---------------------------------------- -BIN -------------------------------------------]] - -function bin:newSink() - local c={} - c.data={} - c.name="sinkobj" - c.num=1 - c.type="sink" - function c:tackE(data) - self.data[self.num]=data - self.num=self.num+1 - end - function c:tofile(path) - bin.new(table.concat(self.data)):tofile(path) - end - function c:getData() - return table.concat(self.data) - end - function c:reset() - self.data={} - end - function c:close() - -- does nothing lol - end - return c -end -function bin:segmentedRead(size,func) - local mSize=self:getSize() - local pSize=size - local iter=math.ceil(mSize/pSize) - for i=0,iter-1 do - func(self:sub((i*pSize)+1,(i+1)*pSize)) - end -end -function bin.compress(uncomp,n) - n=n or 9 - local cipher = lzw.encode(uncomp) - local dat={} - for i=1,#cipher do - local fix=bits.new(cipher[i]).data:match("0*(%d+)") - if cipher[i]==0 then - fix=string.rep("0",n) - end - fix=string.rep("0",n-#fix)..fix - table.insert(dat,fix) - end - str=table.concat(dat,"") - str=string.rep("0",8-#str%8)..str - comp={} - for i=0,(#str/8) do - table.insert(comp,bits.new(str:sub(i*8+1,i*8+8)):toSbytes()) - end - return table.concat(comp,"") -end -function bin.decompress(comp,n) - n=n or 9 - local tab={} - for i=1,#comp do - table.insert(tab,bits.new(comp:sub(i,i)).data) - end - tab=table.concat(tab,"") - tab=tab:match("0*(%d+)") - tab=string.rep("0",n-#tab%n)..tab - uncomp={} - for i=0,(#tab/n) do - table.insert(uncomp,tonumber(tab:sub(i*n+1,i*n+n),2)) - end - return lzw.decode(uncomp) -end -function bin:getSize() - return self:getlength() -end -function bin.getVersion() - return bin.Version[1]..'.'..bin.Version[2]..'.'..bin.Version[3] -end -function bin:gsub(...) - self.data=self.data:gsub(...) -end --- -function bin:trim() - self.data=self.data:match'^()%s*$' and '' or self.data:match'^%s*(.*%S)' -end -function bin._trim(str) - return str:match'^()%s*$' and '' or str:match'^%s*(.*%S)' -end -function bin:fullTrim(empty) - local t=self:lines() - for i=#t,1,-1 do - t[i]=bin._trim(t[i]) - if empty then - if t[i]=="" then - table.remove(t,i) - end - end - end - self.data = table.concat(t,"\n") -end -function bin:lines() - local t = {} - local function helper(line) table.insert(t, line) return '' end - helper((self.data:gsub('(.-)\r?\n', helper))) - return t -end -function bin._lines(str) - local t = {} - local function helper(line) table.insert(t, line) return '' end - helper((str:gsub('(.-)\r?\n', helper))) - return t -end --- -function bin:find(...) - return self.data:find(...) -end -function bin.fromhex(str) - return (str:gsub('..', function (cc) - return string.char(tonumber(cc, 16)) - end)) -end - --- working lua base64 codec (c) 2006-2008 by Alex Kloss --- compatible with lua 5.1 --- http://www.it-rfc.de --- licensed under the terms of the LGPL2 -bin.base64chars = {[0]='A',[1]='B',[2]='C',[3]='D',[4]='E',[5]='F',[6]='G',[7]='H',[8]='I',[9]='J',[10]='K',[11]='L',[12]='M',[13]='N',[14]='O',[15]='P',[16]='Q',[17]='R',[18]='S',[19]='T',[20]='U',[21]='V',[22]='W',[23]='X',[24]='Y',[25]='Z',[26]='a',[27]='b',[28]='c',[29]='d',[30]='e',[31]='f',[32]='g',[33]='h',[34]='i',[35]='j',[36]='k',[37]='l',[38]='m',[39]='n',[40]='o',[41]='p',[42]='q',[43]='r',[44]='s',[45]='t',[46]='u',[47]='v',[48]='w',[49]='x',[50]='y',[51]='z',[52]='0',[53]='1',[54]='2',[55]='3',[56]='4',[57]='5',[58]='6',[59]='7',[60]='8',[61]='9',[62]='-',[63]='_'} -function bin.tob64(data) - local bytes = {} - local result = "" - for spos=0,string.len(data)-1,3 do - for byte=1,3 do bytes[byte] = string.byte(string.sub(data,(spos+byte))) or 0 end - result = string.format('%s%s%s%s%s',result,bin.base64chars[bits.rsh(bytes[1],2)],bin.base64chars[bits.lor(bits.lsh((bytes[1] % 4),4), bits.rsh(bytes[2],4))] or "=",((#data-spos) > 1) and bin.base64chars[bits.lor(bits.lsh(bytes[2] % 16,2), bits.rsh(bytes[3],6))] or "=",((#data-spos) > 2) and bin.base64chars[(bytes[3] % 64)] or "=") - end - return result -end -bin.base64bytes = {['A']=0,['B']=1,['C']=2,['D']=3,['E']=4,['F']=5,['G']=6,['H']=7,['I']=8,['J']=9,['K']=10,['L']=11,['M']=12,['N']=13,['O']=14,['P']=15,['Q']=16,['R']=17,['S']=18,['T']=19,['U']=20,['V']=21,['W']=22,['X']=23,['Y']=24,['Z']=25,['a']=26,['b']=27,['c']=28,['d']=29,['e']=30,['f']=31,['g']=32,['h']=33,['i']=34,['j']=35,['k']=36,['l']=37,['m']=38,['n']=39,['o']=40,['p']=41,['q']=42,['r']=43,['s']=44,['t']=45,['u']=46,['v']=47,['w']=48,['x']=49,['y']=50,['z']=51,['0']=52,['1']=53,['2']=54,['3']=55,['4']=56,['5']=57,['6']=58,['7']=59,['8']=60,['9']=61,['-']=62,['_']=63,['=']=nil} -function bin.fromb64(data) - local chars = {} - local result="" - for dpos=0,string.len(data)-1,4 do - for char=1,4 do chars[char] = bin.base64bytes[(string.sub(data,(dpos+char),(dpos+char)) or "=")] end - result = string.format('%s%s%s%s',result,string.char(bits.lor(bits.lsh(chars[1],2), bits.rsh(chars[2],4))),(chars[3] ~= nil) and string.char(bits.lor(bits.lsh(chars[2],4), bits.rsh(chars[3],2))) or "",(chars[4] ~= nil) and string.char(bits.lor(bits.lsh(chars[3],6) % 192, (chars[4]))) or "") - end - return result -end --- ^^ - -function bin:getB64() - return bin.tob64(self.data) -end -if table.unpack==nil then - table.unpack=unpack -end -function bin.tohex(str) - return (str:gsub('.', function (c) - return string.format('%02X', string.byte(c)) - end)) -end -function bin:streamData(a,b) - if type(a)=='table' then - a,b,t=table.unpack(a) - end - if type(a)=='number' and type(b)=='string' then - return bin.load(self.file,a,b),bin.load(self.file,a,b).data - else - error('Invalid args!!! Is do you have a valid stream handle or is this a streamable object?') - end -end -function bin.new(data,hex,b64) - data=data or "" - data=tostring(data) - local c = {} - setmetatable(c, bin) - if string.sub(data,1,2)=='0x' and hex then - data=string.sub(data,3) - data=bin.fromhex(data) - elseif hex then - data=bin.fromhex(data) - end - if b64 then - data=bin.fromb64(data) - end - c.data=data - c.t='bin' - c.Stream=false - return c -end -function bin.freshStream(file) - bin.new():tofile(file) - return bin.stream(file,false) -end -function bin.stream(file,l) - local c=bin.new() - if bin.streams[file]~=nil then - c.file=file - c.lock = l - c.workingfile=bin.streams[file].workingfile - c.Stream=true - return c - end - if bin.fileExist(file) then - c.file=file - c.lock = l - c.workingfile=io.open(file,'rb+') - else - c.file=file - c.lock = l - c.workingfile=io.open(file,'w') - io.close(c.workingfile) - c.workingfile=io.open(file,'rb+') - end - c.Stream=true - bin.streams[file]=c - return c -end -function bin:streamwrite(d,n) - if self:canStreamWrite() then - if n then - self.workingfile:seek('set',n) - else - self.workingfile:seek('set',self.workingfile:seek('end')) - end - self.workingfile:write(d) - end -end -function bin:streamread(a,b) - a=a-1 - local loc=self.workingfile:seek('cur') - self.workingfile:seek('set',a) - local dat=self.workingfile:read(b-a) - self.workingfile:seek('set',loc) - return dat -end -function bin:streamreadNext(a) - return self.workingfile:read(a) -end -function bin:close() - if self:canStreamWrite() then - self.workingfile:close() - end -end -function bin:flush() - if self:canStreamWrite() then - self.workingfile:flush() - else - self:tofile(self.filepath) - end -end -function bin:open() - if self:canStreamWrite() then - self.workingfile=io.open(self.file,'r+') - end -end -function bin:canStreamWrite() - return (self.Stream==true and self.lock==false) -end -function bin:getDataBuffer(a,b,filler) - if self:canStreamWrite() then - if not(a) and not(b) then - a=1 - b=math.huge - elseif a and not(b) then - b=a - a=1 - if self:getSize()=k then - me:streamwrite(string.char(v),k+(ss-1)) - elseif type(v)=="string" and s>=k then - if #v~=1 then - t:fillBuffer(v,k+(ss)) - elseif s>=k then - me:streamwrite(v,k+(ss-1)) - else - print("Buffer Overflow!") - end - else - print("Warning Attempting to index outside defined range!") - end - end, - __tostring=function(t) -- GOOD - return t:getBuffer() - end - } - c.t="buffer" - c.dataS={} - function c:getBuffer(a,b) -- GOOD - if not(a) and not(b) then - local str={} - for i=ss,max do - table.insert(str,me:streamread(i+(ss-1),i+(ss-1))) - end - return table.concat(str) - else - return me:streamread(a+(ss-1),b+(ss-1)) - end - end - function c:getData() -- GOOD - return self:getBuffer() - end - function c:getBufferTable() -- GOOD - local str={} - for i=ss,max do - table.insert(str,me:streamread(i+(ss-1),i+(ss-1))) - end - return str - end - function c:getBufferSize() -- GOOD - return #self:getBuffer() - end - function c:getlength() -- GOOD - return #self:getBuffer() - end - function c:tonumber(a,b) -- GOOD - return bin.new(self:getBuffer(a,b)):tonumber() - end - c.getSize=c.getlength - function c:fillBuffer(sg,a) -- GOOD - for i=#sg+(a-1),a,-1 do - if i<=max then - local ii=(a+#sg)-i - self[ii+(a-1)]=sg:sub(ii,ii) - else - return print("Buffer Overflow!") - end - end - return a,a+#sg-1 - end - setmetatable(c,mt) - return c - else - error("Stream not opened for writing!") - end -end -function bin.load(file,s,r) - if not(s) or not(r) then - if type(file)~="string" then return bin.new() end - local f = io.open(file, 'rb') - local content = f:read('*a') - f:close() - return bin.new(content) - end - s=s or 0 - r=r or -1 - if type(r)=='number' then - r=r+s-1 - elseif type(r)=='string' then - r=tonumber(r) or -1 - end - local f = io.open(file, 'rb') - f:seek('set',s) - local content = f:read((r+1)-s) - f:close() - local temp=bin.new(content) - temp.filepath=file - return temp -end -function bin:tofile(filename) - if not(filename) or self.Stream then return nil end - io.mkFile(filename,self.data) -end -function bin.trimNul(s) - for i=1,#s do - if s:sub(i,i)=='\0' then - return s:sub(1,i-1) - end - end - return s -end -function bin:match(pat) - return self.data:match(pat) -end -function bin:gmatch(pat) - return self.data:gmatch(pat) -end -function bin:getHash(n) - if self:getlength()==0 then - return "NaN" - end - n=(n or 32)/2 - local rand = randomGen:newND(1,self:getlength(),self:getlength()) - local h,g={},0 - for i=1,n do - g=rand:nextInt() - table.insert(h,bin.tohex(self:sub(g,g))) - end - return table.concat(h,'') -end -function bin:getRandomHash(n) - if self:getlength()==0 then - return "NaN" - end - n=(n or 32)/2 - local rand = randomGen:new(math.random(1,self:getlength()^2)) - local h,g={},0 - for i=1,n do - g=rand:randomInt(1,self:getlength()) - table.insert(h,bin.tohex(self:sub(g,g))) - end - return table.concat(h,'') -end -function bin:newDataBuffer(s,def) - local c={} - local mt={ - __index=function(t,k,v) - if k<=t.maxBuffer then - if t.dataS[k] then - return string.byte(t.dataS[k]) - else - return "NOINDEX" - end - else - return - end - end, - __newindex=function(t,k,v) - if type(v)=="number" and t.maxBuffer>=k then - t.dataS[k]=string.char(v) - elseif type(v)=="string" and t.maxBuffer>=k then - if #v~=1 then - t:fillBuffer(v,k) - elseif t.maxBuffer>=k then - t.dataS[k]=v - else - print("Buffer Overflow!") - end - end - end, - __tostring=function(t) - return t:getBuffer() - end - } - c.t="buffer" - c.dataS={} - if s then - if type(s)=="number" then - c.maxBuffer=s - s=string.rep(def or"\0",s) - else - c.maxBuffer=math.huge - end - for i=1,#s do - c.dataS[i]=s:sub(i,i) - end - else - c.maxBuffer=math.huge - end - function c:getBuffer(a,b) - if a and b then - return table.concat(self.dataS,""):sub(a,b) - else - return table.concat(self.dataS,"") - end - end - function c:getData() - return table.concat(self.dataS,"") - end - function c:getBufferTable() - return self.dataS - end - function c:getBufferSize() - if self.maxBuffer~=math.huge then - return self.maxBuffer - end - return #self:getBuffer() - end - function c:getlength() - return #self:getBuffer(a,b) - end - function c:tonumber(a,b) - return bin.new(self:getBuffer(a,b)):tonumber() - end - c.getSize=c.getlength - function c:fillBuffer(s,a) - for i=0,#s-1 do - if i+a<=self.maxBuffer then - c.dataS[i+a]=s:sub(i+1,i+1) - else - return "Buffer Overflow!" - end - end - return a,a+#s-1 - end - setmetatable(c,mt) - return c -end -function bin:getHash2(h,n) - n=n or 1024 - h=(h or 32) - local temp=bin.new() - local len=self:getSize() - local seg=math.ceil(len/n) - temp:fill("\0",h) - for i=1,seg do - local s=bin.new(self:sub(n*(i-1)+1,n*i)):getHash(h) - for i=1,h do - temp:shiftbit(string.byte(s:sub(i,i)),i) - end - end - return temp:getHEX() -end -function bin.encryptA(data,seed) - seed=seed or 1 - local d=bin.new(data) - local r=randomGen:newND(1,#d.data,seed) - for i=1,#d.data do - d:shiftbit(r:nextInt(),i) - end - return bin.tohex(d.data) -end -function bin.decryptA(data,seed) - seed=seed or 1 - local d=bin.new('0x'..data) - local r=randomGen:newND(1,#d.data,seed) - for i=1,#d.data do - d:shiftbit(-r:nextInt(),i) - end - return d.data -end -function bin.encryptB(data,seed) - seed=seed or 'abcdefghijklmnopqrstuvwxyz' - seed=tostring(seed) - local d=bin.new(data) - local r,mr=1,#seed - for i=1,#d.data do - d:shiftbit(string.byte(seed:sub(r,r)),i) - r=r+1 - if r>mr then - r=1 - end - end - return bin.tohex(d.data) -end -function bin.decryptB(data,seed) - seed=seed or 'abcdefghijklmnopqrstuvwxyz' - seed=tostring(seed) - local d=bin.new('0x'..data) - local r,mr=1,#seed - for i=1,#d.data do - d:shiftbit(-string.byte(seed:sub(r,r)),i) - r=r+1 - if r>mr then - r=1 - end - end - return d.data -end -function bin:encrypt(seed) - seed=seed or 'abcdefghijklmnopqrstuvwxyz' - seed=tostring(seed) - local r,mr=1,#seed - for i=1,self:getlength() do - self:shiftbit(string.byte(seed:sub(r,r)),i) - r=r+1 - if r>mr then - r=1 - end - end -end -function bin:decrypt(seed) - seed=seed or 'abcdefghijklmnopqrstuvwxyz' - seed=tostring(seed) - local r,mr=1,#seed - for i=1,self:getlength() do - self:shiftbit(-string.byte(seed:sub(r,r)),i) - r=r+1 - if r>mr then - r=1 - end - end -end -function bin.randomName(n,ext) - n=n or math.random(7,15) - if ext then - a,b=ext:find('.',1,true) - if a and b then - ext=ext:sub(2) - end - end - local str,h = '',0 - strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'} - for i=1,n do - h = math.random(1,#strings) - str = str..''..strings[h] - end - return str..'.'..(ext or 'tmp') -end -function bin.newTempFile(data) - data=data or '' - local name=bin.randomName() - bin.new():tofile(name) - local tempfile=bin.stream(name,false) - tempfile:streamwrite(data,0) - tempfile:setEndOfFile(#data) - return tempfile -end -function bin:wipe() - if self:canStreamWrite() then - self:close() - os.remove(self.file) - self:open() - else - self.data='' - end -end -function bin:setEndOfFile(n) - if self:canStreamWrite() then - local name=bin.randomName() - local tempfile=bin.stream(name,false) - tempfile:streamwrite(self:sub(0,n-1)) - self:close() - os.remove(self.file) - tempfile:close() - os.rename(name,self.file) - self:open() - tempfile=nil - else - self.data=self.data:sub(1,n) - end -end -function bin:reverse() - if self:canStreamWrite() then - local x,f,b=self:getlength(),0,0 - for i=0,math.floor((x-1)/2) do - self:streamwrite(self:sub(i+1,i+1),x-i-1) - self:streamwrite(self:sub(x-i,x-i),i) - end - elseif self.Stream==false then - self.data=string.reverse(self.data) - end -end -function bin:flipbits() - if self:canStreamWrite() then - for i=0,self:getlength()-1 do - self:streamwrite(string.char(255-string.byte(self:streamread(i,i))),i) - end - elseif self.Stream==false then - local temp={} - for i=1,#self.data do - table.insert(temp,string.char(255-string.byte(string.sub(self.data,i,i)))) - end - self.data=table.concat(temp,'') - end -end -function bin:flipbit(i) - if self:canStreamWrite() then - self:streamwrite(string.char(255-string.byte(self:streamread(i-1,i-1))),i-1) - elseif self.Stream==false then - self:mutate(string.char(255-string.byte(string.sub(self.data,i,i))),i) - end -end -function bin:segment(a,b) -- needs to be updated!!! - if self:canStreamWrite() then - --[[local pos=1 - for i=a,b do - self:streamwrite(self:sub(i,i),b-a-i) - end]] - local temp=self:sub(a,b) - self:close() - local f=io.open(self.file,'w') - f:write(temp) - io.close(f) - self:open() - elseif self.Stream==false then - self.data=string.sub(self.data,a,b) - end -end -function bin:insert(i,a) - if self:canStreamWrite() then - -- do something - elseif self.Stream==false then - if type(i)=='number' then i=string.char(i) end - self.data=string.sub(self.data,1,a)..i..string.sub(self.data,a+1) - end -end -function bin:parseN(n) - if self:canStreamWrite() then - -- do something - elseif self.Stream==false then - local temp={} - for i=1,#self.data do - if i%n==0 then - table.insert(temp,string.sub(self.data,i,i)) - end - end - self.data=table.concat(temp,'') - end -end -function bin:parse(n,f) - local f = f - local n=n or 1 - if not(f) then return end - for i=1,self:getlength() do - if i%n==0 then - f(i,self,self:sub(i,i)) - end - end -end -function bin.copy(file,tofile,s) - if not(s) then - bin.load(file):tofile(tofile) - else - rf=bin.stream(file) - wf=bin.stream(tofile,false) - for i=1,rf:getlength(),s do - wf:streamwrite(rf:sub(i,i-1+s)) - end - end -end -function bin:getlength() - if self.Stream then - if self.workingfile==nil then print("Error getting size of file!") return 0 end - local current = self.workingfile:seek() -- get current position - local size = self.workingfile:seek('end') -- get file size - self.workingfile:seek('set', current) -- restore position - return size - elseif self.Stream==false then - return #self.data - end -end -function bin:sub(a,b) - if self.Stream then - return bin.load(self.file,a-1,tostring(b-1)).data - elseif self.Stream==false then - return string.sub(self.data,a,b) - end -end -function bin:tackB(d) - if self:canStreamWrite() then - -- do something don't know if possible - elseif self.Stream==false then - self.data=d..self.data - end -end -function bin:tackE(d) - if type(d)=='table' then - if d:canStreamWrite() then - d=d:sub(1,d:getlength()) - else - d=d.data - end - return - end - if self:canStreamWrite() then - self:streamwrite(d) - elseif self.Stream==false then - self.data=self.data..d - end -end -function bin:clone(filename) - if self:canStreamWrite() then - -- do something - elseif self.Stream==false then - return bin.new(self.data) - end -end -function bin.closeto(a,b,v) - if self:canStreamWrite() then - -- do something - elseif self.Stream==false then - if type(a)~=type(b) then - error('Attempt to compare unlike types') - elseif type(a)=='number' and type(b)=='number' then - return math.abs(a-b)<=v - elseif type(a)=='table' and type(b)=='table' then - if a.data and b.data then - return (math.abs(string.byte(a.data)-string.byte(b.data)))<=v - else - error('Attempt to compare non-bin data') - end - elseif type(a)=='string' and type(b)=='string' then - return math.abs(string.byte(a)-string.byte(b))<=v - else - error('Attempt to compare non-bin data') - end - end -end -function bin:compare(_bin,t) - if self:canStreamWrite() then - -- do something - elseif self.Stream==false then - t=t or 1 - local tab={} - local a,b=self:getlength(),_bin:getlength() - if not(a==b) then - print('Unequal Lengths!!! Equalizing...') - if a>b then - _bin.data=_bin.data..string.rep(string.char(0),a-b) - else - self.data=self.data..string.rep(string.char(0),b-a) - end - end - if t==1 then - for i=1,self:getlength() do - table.insert(tab,self:sub(i,i)==_bin:sub(i,i)) - end - else - for i=1,self:getlength() do - table.insert(tab,bin.closeto(self:sub(i,i),_bin:sub(i,i),t)) - end - end - local temp=0 - for i=1,#tab do - if tab[i]==true then - temp=temp+1 - end - end - return (temp/#tab)*100 - end -end -function bin:shift(n) - if self:canStreamWrite() then - local a,b,x,p='','',self:getlength(),0 - for i=1,x do - if i+n>x then - p=(i+n)-(x) - else - p=i+n - end - end - elseif self.Stream==false then - n=n or 0 - local s=#self.data - if n>0 then - self.data = string.sub(self.data,s-n+1)..string.sub(self.data,1,s-n) - elseif n<0 then - n=math.abs(n) - self.data = string.sub(self.data,n+1)..string.sub(self.data,1,n*1) - end - end -end -function bin:delete(a,b) - if self:canStreamWrite() then - -- do something - elseif self.Stream==false then - if type(a)=='string' then - local tab={} - for i=1,self:getlength() do - if self:getbyte(i)~=string.byte(a) then - table.insert(tab,self:sub(i,i)) - end - end - self.data=table.concat(tab) - elseif a and not(b) then - self.data=self:sub(1,a-1)..self:sub(a+1) - elseif a and b then - self.data=self:sub(1,a-1)..self:sub(b+1) - else - self.data='' - end - end -end -function bin:tonumber(a,b) - local temp={} - if a then - temp.data=self:sub(a,b) - else - temp=self - end - local l,r=0,0 - local g=#temp.data - for i=1,g do - r=r+(256^(g-i))*string.byte(string.sub(temp.data,i,i)) - l=l+(256^(i-1))*string.byte(string.sub(temp.data,i,i)) - end - return r,l -end -function bin:getbyte(n) - return string.byte(self:sub(n,n)) -end -function bin:shuffle(s) - if self:canStreamWrite() then - -- do something - elseif self.Stream==false then - s=tonumber(s) or 4546 - math.randomseed(s) - local t={} - for i=1,self:getlength() do - table.insert(t,self:sub(i,i)) - end - local n = #t - while n >= 2 do - local k = math.random(n) - t[n], t[k] = t[k], t[n] - n = n - 1 - end - self.data=table.concat(t) - end -end -function bin:tobits(i) - return bits.new(self:getbyte(i)) -end -function bin:mutate(a,i) - if self:canStreamWrite() then - self:streamwrite(a,i-1) - elseif self.Stream==false then - self:delete(i) - self:insert(a,i-1) - end -end -function bin:parseA(n,a,t) - if self:canStreamWrite() then - -- do something - elseif self.Stream==false then - local temp={} - for i=1,#self.data do - if i%n==0 then - if t then - table.insert(temp,a) - table.insert(temp,string.sub(self.data,i,i)) - else - table.insert(temp,string.sub(self.data,i,i)) - table.insert(temp,a) - end - else - table.insert(temp,string.sub(self.data,i,i)) - end - end - self.data=table.concat(temp,'') - end -end -function bin:merge(o,t) - if self:canStreamWrite() then - self:close() - self.workingfile=io.open(self.file,'a+') - self.workingfile:write(o.data) - self:close() - self:open() - elseif self.Stream==false then - if not(t) then - self.data=self.data..o.data - else - seld.data=o.data..self.data - end - end -end -function bin:cryptM() - self:flipbits() - self:reverse() -end -function bin.escapeStr(str) - local temp='' - for i=1,#str do - temp=temp..'\\'..string.byte(string.sub(str,i,i)) - end - return temp -end - -function bin.ToStr(val, name, skipnewlines, depth) - skipnewlines = skipnewlines or false - depth = depth or 0 - local tmp = string.rep(" ", depth) - if name then - if type(name) == "string" then - tmp = tmp .. "[\""..name.."\"] = " - else - tmp = tmp .. "["..(name or "").."] = " - end - end - if type(val) == "table" then - tmp = tmp .. "{" .. (not skipnewlines and " " or "") - for k, v in pairs(val) do - tmp = tmp .. bin.ToStr(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and " " or "") - end - tmp = tmp .. string.rep(" ", depth) .. "}" - elseif type(val) == "number" then - tmp = tmp .. tostring(val) - elseif type(val) == "string" then - tmp = tmp .. string.format("%q", val) - elseif type(val) == "boolean" then - tmp = tmp .. (val and "true" or "false") - else - tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\"" - end - return tmp -end -function bin:addBlock(d,n,e) - local temp={} - if type(d)=='table' then - if d.t=='bin' then - temp=d - elseif d.t=='bit' then - temp=bin.new(d:tobytes()) - else - self:addBlock('return '..bin.ToStr(d)) - return - end - elseif type(d)=='string' then - temp=bin.new(d) - if e or not(n) then - temp.data=temp.data..'_EOF' - temp:flipbits() - end - elseif type(d)=='function' then - temp=bin.new(string.dump(d)) - if e or not(n) then - temp.data=temp.data..'_EOF' - temp:flipbits() - end - elseif type(d)=='number' then - local nn=tostring(d) - if nn:find('.',1,true) then - temp=bin.new(nn) - temp.data=temp.data..'_EOF' - temp:flipbits() - else - temp=bits.new(d):tobytes() - if not n then - temp.data=temp.data..'_EOF' - temp:flipbits() - end - end - elseif type(d)=='boolean' then - n=1 - if d then - temp=bits.new(math.random(0,127)):tobytes() - else - temp=bits.new(math.random(128,255)):tobytes() - end - end - if n then - if temp:getlength()n then - temp:segment(1,n) - end - end - self:merge(temp) -end -function bin:getBlock(t,n,se) - if not(self.Block) then - self.Block=1 - end - local x=self.Block - local temp=bin.new() - if n then - temp=bin.new(self:sub(x,x+n-1)) - self.Block=self.Block+n - end - if se then - self.Block=self.Block+se - end - if t=='stringe' or t=='stre' or t=='se' and n then - temp:flipbits() - bin.lastBlockSize=#temp - return temp.data - elseif t=='string' or t=='str' or t=='s' and n then - bin.lastBlockSize=#temp - return temp.data - elseif t=='number' or t=='num' or t=='n' and n then - bin.lastBlockSize=n - return self:tonumber(x,x+n-1) - elseif t=='boolean' or t=='bool' or t=='b' then - self.Block=self.Block+1 - bin.lastBlockSize=1 - return self:tonumber(x,x)<127 - elseif t=='stringe' or t=='stre' or t=='se' or t=='string' or t=='str' or t=='s' then - local a,b=self:scan('_EOF',self.Block,true) - if not(b) then return nil end - local t=bin.new(self:sub(self.Block,b-4)) - bin.lastBlockSize=t:getlength() - t:flipbits() - self.Block=self.Block+t:getlength()+4 - return tostring(t) - elseif t=='table' or t=='tab' or t=='t' then - temp=self:getBlock('s') - bin.lastBlockSize=#temp - return assert(loadstring(temp))() - elseif t=='function' or t=='func' or t=='f' then - local temp=self:getBlock('s') - bin.lastBlockSize=#temp - return assert(loadstring(temp)) - elseif t=='number' or t=='num' or t=='n' then - local num=bin.new(self:getBlock('s')) - bin.lastBlockSize=#num - if tonumber(num.data) then - return tonumber(num.data) - end - local a,b=num:tonumber() - return a - elseif n then - -- C data - else - print('Invalid Args!!!') - end -end -function bin:seek(n) - self.Block=self.Block+n -end -function bin.NumtoHEX(num) - local hexstr = '0123456789ABCDEF' - local s = '' - while num > 0 do - local mod = math.fmod(num, 16) - s = string.sub(hexstr, mod+1, mod+1) .. s - num = math.floor(num / 16) - end - if s == '' then - s = '0' - end - return s -end -function bin:getHEX(a,b,e) - a=a or 1 - local temp = self:sub(a,b) - if e then temp=string.reverse(temp) end - return bin.tohex(temp) -end -function bin.HEXtoBin(hex,e) - if e then - return bin.new(string.reverse(bin.fromhex(hex))) - else - return bin.new(bin.fromhex(hex)) - end -end -function bin.HEXtoStr(hex,e) - if e then - return string.reverse(bin.fromhex(hex)) - else - return bin.fromhex(hex) - end -end -function bin:morph(a,b,d) - if self:canStreamWrite() then - local len=self:getlength() - local temp=bin.newTempFile(self:sub(b+1,self:getlength())) - self:streamwrite(d,a-1) - print(temp:sub(1,temp:getlength())) - self:setEndOfFile(len+(b-a)+#d) - self:streamwrite(temp:sub(1,temp:getlength()),a-1) - temp:remove() - elseif self.Stream==false then - if a and b then - self.data=self:sub(1,a-1)..d..self:sub(b+1) - else - print('error both arguments must be numbers and the third a string') - end - end -end -function bin.endianflop(data) - return string.reverse(data) -end -function bin:scan(s,n,f) - n=n or 1 - if self.Stream then - for i=n,self:getlength() do - if f then - local temp=bin.new(self:sub(i,i+#s-1)) - temp:flipbits() - if temp.data==s then - return i,i+#s-1 - end - else - if self:sub(i,i+#s-1)==s then - return i,i+#s-1 - end - end - end - elseif self.Stream==false then - if f then - s=bin.new(s) - s:flipbits() - s=s.data - end - n=n or 1 - local a,b=string.find(self.data,s,n,true) - return a,b - end -end -function bin:fill(s,n) - if self:canStreamWrite() then - self:streamwrite(string.rep(s,n),0) - self:setEndOfFile(n*#s) - elseif self.Stream==false then - self.data=string.rep(s,n) - end -end -function bin:fillrandom(n) - if self:canStreamWrite() then - local t={} - for i=1,n do - table.insert(t,string.char(math.random(0,255))) - end - self:streamwrite(table.concat(t),0) - self:setEndOfFile(n) - elseif self.Stream==false then - local t={} - for i=1,n do - table.insert(t,string.char(math.random(0,255))) - end - self.data=table.concat(t) - end -end -function bin.packLLIB(name,tab,ext) - local temp=bin.new() - temp:addBlock('') - temp:addBlock(bin.getVersion()) - temp:addBlock(tab) - for i=1,#tab do - temp:addBlock(tab[i]) - temp:addBlock(bin.load(tab[i]).data) - end - temp:addBlock('Done') - temp:tofile(name.. ('.'..ext or '.llib')) -end -function bin.unpackLLIB(name,exe,todir,over,ext) - local temp=bin.load(name..('.'..ext or '.llib')) - local name='' - Head=temp:getBlock('s') - ver=temp:getBlock('s') - infiles=temp:getBlock('t') - if ver~=bin.getVersion() then - print('Incompatable llib file') - return nil - end - local tab={} - while name~='Done' do - name,data=temp:getBlock('s'),bin.new(temp:getBlock('s')) - if string.find(name,'.lua',1,true) then - table.insert(tab,data.data) - else - if not(bin.fileExist((todir or '')..name) and not(over)) then - data:tofile((todir or '')..name) - end - end - end - os.remove((todir or '')..'Done') - if exe then - for i=1,#tab do - assert(loadstring(tab[i]))() - end - end - return infiles -end -function bin.fileExist(path) - g=io.open(path or '','r') - if path =='' then - p='empty path' - return nil - end - if g~=nil and true or false then - p=(g~=nil and true or false) - end - if g~=nil then - io.close(g) - else - return false - end - return p -end -function bin:shiftbits(n) - if self:canStreamWrite() then - n=n or 0 - if n>=0 then - for i=0,self:getlength() do - print(string.byte(self:sub(i,i))+n%256) - self:streamwrite(string.char(string.byte(self:sub(i,i))+n%256),i-1) - end - else - n=math.abs(n) - for i=0,self:getlength() do - self:streamwrite(string.char((string.byte(self:sub(i,i))+(256-n%256))%256),i-1) - end - end - elseif self.Stream==false then - n=n or 0 - if n>=0 then - for i=1,self:getlength() do - self:morph(i,i,string.char(string.byte(self:sub(i,i))+n%256)) - end - else - n=math.abs(n) - for i=1,self:getlength() do - self:morph(i,i,string.char((string.byte(self:sub(i,i))+(256-n%256))%256)) - end - end - end -end -function bin:shiftbit(n,i) - if self:canStreamWrite() then - i=i-1 - n=n or 0 - if n>=0 then - print((string.byte(self:sub(i,i))+n)%256,n) - self:streamwrite(string.char((string.byte(self:sub(i,i))+n)%256),i-1) - else - n=math.abs(n) - print((string.byte(self:sub(i,i))+(256-n))%256,n) - self:streamwrite(string.char((string.byte(self:sub(i,i))+(256-n%256))%256),i-1) - end - elseif self.Stream==false then - n=n or 0 - if n>=0 then - self:morph(i,i,string.char((string.byte(self:sub(i,i))+n)%256)) - else - n=math.abs(n) - self:morph(i,i,string.char((string.byte(self:sub(i,i))+(256-n%256))%256)) - end - end -end -function bin.decodeBits(par) - if type(par)=='table' then - if par.t=='bit' then - return bin.new(par:toSbytes()) - end - else - if par:find(' ') then - par=par:gsub(' ','') - end - local temp=bits.new() - temp.data=par - return bin.new((temp:toSbytes()):reverse()) - end -end -function bin.textToBinary(txt) - return bin.new(bits.new(txt:reverse()):getBin()) -end -function bin:getData() - if self.Stream then - return self:sub(1,self:getSize()) - else - return self.data - end -end -function bin.getLuaVersion() - if type(jit)=="table" then - if jit.version then - return "JIT",jit.version - end - end - return "PUC",_VERSION:match("(%d-)%.(%d+)") -end -function bin.binToBuffer(b) - return bin:newDataBuffer(b.data) -end -function bin.bufferToBin(b) - return bin.new(b:getBuffer()) -end -function bin.newNamedBlock(indexSize) - local c={} - c.data=bin.new() - c.lastLoc=0 - if indexSize then - indexSize=indexSize+4 - end - c.index=bin:newDataBuffer(indexSize) - c.conv={ - ["n"]="\1", - ["b"]="\2", - ["s"]="\3", - ["t"]="\4", - ["f"]="\5" - } - if indexSize then - c.index:fillBuffer(bits.numToBytes(indexSize,4),1) - c.lastLoc=4 - else - --c.index:fillBuffer(bits.numToBytes(2048,4),1) - end - function c:tofile(path) - bin.new(self:tostring()):tofile(path) - end - function c:tostring() - c.index:fillBuffer(bits.numToBytes(c.index:getSize()-4,4),1) - return self.index:getBuffer()..self.data.data - end - function c:setPointer(name,data,t) - t=c.conv[t] - data=t..data - local dSize=#data - local index=bin:newDataBuffer() - local nLen=#name - local test="" - index:fillBuffer(bits.numToBytes(self.data:getSize()+1,4),1) - index:fillBuffer(name,5) - self.data:tackE(data) - test=self.index:fillBuffer(index:getBuffer().."\31",self.lastLoc+1) - self.lastLoc=self.lastLoc+1+index:getBufferSize() - if test=="Buffer Overflow!" then - error("Increase Index size!") - end - end - function c:addNamedBlock(name,value) - local bSize=#name - local ftype={} - if type(value)=="number" then - local dat=bits.numToBytes(value,8) -- makes 64 bit version of lua compatable - self:setPointer(name,dat,"n") - elseif type(value)=="boolean" then - if value then - self:setPointer(name,"1","b") - else - self:setPointer(name,"0","b") - end - elseif type(value)=="string" then - self:setPointer(name,value,"s") - elseif type(value)=="table" then - local str=bin.ToStr(value) - self:setPointer(name,str,"t") - elseif type(value)=="function" then - local ver,verM,verm=bin.getLuaVersion() - local data=string.dump(value) - if ver=="JIT" then - ftype=bin:newDataBuffer(bits.numToBytes(0,4)) -- luajit version - else - ftype=bin:newDataBuffer(bits.numToBytes(tonumber(verM..verm),4)) -- lua version with MajorMinor data - end - local fdata=bin.new() - fdata:tackE(ftype:getBuffer()..data) - self:setPointer(name,fdata.data,"f") - elseif type(value)=="userdata" then - error("Userdata cannot be put into a block!") - end - end - if not indexSize then - c:addNamedBlock("__UNBOUNDEDINDEX__",true) - end - return c -end -function bin.newStreamedNamedBlock(indexSize,path,update) - local c={} - c.data=bin.stream(path,false) - c.lastLoc=4 - c.conv={ - ["n"]="\1", - ["b"]="\2", - ["s"]="\3", - ["t"]="\4", - ["f"]="\5" - } - if not update then - c.data:tackE(bin:newDataBuffer(indexSize+4 or 2052):getBuffer()) - if indexSize then - c.data:mutate(bits.numToBytes(indexSize,4),1) - else - c.data:mutate(bits.numToBytes(2048,4),1) - end - c.indexSize=indexSize+4 or 2052 - else - c.indexSize=c.data:tonumber(1,4) - local i=bin.new(c.data:sub(5,c.indexSize+4)).data - local last=0 - for b=#i,1,-1 do - if i:sub(b,b)=="\31" then - last=b+4 - break - end - end - c.lastLoc=last - end - function c:tofile(path) - --No need when using a streamed block - end - function c:tostring() - return self.index:getBuffer()..self.data.data - end - function c:setPointer(name,data,t) - t=c.conv[t] - data=t..data - local dSize=#data - local index=bin:newDataBuffer() - local nLen=#name - local test="" - index:fillBuffer(bits.numToBytes((self.data:getSize()+1)-self.indexSize,4),1) - index:fillBuffer(name,5) - local test=self.data:mutate(index:getBuffer().."\31",self.lastLoc+1) - self.lastLoc=self.lastLoc+1+index:getBufferSize() - self.data:tackE(data) - if test=="Buffer Overflow!" then - error("Increase Index size!") - end - end - function c:addNamedBlock(name,value) - local bSize=#name - local ftype={} - if type(value)=="number" then - local dat=bits.numToBytes(value,8) -- makes 64 bit version of lua compatable - self:setPointer(name,dat,"n") - elseif type(value)=="boolean" then - if value then - self:setPointer(name,"1","b") - else - self:setPointer(name,"0","b") - end - elseif type(value)=="string" then - self:setPointer(name,value,"s") - elseif type(value)=="table" then - local str=bin.ToStr(value) - self:setPointer(name,str,"t") - elseif type(value)=="function" then - local ver,verM,verm=bin.getLuaVersion() - local data=string.dump(value) - if ver=="JIT" then - ftype=bin:newDataBuffer(bits.numToBytes(0,4)) -- luajit version - else - ftype=bin:newDataBuffer(bits.numToBytes(tonumber(verM..verm),4)) -- lua version with MajorMinor data - end - local fdata=bin.new() - fdata:tackE(ftype:getBuffer()..data) - self:setPointer(name,fdata.data,"f") - elseif type(value)=="userdata" then - error("Userdata cannot be put into a block!") - end - end - function c:close() - self:addNamedBlock("",false) - self.data:close() - end - return c -end -function bin.loadNamedBlock(path) - local c={} - c.data=bin.stream(path) - c.iSize=c.data:tonumber(1,4) - c.index=bin.new(c.data:sub(5,c.iSize+4)) - c.sData=bin.new(c.data:sub(c.iSize+5,-1)) - function c:CheckRestOfIndex(name) - local a,b=self.index:scan(name) - local d=self.index:tonumber(b+2,b+5) - if d==0 or b+5>self.iSize then - return -1 - end - return d - end - function c:getIndexes() - local tab={} - ind=5 - while ind do - local a=self.index:find("\31",ind) - if not a then break end - local b=self.index:sub(ind,a-1) - table.insert(tab,b) - ind=a+5 - end - return tab - end - function c:getBlock(name) - local a,b=self.index:scan(name) - if not a then return "index not found" end - local dloc=self.index:tonumber(a-4,a-1) - local dindex=bin:newDataBuffer(self.sData:sub(dloc,dloc)) - if dindex[1]==0x01 then -- type number - return self.sData:tonumber(dloc+1,dloc+8) - elseif dindex[1]==0x02 then -- type bool - return ({[1]=true,[0]=false})[tonumber(self.sData:sub(dloc+1,dloc+1))] - elseif dindex[1]==0x03 then -- type string - local dend=self:CheckRestOfIndex(name)--self.index:tonumber(b+2,b+5) - return self.sData:sub(dloc+1,dend-1) - elseif dindex[1]==0x04 then -- type table - local dend=self.index:tonumber(b+2,b+5) - return loadstring("return "..self.sData:sub(dloc+1,dend-1))() - elseif dindex[1]==0x05 then -- type function - local dend=self:CheckRestOfIndex(name)--self.index:tonumber(b+2,b+5) - local _ver=self.sData:tonumber(dloc+1,dloc+4) - local ver,verM,verm=bin.getLuaVersion() - if tonumber(verM..verm)==_ver then - return loadstring(self.sData:sub(dloc+5,dend-1)) - else - return function() error("This lua function is not compatible with the current version of lua!") end - end - end - end - return c -end -function bin.namedBlockManager(name) - if type(name)=="string" then - local i={} - local data=bin.loadNamedBlock(name) - local mt={ - __index=function(t,k) - return data:getBlock(k) - end, - } - setmetatable(i,mt) - return i - else - local i={} - local data=bin.newNamedBlock(name) - local mt={ - __newindex=function(t,k,v) - data:addNamedBlock(k,v) - end, - __index=data - } - setmetatable(i,mt) - return i - end -end -function bin.getIndexSize(tab) - size=0 - for i=1,#tab do - size=size+#tab[i]+5 - end - return size+5 -end -function bin.gcd( m, n ) - while n ~= 0 do - local q = m - m = n - n = q % n - end - return m -end -function bin.numToFraction(num) - num=num or error("Must enter a number!") - local n=#tostring(num) - num=num*(10^n) - local d=(10^n) - local g=bin.gcd(num,d) - return tostring(num/g).."/"..tostring(d/g),num/g,d/g -end -function bin.doubleToString(double) - local s=({[false]="-",[true]="+"})[double>=0] - double=math.abs(double) - local _,n,d=bin.numToFraction(double) - gfit=4 - local a=bits.numToBytes(n,gfit,function(ref) - ref.fit=12 -- should be able to pack any number into that space - ref.num=string.rep("\0",12-#ref.num)..ref.num - if s=="-" then - s="_" - else - s="=" - end - gfit=12 - end) - local b=bits.numToBytes(d,gfit) - return s..a..b -end -function bin.stringToDouble(str) - local s=str:sub(1,1) - if #str~=9 and #str~=25 then - if s~="-" and s~="+" and s~="_" and s~="=" then - print(s) - error("Not a double encoded string") - end - error("Not a double encoded string") - end - local n,d - if s=="_" or s=="=" then - n,d=str:sub(2,13),str:sub(14) - else - n,d=str:sub(2,5),str:sub(6) - end - local n=bin.new(n):tonumber() - local d=bin.new(d):tonumber() - local num=n/d - if s=="-" or s=="_" then - num=-num - end - return num -end ---[[---------------------------------------- -VFS -------------------------------------------]] -local _require = require -function require(path,vfs) - if bin.fileExist(path..'.lvfs') then - local data = bin.loadVFS(path..'.lvfs') - if data:fileExist(vsf) then - loadstring(data:readFile(vfs))() - end - else - return _require(path) - end -end -function bin.loadVFS(path) - local vfs=bin.newVFS() - local temp=bin.stream(path,false) - local files=temp:getBlock("t") - local size=0 - for i=1,#files do - local p,len=files[i]:match("(.-)|(.+)") - len=tonumber(len) - size=size+bin.lastBlockSize - local dat=temp:sub(size+5,size+len+4) - bin.lastBlockSize=len - vfs:mkfile(p:gsub("%./",""),dat) - end - return vfs -end -function bin.copyDir(dir,todir) - local vfs=bin.newVFS(dir,true) - vfs:toFS(todir) - vfs=nil -end -function bin.newVFS(t,l) - l=l or true - if type(t)=='string' then - t=io.parseDir(t,l) - end - local c={} - c.FS= t or {} - function c:merge(vfs) - bin.newVFS(table.merge(self.FS,vfs.FS)) - end - function c:mirror(file) - self:mkfile(file,file) - end - function c:mkdir(path) - table.merge(self.FS,io.pathToTable(path)) - end - function c:scanDir(path) - path=path or '' - local tab={} - if path=='' then - for i,v in pairs(self.FS) do - tab[#tab+1]=i - end - return tab - end - spath=io.splitPath(path) - local last=self.FS - for i=1,#spath-1 do - last=last[spath[i]] - end - return last[spath[#spath]] - end - function c:getFiles(path) - if not self:dirExist(path) then return end - path=path or '' - local tab={} - if path=='' then - for i,v in pairs(self.FS) do - if self:fileExist(i) then - tab[#tab+1]=i - end - end - return tab - end - spath=io.splitPath(path) - local last=self.FS - for i=1,#spath-1 do - last=last[spath[i]] - end - local t=last[spath[#spath]] - for i,v in pairs(t) do - if self:fileExist(path..'/'..i) then - tab[#tab+1]=path..'/'..i - end - end - return tab - end - function c:getDirectories(path) - if not self:dirExist(path) then return end - path=path or '' - local tab={} - if path=='' then - for i,v in pairs(self.FS) do - if self:dirExist(i) then - tab[#tab+1]=i - end - end - return tab - end - spath=io.splitPath(path) - local last=self.FS - for i=1,#spath-1 do - last=last[spath[i]] - end - local t=last[spath[#spath]] - for i,v in pairs(t) do - if self:dirExist(path..'/'..i) then - tab[#tab+1]=path..'/'..i - end - end - return tab - end - function c:mkfile(path,data) - local name=io.getFullName(path) - local temp=path:reverse() - local a,b=temp:find('/') - if not a then - a,b=temp:find('\\') - end - if a then - temp=temp:sub(a+1):reverse() - path=temp - local t,l=io.pathToTable(path) - l[name]=data - table.merge(self.FS,t) - else - self.FS[name]=data - end - end - function c:remove(path) - if path=='' or path==nil then return end - spath=io.splitPath(path) - local last=self.FS - for i=1,#spath-1 do - last=last[spath[i]] - end - last[spath[#spath]]=nil - end - function c:readFile(path) - spath=io.splitPath(path) - local last=self.FS - for i=1,#spath do - last=last[spath[i]] - end - if type(last)=='userdata' then - last=last:read('*all') - end - return last - end - function c:copyFile(p1,p2) - self:mkfile(p2,self:readFile(p1)) - end - function c:moveFile(p1,p2) - self:copyFile(p1,p2) - self:remove(p1) - end - function c:fileExist(path) - return type(self:readFile(path))=='string' - end - function c:dirExist(path) - if path=='' or path==nil then return end - spath=io.splitPath(path) - local last=self.FS - for i=1,#spath-1 do - last=last[spath[i]] - end - if last[spath[#spath]]~=nil then - if type(last[spath[#spath]])=='table' then - return true - end - end - return false - end - function c:_getHierarchy() - local ord={} - local datlink=bin.new() - local function toStr(val, name, skipnewlines, depth, path) - skipnewlines = skipnewlines or false - path=path or "." - depth = depth or 0 - local tmp = string.rep(" ", depth) - if name then - if type(name) == "string" then - tmp = tmp .. "[\""..name.."\"] = " - else - tmp = tmp .. "["..(name or "").."] = " - end - end - if type(val) == "table" then - tmp = tmp .. "{" .. (not skipnewlines and "\n" or "") - for k, v in pairs(val) do - tmp = tmp .. toStr(v, k, skipnewlines, depth + 1,path.."/"..k) .. "," .. (not skipnewlines and "\n" or "") - end - tmp = tmp .. string.rep(" ", depth) .. "}" - elseif type(val) == "string" then - tmp = tmp .. #val - datlink:tackE(val) - ord[#ord+1]=path.."|"..#val - end - return tmp - end - return toStr(self.FS),ord,datlink - end - function c:getHierarchy() - local ord={} - local function toStr(val, name, skipnewlines, depth, path) - skipnewlines = skipnewlines or false - path=path or "." - depth = depth or 0 - local tmp = string.rep(" ", depth) - if name then - if type(name) == "string" then - tmp = tmp .. "[\""..name.."\"] = " - else - tmp = tmp .. "["..(name or "").."] = " - end - end - if type(val) == "table" then - tmp = tmp .. "{" .. (not skipnewlines and "\n" or "") - for k, v in pairs(val) do - tmp = tmp .. toStr(v, k, skipnewlines, depth + 1,path.."/"..k) .. "," .. (not skipnewlines and "\n" or "") - end - tmp = tmp .. string.rep(" ", depth) .. "}" - elseif type(val) == "string" then - tmp = tmp .. ";" - ord[#ord+1]=path.."|"..#val - end - return tmp - end - return toStr(self.FS),ord - end - function c:tofile(path) - local temp=bin.new() - local h,o,link=self:_getHierarchy() - temp:addBlock(o) - temp:merge(link) - temp:tofile(path) - end - function c:toFS(path) - if path then - if path:sub(-1,-1)~='\\' then - path=path..'\\' - elseif path:find('/') then - path=path:gsub('/','\\') - end - io.mkDir(path) - else - path='' - end - function build(tbl, indent, folder) - if not indent then indent = 0 end - if not folder then folder = '' end - for k, v in pairs(tbl) do - formatting = string.rep(' ', indent) .. k .. ':' - if type(v) == 'table' then - if v.t~=nil then - io.mkFile(folder..k,tostring(v),'wb') - else - if not(io.dirExists(path..folder..string.sub(formatting,1,-2))) then - io.mkDir(folder..string.sub(formatting,1,-2)) - end - build(v,0,folder..string.sub(formatting,1,-2)..'\\') - end - elseif type(v)=='string' then - io.mkFile(folder..k,v,'wb') - elseif type(v)=='userdata' then - io.mkFile(folder..k,v:read('*all'),'wb') - end - end - end - build(self.FS,0,path) - end - function c:print() - table.print(self.FS) - end - return c -end ---[[---------------------------------------- -BITS -------------------------------------------]] -function bits.lsh(value,shift) - return (value*(2^shift)) % 256 -end -function bits.rsh(value,shift) - return math.floor(value/2^shift) % 256 -end -function bits.bit(x,b) - return (x % 2^b - x % 2^(b-1) > 0) -end -function bits.lor(x,y) - result = 0 - for p=1,8 do result = result + (((bits.bit(x,p) or bits.bit(y,p)) == true) and 2^(p-1) or 0) end - return result -end -function bits.newBitBuffer(n) - -- -end -function bits.newConverter(bitsIn,bitsOut) - local c={} - -- -end -bits.ref={} -function bits.newByte(d) - local c={} - if type(d)=="string" then - if #d>1 or #d<1 then - error("A byte must be one character!") - else - c.data=string.byte(d) - end - elseif type(d)=="number" then - if d>255 or d<0 then - error("A byte must be between 0 and 255!") - else - c.data=d - end - else - error("cannot use type "..type(d).." as an argument! Takes only strings or numbers!") - end - c.__index=function(self,k) - if k>=0 and k<9 then - if self.data==0 then - return 0 - elseif self.data==255 then - return 1 - else - return bits.ref[self.data][k] - end - end - end - c.__tostring=function(self) - return bits.ref[tostring(self.data)] - end - setmetatable(c,c) - return c -end -function bits.newByteArray(s) - local c={} - if type(s)~="string" then - error("Must be a string type or bin/buffer type") - elseif type(s)=="table" then - if s.t=="sink" or s.t=="buffer" or s.t=="bin" then - local data=s:getData() - for i=1,#data do - c[#c+1]=bits.newByte(data:sub(i,i)) - end - else - error("Must be a string type or bin/buffer type") - end - else - for i=1,#s do - c[#c+1]=bits.newByte(s:sub(i,i)) - end - end - return c -end -function bits.new(n,s) - if type(n)=='string' then - local t=tonumber(n,2) - if t and #n<8 and not(s) then - t=nil - end - if not(t) then - t={} - for i=#n,1,-1 do - table.insert(t,bits:conv(string.byte(n,i))) - end - n=table.concat(t) - else - n=t - end - end - local temp={} - temp.t='bit' - setmetatable(temp, bits) - if type(n)~='string' then - local tab={} - while n>=1 do - table.insert(tab,n%2) - n=math.floor(n/2) - end - local str=string.reverse(table.concat(tab)) - if #str%8~=0 then - str=string.rep('0',8-#str%8)..str - end - temp.data=str - else - temp.data=n - end - setmetatable({__tostring=function(self) return self.data end},temp) - return temp -end -for i=0,255 do - local d=bits.new(i).data - bits.ref[i]={d:match("(%d)(%d)(%d)(%d)(%d)(%d)(%d)(%d)")} - bits.ref[tostring(i)]=d - bits.ref[d]=i - bits.ref["\255"..string.char(i)]=d -end -function bits.numToBytes(n,fit,func) - local num=bits.new(n):toSbytes() - num=bin.endianflop(num) - local ref={["num"]=num,["fit"]=fit} - if fit then - if fit<#num then - if func then - print("Warning: attempting to store a number that takes up more space than allotted! Using provided method!") - func(ref) - else - print("Warning: attempting to store a number that takes up more space than allotted!") - end - return ref.num:sub(1,ref.fit) - elseif fit==#num then - return num - else - return string.rep("\0",fit-#num)..num - end - else - return num - end -end -function bits:conv(n) - local tab={} - while n>=1 do - table.insert(tab,n%2) - n=math.floor(n/2) - end - local str=string.reverse(table.concat(tab)) - if #str%8~=0 then - str=string.rep('0',8-#str%8)..str - end - return str -end -function bits:add(i) - if type(i)=='number' then - i=bits.new(i) - end - self.data=self:conv(tonumber(self.data,2)+tonumber(i.data,2)) -end -function bits:sub(i) - if type(i)=='number' then - i=bits.new(i) - end - self.data=self:conv(tonumber(self.data,2)-tonumber(i.data,2)) -end -function bits:multi(i) - if type(i)=='number' then - i=bits.new(i) - end - self.data=self:conv(tonumber(self.data,2)*tonumber(i.data,2)) -end -function bits:div(i) - if type(i)=='number' then - i=bits.new(i) - end - self.data=self:conv(tonumber(self.data,2)/tonumber(i.data,2)) -end -function bits:tonumber(s) - if type(s)=='string' then - return tonumber(self.data,2) - end - s=s or 1 - return tonumber(string.sub(self.data,(8*(s-1))+1,8*s),2) or error('Bounds!') -end -function bits:isover() - return #self.data>8 -end -function bits:flipbits() - tab={} - for i=1,#self.data do - if string.sub(self.data,i,i)=='1' then - table.insert(tab,'0') - else - table.insert(tab,'1') - end - end - self.data=table.concat(tab) -end -function bits:tobytes() - local tab={} - for i=self:getbytes(),1,-1 do - table.insert(tab,string.char(self:tonumber(i))) - end - return bin.new(table.concat(tab)) -end -function bits:toSbytes() - local tab={} - for i=self:getbytes(),1,-1 do - table.insert(tab,string.char(self:tonumber(i))) - end - return table.concat(tab) -end -function bits:getBin() - return self.data -end -function bits:getbytes() - return #self.data/8 -end diff --git a/mulit/examples/love2d Threading Example/core/lovebind.lua b/mulit/examples/love2d Threading Example/core/lovebind.lua deleted file mode 100644 index eca6618..0000000 --- a/mulit/examples/love2d Threading Example/core/lovebind.lua +++ /dev/null @@ -1,103 +0,0 @@ -os.sleep=love.timer.sleep -function bin.load(file,s,r) - content, size = love.filesystem.read(file) - local temp=bin.new(content) - temp.filepath=file - return temp -end -function bin:tofile(filename) - if not(filename) or self.Stream then return nil end - love.filesystem.write(filename,self.data) -end -function bin.stream(file,l) - error("Sorry streaming is not available when using love2d :(, I am looking for a solution though :)") -end -function love.run() - if love.math then - love.math.setRandomSeed(os.time()) - end - if love.event then - love.event.pump() - end - if love.load then love.load(arg) end - if love.timer then love.timer.step() end - local dt = 0 - while true do - -- Process events. - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - if multi.boost then - for i=1,multi.boost-1 do - multi:uManager(dt) - end - end - multi:uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - multi.dManager() - love.graphics.setColor(255,255,255,255) - if multi.draw then multi.draw() end - love.graphics.present() - end - end -end -multi.drawF={} -function multi:dManager() - for ii=1,#multi.drawF do - multi.drawF[ii]() - end -end -function multi:onDraw(func,i) - i=i or 1 - table.insert(self.drawF,i,func) -end -function multi:lManager() - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return nil - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - multi:uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - multi.dManager() - love.graphics.setColor(255,255,255,255) - if multi.draw then multi.draw() end - love.graphics.present() - end -end diff --git a/mulit/examples/love2d Threading Example/core/net/Documentation.txt b/mulit/examples/love2d Threading Example/core/net/Documentation.txt deleted file mode 100644 index 462add6..0000000 --- a/mulit/examples/love2d Threading Example/core/net/Documentation.txt +++ /dev/null @@ -1,106 +0,0 @@ -Hey guys, I am currently working on a net library which aims to make Async servers/clients a piece of cake. It is still in heavy development, but a release will be made soon. The basic features are done and work great. The modules are being worked on though. -Right now I have the core and 4 modules finished -+CORE <-- The base library -+net.identity <-- makes registration and login for users seamless -+net.sft <-- a Simple File Transfer module. -NOTE: Once net.aft Is complete net.sft will no longer be supported -+net.aft <-- an Advanced File Transfer module. -NOTE: As of right now user can only download files in aft -+net.chatting <-- allows for chatting between users - -I will go into detail on how the core and 'stable' modules work - - -[color=#FF0000][b]Creating A Server[/b][/color] -EXAMPLE:1 -[code] ---[[Filename: server.lua -+Dependencies: -+the net library -+the bin library -+the multimanager library -+luasocket - -I suggest using luajit when creating the server for that extra boost in performance! -]] - -require("net") --- All you need is a port for the server init -server=net:newServer(12345) ---server=net:newTCPServer(12345) - ---[[The commented line above creates a TCP server -CID: Client ID, unique for each user connected to the server. If you are using a TCP Server then you get the handle used for communication -IP_OR_HANDLE, works much like CID_OR_HANDLE, where you get a handle if using TCP -The reason for this is so modules could be made for both types of servers and work flawlessly, The only exception is the sft and aft module, TCP is recommended to ensure things are sent in order -PORT_OR_IP is like the above as well... Think of it this way UDP_TCP for each argument -]] - -server:OnDataRecived(function(serv,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP) - if data=="Hello Server!" then -- the client say hi lets say something back - serv:send(IP_OR_HANDLE,"Hey client!",PORT_OR_IP,CID_OR_HANDLE)-- cid only needs to be passed for UDP Servers, you can exclude the cid argument if you want though. The server stores ports and IPs for each CID while they are logged on! - end -end) -multi:mainloop() -[/code] - -This is the basic setup for a server where you can send data back and forth. Note: modules that receive data will bypass triggering this event to save CPU time... Only events that are important get triggered If you want to speed up your code and make your event triggered when data you want gets passed use "!eventname! ...rest_of_your_data_here" - -For example You would do this: -EXAMPLE:2 -[code] ---[[ -Assume your client is sending this data: "!gamedata! MOVE bob 10 10" -take a look at the new server OnDataRecieved event -]] - -require("net") -server=net:newServer(12345) -world={["bob"]={x=0,y=0}} -server:OnDataRecived(function(serv,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP) - local cmd,entity,arg1,arg2=data:match("!gamedata! (%S+) (%S+) (%S+) (%S+)") - if cmd=="MOVE" then - --lets move bob - world[entity].x=tonumber(arg1) - world[entity].y=tonumber(arg2) - --Now lets tell every client connected what happened - serv:sendAll("!gamedata! UPDATE "..entity.." "..arg1.." "..arg2) -- note only data is needed now! - end -end,"gamedata") -- notice this string right here it allows the CORE to know that you should call this when !gamedata! is within a method. This is useful especally when you have many connections to the server OnDataRecieved event -multi:mainloop() -[/code] - -Now that was fun... But what if I'm sending binary data over to the client... Doesn't non-ASCII tend to get messed up? -Yes it does and even when using TCP data tends to not always transfer right - -net.normalize(data) converts data into all ASCII characters to keep your data safe, so even binary data can be passed. Since this uses base64 encoding every 3 characters become 4 so your data size becomes a bit bigger. To avoid problems keep all data being normalized data under 384 characters! The data here is converted into 512 bytes. -net.denormalize(data) takes the normalized and converts it back to what it was originally. - -Take a look at this example -EXAMPLE:3 -[code] ---Assume your client is sending this data: "!gamedata! MSG bob NORMILZED_MSG NIL" empty data so pattern matches - -require("net") -function CheckMSG(data) - -- TODO: modify the message for things that break our rules - returns data -end -server=net:newServer(12345) -world={["bob"]={x=0,y=0}} -server:OnDataRecived(function(serv,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP) - local cmd,entity,arg1,arg2=data:match("!gamedata! (%S+) (%S+) (%S+) (%S+)") - if cmd=="MOVE" then - --lets move bob - world[entity].x=tonumber(arg1) -- we are sending the numbers as binary data - world[entity].y=tonumber(arg2) - --Now lets tell every client connected what happened - serv:sendAll("!gamedata! UPDATE "..entity.." "..arg1.." "..arg2) -- note only data is needed now! - elseif cmd=="MSG" then -- client is sending a message NOTE: I have a module that handles chatting however for example sake here is a simple chat message - --Lets look at the data We normalize the data because we can have \n characters in the data and TCP/UDP are line based so that would mess up packets! - local msg=CheckMSG(net.denormalize(arg1)) - serv:sendAll("!gamedata! MSG "..entity.." "..msg.." NIL") - end -end,"gamedata") -- notice this string right here it allows the CORE to know that you should call this when !gamedata! is within a method. This is useful especally when you have many connections to the server OnDataRecieved event -multi:mainloop() -[/code] \ No newline at end of file diff --git a/mulit/examples/love2d Threading Example/core/net/admin.lua b/mulit/examples/love2d Threading Example/core/net/admin.lua deleted file mode 100644 index 886a7f7..0000000 --- a/mulit/examples/love2d Threading Example/core/net/admin.lua +++ /dev/null @@ -1,58 +0,0 @@ -require("parseManager") -require("net.identity") -require("net.aft") -net:registerModule("admin",{1,0,0}) --- Localhost does not need to log in to connect to the server and do whatever... This inculdes modules that you are writing for the server --- LAN connections can request data from the server without logging in, but must log in to alter server settings --- WAN connections can only request or alter settings if they are logged in - ---[[ -User levels: 1 - SERVEROWNER/localhost (Autodetect) - 2 - ADMIN - 3 - Modded User - 4 - Privileged User - 5 - Regular User - 6 - Restricted User - 7 - USER DEFINED - 8 - USER DEFINED - 9 - USER DEFINED - 10 - Banned User -]] -if not io.dirExists("-ADMINS-") then - io.mkdir("-ADMINS-") -end -if not io.fileExists("-ADMINS-/LEVELS-List.dat") then - io.mkfile("-ADMINS-/LEVELS-List.dat") -end -net.statuslist={} -net.OnServerCreated:connect(function(s) - s.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP) - local IP=tonumber(IP_OR_HANDLE) or tonumber(PORT_OR_IP) - end,"admin") - function s:setUserLevel(user,n) - -- - end - function s:makeAdmin(user) - -- - end - function s:makeMod(user) - -- - end - function s:makePrivileged(user) - -- - end - function s:restrict(user) - -- - end - function s:ban(user) - -- - end - function s:getUserLevel(user) - -- - end -end) -net.OnClientCreated:connect(function(c) - c.OnDataRecieved(function(self,data) - -- - end,"admin") -end) diff --git a/mulit/examples/love2d Threading Example/core/net/aft.lua b/mulit/examples/love2d Threading Example/core/net/aft.lua deleted file mode 100644 index 0ce6c59..0000000 --- a/mulit/examples/love2d Threading Example/core/net/aft.lua +++ /dev/null @@ -1,325 +0,0 @@ -require("net") ---General Stuff ---[[ What this module does! -Allows reliable transfer of files over the internet! -Hash testing and piece transfer -TODO: Add uploading support... For now use sft less intensive on the client/server -]] -net:registerModule("aft",{2,1,0}) -net.aft.transfers={} -net.aft.sinks={} -net.aft.cache={} -net.aft.preload={} -net.aft.pieceSize=768 -- max data packet for b64 that can safely be transfered without erroring! DO NOT CHANGE!!! -function net.aft:init() -- calling this initilizes the library and binds it to the servers and clients created - --Server Stuff - net.OnServerCreated:connect(function(s) - print("The aft(Advance File Transfer) Module has been loaded onto the server!") - if s.Type~="tcp" then - print("It is recomended that you use tcp to transfer files!") - end - s.OnUploadRequest=multi:newConnection() -- create an aft event - s.OnDownloadRequest=multi:newConnection() - s.OnClientClosed:connect(function(self,reason,cid,ip,port) - if net.aft.transfers[cid] then - for i,v in pairs(net.aft.transfers[cid]) do - v.resendAlarm:Destroy() - end - net.aft.transfers[cid]=nil - end - end) - function s:preloadFile(name) - net.aft.preload[name]={} - local temp=bin.stream(name) - temp:segmentedRead(768,function(data) - local unpackedDATA1=data:sub(1,384) - local unpackedDATA2=data:sub(385) - local packedDATA=net.normalize(unpackedDATA1)..net.normalize(unpackedDATA2) - table.insert(net.aft.preload,packedDATA) - end) - end - function s:isPreloaded(name) - return net.aft.preload[name]~=nil - end - s.allowSmallFileCaching=false - s.cachable=10 -- 10 MBs - s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered - local cmd,arg1,arg2=data:match("!aft! (%S+) (%S+) (%S+)") - --print(cmd,arg1,arg2) - if cmd=="PIECE" then - local FID,piecenum=arg1,tonumber(arg2) - local pp=piecenum-1 - net.aft.transfers[cid][FID].resendAlarm:Reset() - if net.aft.transfers[cid][FID] then - if pp>net.aft.transfers[cid][FID].pieces-1 then - self:send(ip,"!aft! DOWNLOAD INVALID_PIECENUM NIL NIL NIL",port) - print("ERROR 101") - else - if self:isPreloaded(name) then - self:send(ip,net.aft.preload[name][piecenum],port) - return - end - if self.allowSmallFileCaching then - if net.aft.cache[net.aft.transfers[cid][FID].name] then - if net.aft.cache[net.aft.transfers[cid][FID].name][piecenum] then - self:send(ip,net.aft.cache[net.aft.transfers[cid][FID].name][piecenum],port) - return - end - end - end - local ddata - local unpackedDATA=net.aft.transfers[cid][FID].sink:sub((pp*net.aft.pieceSize)+1,(pp+1)*net.aft.pieceSize) - local num=#unpackedDATA - if num<384 then - ddata="!aft! TRANS "..piecenum.." "..FID.." | "..net.normalize(unpackedDATA) - else - local unpackedDATA1=unpackedDATA:sub(1,384) - local unpackedDATA2=unpackedDATA:sub(385) - local packedDATA=net.normalize(unpackedDATA1)..net.normalize(unpackedDATA2) - ddata="!aft! TRANS "..piecenum.." "..FID.." | "..packedDATA - end - net.aft.transfers[cid][FID].resendAlarm.piecenum=piecenum - net.aft.transfers[cid][FID].resendAlarm.hash="" -- not needed anymore - net.aft.transfers[cid][FID].resendAlarm.packedDATA=packedDATA - -- SAFE - if self.allowSmallFileCaching then - net.aft.cache[net.aft.transfers[cid][FID].name][piecenum]=ddata - end - self:send(ip,ddata,port) - end - else - self:send(ip,"!aft! DOWNLOAD INVALID_FID NIL NIL NIL",port) - print("ERROR 102") - end - elseif cmd=="UPLOAD" then -- here we set up the spot for file writing - local FID,filename=arg1:match("(.-)|(.+)") - local struct={ - FID=FID, - filename=filename, - numpieces=tonumber(arg2) or -1 - } - if struct.numpieces==-1 then -- error handling catch it all :) - self:send(ip,"!aft! UPLOAD UPLOAD_REFUSED INVALID_NUMBER_OF_PIECES | |",port) - return - end - self.OnUploadRequest:Fire(struct,cid,ip,port) - if not(struct.deny) then -- block request or allow it - -- If we are allowed to lets do this - if not(net.aft.transfers.DOWNLOADS) then - net.aft.transfers.DOWNLOADS={} - end - if not(net.aft.transfers.DOWNLOADS[FID]) then - net.aft.transfers.DOWNLOADS[FID]={} - end - bin.new(""):tofile(struct.filename) - net.aft.transfers.DOWNLOADS[struct.FID].sink=struct.sink or bin.stream(struct.filename,false) - net.aft.transfers.DOWNLOADS[struct.FID].currentPiece=1 - net.aft.transfers.DOWNLOADS[struct.FID].numPieces=tonumber(arg2) - --we got that setup... Lets Request a piece now! - self:send(ip,"!aft! PIECE 1 "..FID.." | |",port) -- request piece # 1 - else - self:send(ip,"!aft! UPLOAD UPLOAD_REFUSED "..(struct.reason or "UNSPECIFIED_ERROR").." | |",port) - end - elseif cmd=="TRANS" then - local FID,piece=arg1:match("(.-)|(.+)") - local piece=tonumber(piece) or -1 - if pieces==-1 then -- error handling catch it all :) - self:send(ip,"!aft! UPLOAD UPLOAD_CANCLED PIECE_DATA_MALFORMED | |",port) - return - end - if #arg2<512 then - net.aft.transfers.DOWNLOADS[FID].sink:tackE(net.denormalize(arg2)) - else - net.aft.transfers.DOWNLOADS[FID].sink:tackE(net.denormalize(arg2:sub(1,512))..net.denormalize(arg2:sub(513))) - end - -- request the next piece - if piece==net.aft.transfers.DOWNLOADS[FID].numPieces then - -- We are done! - self:send(ip,"!aft! DONE "..FID.." | | |",port) - net.aft.transfers.DOWNLOADS[FID].sink:close() -- close the file - else - self:send(ip,"!aft! PIECE "..piece+1 .." "..FID.." | |",port) - end - elseif cmd=="REQUEST" then - local filename=arg1 - local struct={ - filename=filename - } - self.OnDownloadRequest:Fire(self,struct) - if io.fileExists(struct.filename) or struct.handle then - local FID=bin.new(filename):getRandomHash(16) - if struct.handle then - FID=struct.handle:getRandomHash(16) - end - if not net.aft.transfers[cid] then - net.aft.transfers[cid]={} -- setup server-client filestream - end - net.aft.transfers[cid][FID]={} - net.aft.transfers[cid][FID].name=struct.filename - if struct.handle then - net.aft.transfers[cid][FID].sink=struct.handle - else - net.aft.transfers[cid][FID].sink=bin.stream(struct.filename,false) - end - net.aft.transfers[cid][FID].size=net.aft.transfers[cid][FID].sink:getSize() - net.aft.transfers[cid][FID].pieces=math.ceil(net.aft.transfers[cid][FID].size/net.aft.pieceSize) - net.aft.transfers[cid][FID].resendAlarm=multi:newAlarm(.25) - net.aft.transfers[cid][FID].resendAlarm:OnRing(function(alarm) - if not(alarm.packedDATA) then return end - self:send(ip,"!aft! TRANS "..alarm.piecenum.." "..FID.." | "..alarm.packedDATA,port) - alarm:Reset() - end) - if self.allowSmallFileCaching then - if net.aft.transfers[cid][FID].size<=1024*self.cachable then -- 10 MB or smaller can be cached - net.aft.cache[struct.filename]={} - end - end - self:send(ip,"!aft! START "..net.aft.transfers[cid][FID].pieces.." "..FID.." "..filename.." NIL",port) - else - self:send(ip,"!aft! DOWNLOAD REQUEST_REFUSED NIL NIL NIL",port) - print("ERROR 103") - end - elseif cmd=="COMPLETE" then - net.aft.transfers[cid][arg1].resendAlarm:Destroy() - net.aft.transfers[cid][arg1]=nil - end - end,"aft") -- some new stuff - end) - --Client Stuff - net.OnClientCreated:connect(function(c) - c.OnPieceRecieved=multi:newConnection() - c.OnTransferStarted=multi:newConnection() - c.OnTransferCompleted=multi:newConnection() - c.OnFileRequestFailed=multi:newConnection() -- create an aft event - c.OnFileUploadFailed=multi:newConnection() -- not yet must ensure oneway works well first - c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered - local cmd,pieces,FID,arg1,arg2=data:match("!aft! (%S+) (%S+) (%S+) (%S+) (%S+)") - --print(cmd,pieces,FID,arg1,arg2) - if cmd=="START" then-- FID filename #pieces - local struct={ - FID=FID, - filename=arg1, - numpieces=tonumber(pieces) - } - self.OnTransferStarted:Fire(self,struct) - local fid,filename,np=struct.FID,struct.filename,struct.numpieces - local sink="" - if type(net.aft.sinks[filename])=="table" then - sink=net.aft.sinks[filename] - sink.file=filename - else - if net.aft.sinks[filename] then - bin.new():tofile(net.aft.sinks[filename]) - sink=bin.stream(net.aft.sinks[filename],false) - else - bin.new():tofile(filename) - sink=bin.stream(filename,false) - end - end - net.aft.transfers[FID]={} - net.aft.transfers[FID].name=sink.file - net.aft.transfers[FID].sink=sink - net.aft.transfers[FID].currentPiece=1 - net.aft.transfers[FID].piecesRecieved=0 - net.aft.transfers[FID].numpieces=tonumber(pieces) - c:requestPiece(FID,1) - elseif cmd=="DONE" then - local FID=pieces - print(net.aft.transfers.UPLOADS[FID].name.." has Finished Uploading!") - self.OnTransferCompleted:Fire(self,net.aft.transfers[FID].name,"U") - net.aft.transfers[FID]=nil -- clean up - elseif cmd=="PIECE" then -- Server is asking for a piece to some file - local pieces=tonumber(pieces) - local pp=pieces-1 - local unpackedDATA=net.aft.transfers.UPLOADS[FID].sink:sub((pp*net.aft.pieceSize)+1,(pp+1)*net.aft.pieceSize) - local num=#unpackedDATA - if num<384 then - self:send("!aft! TRANS "..FID.."|"..pieces.." "..net.normalize(unpackedDATA)) - else - local unpackedDATA1=unpackedDATA:sub(1,384) - local unpackedDATA2=unpackedDATA:sub(385) - local packedDATA=net.normalize(unpackedDATA1)..net.normalize(unpackedDATA2) - self:send("!aft! TRANS "..FID.."|"..pieces.." "..packedDATA) - end - elseif cmd=="TRANS" then-- self,data,FID,piecenum,hash - if self.autoNormalization==false then -- if we already handled normalization in the main data packet then don't redo - local ddata - if #arg2<512 then - ddata=net.denormalize(arg2) - else - ddata=net.denormalize(arg2:sub(1,512))..net.denormalize(arg2:sub(513)) - end - struct={ - data=ddata, - FID=FID, - piecenum=tonumber(pieces), - numpieces=net.aft.transfers[FID].numpieces, - hash=arg1, - name=net.aft.transfers[FID].name, - } - else - struct={ - data=arg2, - FID=FID, - piecenum=tonumber(pieces), - numpieces=net.aft.transfers[FID].numpieces, - hash=arg1, - name=net.aft.transfers[FID].name, - } - end - net.aft.transfers[FID].currentPiece=tonumber(pieces) - self.OnPieceRecieved:Fire(self,struct) - local data,FID,piecenum,hash=struct.data,struct.FID,struct.piecenum,struct.hash - net.aft.transfers[FID].sink:tackE(data) - net.aft.transfers[FID].piecesRecieved=net.aft.transfers[FID].piecesRecieved+1 - if net.aft.transfers[FID].numpieces==net.aft.transfers[FID].piecesRecieved then - print(net.aft.transfers[FID].name.." has finished downloading!") - net.aft.transfers[FID].sink:close() - self:send("!aft! COMPLETE "..FID.." NIL") -- for clean up purposes - self.OnTransferCompleted:Fire(self,net.aft.transfers[FID].name) - else - self:requestPiece(FID,piecenum+1) -- get next piece - end - elseif cmd=="DOWNLOAD" then - local msg=FID - self.OnFileRequestFailed:Fire(msg) - print("Download Error!",msg) - elseif cmd=="UPLOAD" then - local msg=FID - self.OnFileUploadFailed:Fire(msg) - print("Upload Error!",msg) - end - end,"aft") - function c:requestFile(filename,sink) -- sinks data through a bin-stream sink if the filename you want otherwise the filename is used instead - self:send("!aft! REQUEST "..filename.." NIL") - if sink then - net.aft.sinks[filename]=sink - end - end - function c:requestUpload(filename) - if io.fileExists(filename) then - local FID=bin.new(filename):getRandomHash(16) -- We need this, but its not as important for client as it is for servers - local file=bin.stream(filename) - if not net.aft.transfers.UPLOADS then - net.aft.transfers.UPLOADS={} - end - if not net.aft.transfers.UPLOADS[FID] then - net.aft.transfers.UPLOADS[FID]={} - end - net.aft.transfers.UPLOADS[FID].sink=file -- client file management is much simpler since we only have to worry about 1 reciever/sender - net.aft.transfers.UPLOADS[FID].name=filename - net.aft.transfers.UPLOADS[FID].size=file:getSize() - net.aft.transfers.UPLOADS[FID].pieces=math.ceil(net.aft.transfers.UPLOADS[FID].size/net.aft.pieceSize) - self:send("!aft! UPLOAD "..FID.."|"..filename.." "..net.aft.transfers.UPLOADS[FID].pieces)-- Lets send the FID we will be using and the number of pieces the server should look out for - else - self.OnFileUploadFailed:Fire("File specified not found! "..filename.." does not exist!") - end - end - function c:requestPiece(FID,piecenum) - self:send("!aft! PIECE "..FID.." "..piecenum) - end - end) -end -if net.autoInit then - net.aft.init() -end diff --git a/mulit/examples/love2d Threading Example/core/net/audp.lua b/mulit/examples/love2d Threading Example/core/net/audp.lua deleted file mode 100644 index d310477..0000000 --- a/mulit/examples/love2d Threading Example/core/net/audp.lua +++ /dev/null @@ -1,273 +0,0 @@ -function net:newAUDPServer(port,servercode) - local c={} - c.udp=assert(socket.udp()) - c.udp:settimeout(0) - c.udp:setsockname("*", port) - c.ips={} - c.Type="udp" - c.port=port - c.ids={} - c.servercode=servercode - c.bannedIPs={} - c.bannedCIDs={} - c.autoNormalization=false - function c:setUpdateRate(n) - print("Not needed in a audp server!") - end - function c:banCID(cid) - table.insert(self.bannedCIDs,cid) - end - function c:banIP(ip) - table.insert(self.bannedIPs,cid) - end - function c:send(ip,data,port,cid) - if self.autoNormalization then - data=net.normalize(data) - end - if self.servercode then - cid=cid or self:CIDFrom(ip,port) - if not self.ips[cid] then - print("Can't determine cid from client... sending the client a new one!") - local cid=net.resolveID(self) - print("Sending unique cid to client: "..cid) - self.ips[cid]={ip,port,0,self.servercode==nil} - print(ip) - self.udp:sendto("I!"..cid,ip,port) - if self.servercode then - self.udp:sendto("S!",ip,port) - end - return - end - if net.inList(self.bannedIPs,ip) or net.inList(self.bannedCIDs,cid) then - self.udp:sendto("BANNED CLIENT", ip, port or self.port) - elseif self.ips[cid][4] then - self.udp:sendto(data, ip, port or self.port) - elseif self.ips[cid][4]==false then - self.udp:sendto("Make sure your server code is correct!", ip, port) - end - else - self.udp:sendto(data, ip, port or self.port) - end - end - function c:pollClientModules(ip,port) - self:send(ip,"L!",port) - end - function c:CIDFrom(ip,port) - for i,v in pairs(self.ips) do - if(ip==v[1] and v[2]==port) then - return i - end - end - end - function c:sendAll(data) - for i,v in pairs(self.ips) do - self:send(v[1],data,v[2],i) - end - end - function c:sendAllBut(data,cid) - for i,v in pairs(self.ips) do - if i~=cid then - self:send(v[1],data,v[2],i) - end - end - end - function c:clientRegistered(cid) - return self.ips[cid] - end - function c:clientLoggedIn(cid) - if not self.clientRegistered(cid) then - return nil - end - return self.ips[cid][4] - end - function c:update() - local data,ip,port=self.udp:receivefrom() - if net.inList(self.bannedIPs,ip) or net.inList(self.bannedCIDs,cid) then - print("We will ingore data from a banned client!") - return - end - if data then - if self.autoNormalization then - data=net.denormalize(data) - end - if data:sub(1,4)=="pong" then - self.ips[data:sub(5,-1)][3]=os.clock() - elseif data:sub(1,2)=="S!" then - local cid=self:CIDFrom(ip,port) - if data:sub(3,-1)==self.servercode then - print("Servercode Accepted: "..self.servercode) - if self.ips[cid] then - self.ips[cid][4]=true - else - print("Server can't keep up! CID: "..cid.." has been skipped! Sending new CID to the client!") - local cid=net.resolveID(self) - print("Sending unique cid to client: "..cid) - self.ips[cid]={ip,port,0,self.servercode==nil} - print(ip) - self.udp:sendto("I!"..cid,ip,port) - if self.servercode then - self.udp:sendto("S!",ip,port) - end - end - else - self.udp:sendto("Make sure your server code is correct!", ip, port) - end - elseif data:sub(1,2)=="C!" then - local hook=(data:sub(11,-1)):match("!(.-)!") - self.OnDataRecieved:getConnection(hook):Fire(self,data:sub(11,-1),data:sub(3,10),ip,port) - elseif data:sub(1,2)=="E!" then - self.ips[data:sub(3,10)]=nil - obj.ids[data:sub(3,10)]=false - self.OnClientClosed:Fire(self,"Client Closed Connection!",data:sub(3,10),ip,port) - elseif data=="I!" then - local cid=net.resolveID(self) - print("Sending unique cid to client: "..cid) - self.ips[cid]={ip,port,os.clock(),self.servercode==nil} - print(ip) - self.udp:sendto("I!"..cid,ip,port) - if self.servercode then - self.udp:sendto("S!",ip,port) - end - self.OnClientConnected:Fire(self,cid,ip,port) - elseif data:sub(1,2)=="L!" then - cid,cList=data:sub(3,10),data:sub(11,-1) - local list={} - for m,v in cList:gmatch("(%S-):(%S-)|") do - list[m]=v - end - self.OnClientsModulesList:Fire(list,cid,ip,port) - end - end - for cid,dat in pairs(self.ips) do - if not((os.clock()-dat[3])<65) then - self.ips[cid]=nil - self.OnClientClosed:Fire(self,"Client lost Connection: ping timeout",cid,ip,port) - end - end - end - c.OnClientsModulesList=multi:newConnection() - c.OnDataRecieved=multi:newConnection() - c.OnClientClosed=multi:newConnection() - c.OnClientConnected=multi:newConnection() - c.connectiontest=multi:newAlarm(30) - c.connectiontest.link=c - c.connectiontest:OnRing(function(alarm) - --print("pinging clients!") - alarm.link:sendAll("ping") - alarm:Reset() - end) - multi:newLoop(function() - c:update() - end) - net.OnServerCreated:Fire(c) - return c -end - -function net:newAUDPClient(host,port,servercode,nonluaServer) - local c={} - c.ip=assert(socket.dns.toip(host)) - c.udp=assert(socket.udp()) - c.udp:settimeout(0) - c.cid="NIL" - c.lastPing=0 - c.Type="udp" - c.servercode=servercode - c.autoReconnect=true - c.autoNormalization=false - function c:pollPing(n) - return not((os.clock()-self.lastPing)<(n or 60)) - end - function c:send(data) - if self.autoNormalization then - data=net.normalize(data) - end - self.udp:send("C!"..self.cid..data) - end - function c:sendRaw(data) - if self.autoNormalization then - data=net.normalize(data) - end - self.udp:send(data) - end - function c:getCID() - if self:IDAssigned() then - return self.cid - end - end - function c:close() - self:send("E!") - end - function c:IDAssigned() - return self.cid~="NIL" - end - function c:update() - local data=self.udp:receive() - if data then - if self.autoNormalization then - data=net.denormalize(data) - end - if data:sub(1,2)=="I!" then - self.cid=data:sub(3,-1) - self.OnClientReady:Fire(self) - elseif data=="S!" then - self.udp:send("S!"..(self.servercode or "")) - elseif data=="L!" then - local mods="" - local m="" - for i=1,#net.loadedModules do - m=net.loadedModules[i] - mods=mods..m..":"..net.getModuleVersion(m).."|" - end - self.udp:send("L!"..self.cid..mods) - elseif data=="ping" then - self.lastPing=os.clock() - self.OnPingRecieved:Fire(self) - self.udp:send("pong"..self.cid) - else - local hook=data:match("!(.-)!") - self.OnDataRecieved:getConnection(hook):Fire(self,data) - end - end - end - function c:reconnect() - if not nonluaServer then - self.cid="NIL" - c.udp:send("I!") - end - self.OnConnectionRegained:Fire(self) - end - c.pingEvent=multi:newEvent(function(self) return self.link:pollPing() end) - c.pingEvent:OnEvent(function(self) - if self.link.autoReconnect then - self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout! Attempting to reconnect...") - self.link.OnClientDisconnected:Fire(self,"closed") - self.link:reconnect() - else - self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout!") - self.link.OnClientDisconnected:Fire(self,"closed") - end - end) - c.pingEvent.link=c - c.OnPingRecieved=multi:newConnection() - c.OnDataRecieved=multi:newConnection() - c.OnServerNotAvailable=multi:newConnection() - c.OnClientReady=multi:newConnection() - c.OnClientDisconnected=multi:newConnection() - c.OnConnectionRegained=multi:newConnection() - c.notConnected=multi:newFunction(function(self) - self:hold(3) - if self.link:IDAssigned()==false then - self.link.OnServerNotAvailable:Fire("Can't connect to the server: no response from server") - end - end) - c.notConnected.link=c - if not nonluaServer then - c.udp:send("I!") - end - multi:newLoop(function() - c:update() - end) - multi:newJob(function() c.notConnected() end) - net.OnClientCreated:Fire(c) - return c -end diff --git a/mulit/examples/love2d Threading Example/core/net/chatting.lua b/mulit/examples/love2d Threading Example/core/net/chatting.lua deleted file mode 100644 index b2ab8d5..0000000 --- a/mulit/examples/love2d Threading Example/core/net/chatting.lua +++ /dev/null @@ -1,134 +0,0 @@ -require("net") -require("net.identity") ---General Stuff ---[[ What this module does! -Adds -net.chatting:init() -server:OnChatRecieved(function({user,msg}) end) -client:OnChatRecieved(function(user,msg) end) -client:sendChat(user,msg) -]] -net:registerModule("chatting",{3,0,0}) -net.chatting.users={} -function net.chatting:getUserIdFromIP(ip) - return net.chatting.users[ip] -end -function net.chatting:init() -- calling this initilizes the library and binds it to the servers and clients created - --Server Stuff - net.OnServerCreated:connect(function(s) - print("The Chatting Module has been loaded onto the server!") - s.OnUserLoggedIn(function(user,cid,ip,port,dTable) - dTable=loadstring("return "..dTable)() - local USERID=bin.new(user):getHash(32) - net.chatting.users[USERID]={dTable.nick,cid,ip,port,dTable} -- add users that log in to the userlist - net.chatting.users[ip]=USERID -- add users that log in to the userlist - local users={} - for i,v in pairs(net.chatting.users) do - if type(i)~="userdata" then - table.insert(users,i.."|"..net.chatting.users[i][1]) - end - end - table.insert(users,"") - for i,v in pairs(s.ips) do - s:send(v,"!chatting! $Users|NIL|NIL '"..table.concat(users,",").."'") - end - end) - s.OnUserLoggerOut(function(self,user) - local USERID=bin.new(user):getHash(32) - local ip=net.chatting.users[USERID] - print(USERID) - net.chatting.users[USERID]=nil - net.chatting.users[ip]=nil - end) - s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered - --First Lets make sure we are getting chatting data - local user,msg = data:match("!chatting! (%S-) (.+)") - if user and msg then - if user:sub(1,1)=="$" then - local cmd,arg=user:match("$(.+)|(.+)") - print("Using extended chatting protocal!") - if cmd=="DM" then - local struct={ -- pack the info up as a table so the server can do filtering and whatnot to the chat - user=user, - msg=net.denormalize(msg) - } - self.OnChatRecieved:Fire(struct,"PRIVATE") - print("USERID",arg) - self:send(net.chatting.users[arg][3],"!chatting! $DM|"..net.chatting.users[arg][1].."|"..net.chatting:getUserIdFromIP(ip).." "..net.normalize(struct.msg).."",net.chatting.users[arg][4]) - elseif cmd=="getUsers" then - local users={} - for i,v in pairs(net.chatting.users) do - if type(i)~="userdata" then - table.insert(users,i.."|"..net.chatting.users[i][1]) - end - end - table.insert(users,"") - self:send(ip,"!chatting! $Users|NIL|NIL "..table.concat(users,",").."",port) - end - else - local struct={ -- pack the info up as a table so the server can do filtering and whatnot to the chat - user=user, - msg=net.denormalize(msg) - } - self.OnChatRecieved:Fire(struct,"GROUP") -- trigger the chat event - local USERID=net.chatting:getUserIdFromIP(ip) - for i,v in pairs(self.ips) do - if ip==v then - self:send(v,"!chatting! 1|"..struct.user.."|"..USERID.." "..net.normalize(struct.msg).."") - else - self:send(v,"!chatting! 0|"..struct.user.."|"..USERID.." "..net.normalize(struct.msg).."") - end - end - end - end - end,"chatting") - s.rooms={} - function s:regesterRoom(roomname) - self.rooms[roomname]={} - end - s.OnChatRecieved=multi:newConnection() -- create a chat event - end) - --Client Stuff - net.OnClientCreated:connect(function(c) - c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered - --First Lets make sure we are getting chatting data - local isself,user,USERID,msg = data:match("!chatting! (%S-)|(%S-)|(%S-) (.+)") - if not isself then return end - if tonumber(isself) then - --This is the client so our job here is done - local msg=net.denormalize(msg) - self.OnChatRecieved:Fire(user,msg,({["1"]=true, ["0"]=false})[isself],USERID) -- trigger the chat event - elseif isself:sub(1,1)=="$" then - local cmd=isself:match("$(.+)") - if cmd=="DM" then - local msg=net.denormalize(msg) - c.OnPrivateChatRecieved:Fire(user,msg,USERID) - elseif cmd=="Users" then - local tab={} - for ID,nick in msg:gmatch("(%S-)|(%S-),") do - tab[nick]=ID - end - c.OnUserList:Fire(tab) - end - end - end,"chatting") - function c:sendChat(user,msg) - self:send("!chatting! "..user.." "..net.normalize(msg).."") - end - function c:sendChatTo(user,touser,msg) - self:send("!chatting! $DM|"..touser.." "..net.normalize(msg).."") - end - function c:getUserList() - self:send("!chatting! $getUsers|NIL NIL") - end - function c:getChatFrom(userID) - self:send("!chatting! getPrivateChat|NIL "..userID) -- add if time permits - end - c.OnPrivateChatRecieved=multi:newConnection() - c.OnUserList=multi:newConnection() - c.OnChatRecieved=multi:newConnection() -- create a chat event - end) -end -if net.autoInit then - net.chatting:init() -end diff --git a/mulit/examples/love2d Threading Example/core/net/db.lua b/mulit/examples/love2d Threading Example/core/net/db.lua deleted file mode 100644 index 6e2c41e..0000000 --- a/mulit/examples/love2d Threading Example/core/net/db.lua +++ /dev/null @@ -1,15 +0,0 @@ -require("parseManager") -require("net.identity") -- serversie module -net:registerModule("db",{1,0,0}) -net.OnServerCreated:connect(function(s) - s.OnUserLoggedIn(function(user,cid,ip,port,dTable) -- dealing with userdata - -- - end) - function s:createTable(PKey,fmt,path) - -- - end -end) ---keys are case insensitive, hex and regular base 10 numbers are allowed as well as other structures ---We define a table below with keys and their max size - - diff --git a/mulit/examples/love2d Threading Example/core/net/eft.lua b/mulit/examples/love2d Threading Example/core/net/eft.lua deleted file mode 100644 index c88e472..0000000 --- a/mulit/examples/love2d Threading Example/core/net/eft.lua +++ /dev/null @@ -1,24 +0,0 @@ -require("net") -net:registerModule("eft",{1,0,0}) ---[[ - This module provides a dedicated socket for file transfer - This allows us to do some more complex stuff with it - The only data that is non file stuff is the initial handshake - CMDs are done on the general socket while transfers are done on the file socket -]] -net.OnServerCreated:connect(function(s) - print("The eft(Expert File Transfer) Module has been loaded onto the server!") - if s.Type~="tcp" then - print("It is recomended that you use tcp to transfer files!") - end - s.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP) - -- - end,"eft") - -- -end) -net.OnClientCreated:connect(function(c) - c.OnDataRecieved(function(self,data) - -- - end,"eft") - -- -end) diff --git a/mulit/examples/love2d Threading Example/core/net/email.lua b/mulit/examples/love2d Threading Example/core/net/email.lua deleted file mode 100644 index 1f46368..0000000 --- a/mulit/examples/love2d Threading Example/core/net/email.lua +++ /dev/null @@ -1,54 +0,0 @@ -require("net.identity") -net:registerModule("email",{1,0,0}) --- needs rewriting, where it uses the identity module and can send an email. EX: server:email(user,subject,body) -smtp = require 'socket.smtp' -ssl = require 'ssl' -- server side only so noworries for love2d users - -function net.email.init(from,user,pass) - net.OnServerCreated:connect(function(s) - s.from=from - s.user=user - s.pass=pass - function s:sendMessage(subject, body, dTable) - local msg = { - headers = { - from = '<'..dTable.email..'>' - to = dTable.nick..' <'..dTable.email..'>', - subject = subject - }, - body = body - } - local ok, err = smtp.send { - from = '<'..self.from..'>', - rcpt = '<'..dTable.email..'>', - source = smtp.message(msg), - user = self.user, - password = self.pass, - server = 'smtp.gmail.com', - port = 465, - create = net.sslCreate - } - if not ok then - print("Mail send failed", err) -- better error handling required - end - end - end) -end -function net.sslCreate() - local sock = socket.tcp() - return setmetatable({ - connect = function(_, host, port) - local r, e = sock:connect(host, port) - if not r then return r, e end - sock = ssl.wrap(sock, {mode='client', protocol='tlsv1'}) - return sock:dohandshake() - end - }, { - __index = function(t,n) - return function(_, ...) - return sock[n](sock, ...) - end - end - }) -end - diff --git a/mulit/examples/love2d Threading Example/core/net/emailWIP.lua b/mulit/examples/love2d Threading Example/core/net/emailWIP.lua deleted file mode 100644 index dbea43a..0000000 --- a/mulit/examples/love2d Threading Example/core/net/emailWIP.lua +++ /dev/null @@ -1,53 +0,0 @@ -require("net.identity") -net:registerModule("email",{1,0,0}) -smtp = require 'socket.smtp' -ssl = require 'ssl' - -function net.email.init(from,user,pass) - net.OnServerCreated:connect(function(s) - s.from=from - s.user=user - s.pass=pass - function s:sendMessage(subject, body, dTable) - local msg = { - headers = { - from = '<'..dTable.email..'>' - to = dTable.nick..' <'..dTable.email..'>', - subject = subject - }, - body = body - } - local ok, err = smtp.send { - from = '<'..self.from..'>', - rcpt = '<'..dTable.email..'>', - source = smtp.message(msg), - user = self.user, - password = self.pass, - server = 'smtp.gmail.com', - port = 465, - create = net.sslCreate - } - if not ok then - print("Mail send failed", err) -- better error handling required - end - end - end) -end -function net.sslCreate() - local sock = socket.tcp() - return setmetatable({ - connect = function(_, host, port) - local r, e = sock:connect(host, port) - if not r then return r, e end - sock = ssl.wrap(sock, {mode='client', protocol='tlsv1'}) - return sock:dohandshake() - end - }, { - __index = function(t,n) - return function(_, ...) - return sock[n](sock, ...) - end - end - }) -end - diff --git a/mulit/examples/love2d Threading Example/core/net/identity.lua b/mulit/examples/love2d Threading Example/core/net/identity.lua deleted file mode 100644 index c16aa43..0000000 --- a/mulit/examples/love2d Threading Example/core/net/identity.lua +++ /dev/null @@ -1,266 +0,0 @@ -require("net") ---General Stuff ---[[ What this module does! -Adds -net.identity:init() - -]] -net:registerModule("identity",{2,1,0})--1.0.1 Note: Added eaiser ways to get user data using only cid -function net.hash(text,n) - n=n or 16 - return bin.new(text.."jgmhktyf"):getHash(n) -end -net.identity.UIDS={} -net.identity.UIDS.ids={} -function net.identity:init() -- calling this initilizes the library and binds it to the servers and clients created - --Server Stuff - net.OnServerCreated(function(s) - s.userFolder="./USERS" - print("The identity Module has been loaded onto the server!") - function s:_isRegistered(user) - return io.fileExists(self.userFolder..net.hash(user)..".dat") - end - function s:getUserData(user) - local userdata=bin.load(self.userFolder..net.hash(user)..".dat") - local nick,dTable=userdata:match("%S-|%S-|(%S-)|(.+)") - return nick,loadstring("return "..(dTable or "{}"))() - end - function s:modifyUserData(user,oldpass,pass,nick,dTable) - if self:_isRegistered(user) then - local userdata=bin.load(self.userFolder..net.hash(user)..".dat") - local args={} - local _pass,_nick,_dTable=userdata:match("%S-|(%S-)|(%S-)|(.+)") - if oldpass~=_pass then - args.invalidPass=true - pass=_pass - end - if not nick then nick=_nick args.invalidNick=true end - table.merge(_dTable or {}, dTable or {}) - bin.new(string.format("%s|%s|%s|%s\n",user,pass,nick,dTable)):tofile(self.userFolder..net.hash(user)..".dat") - else - return false - end - end - function s:getUserCred(user) - local userdata=bin.load(self.userFolder..net.hash(user)..".dat") - return userdata:match("%S-|(%S-)|") - end - function s:getUSERID(cid) - return (net.identity.UIDS[cid] or "User Not Logged In!") - end - function s:getUsername(cid) - return self:userLoggedIn(cid) - end - function s:getNickname(cid) - return self.loggedIn[self:getUsername(cid)].nick - end - function s:getdTable(cid) - return self.loggedIn[self:getUsername(cid)] - end - function s:getUserDat(cid) - return self:getUserDataHandle(self:getUsername(cid)) - end - function s:getNickFromUSERID(USERID) - return bin.load(self.userFolder..net.hash(user)..".dat"):match("%S-|%S-|(%S-)|") - end - function s:userLoggedIn(cid) - for i,v in pairs(self.loggedIn) do - if v.cid==cid then - return i - end - end - return false - end - function s:setDataLocation(loc) - if not io.dirExists(loc) then - io.mkDir(loc) - end - self.userFolder=loc - end - s:setDataLocation("USERS/") - function s:logoutUser(user) - net.identity.UIDS.ids[user.UID]=nil - self.loggedIn[user]=nil - end - function s:loginUser(user,cid) - net.identity.UIDS[cid]=net.hash(user) - local nick,dTable=self:getUserData(user) - self.loggedIn[user]={} - table.merge(self.loggedIn[user],dTable or {}) - self.loggedIn[user].cid=cid - self.loggedIn[user].nick=nick - self.loggedIn[user].UID=net.resolveID(net.identity.UIDS) - return self.loggedIn[user] - end - function s:getUserDataHandle(user) - return self.loggedIn[user] - end - function s:syncUserData(user,ip,port) - local handle=self:getUserDataHandle(user) - self:send(ip,"!identity! SYNC <-|"..bin.ToStr(handle).."|->",port) - end - s.loggedIn={} - s.allowDuplicateNicks=true - s.minimumNickLength=4 - s.minimumUserLength=4 - s.OnUserRegistered=multi:newConnection() - s.OnUserLoggedIn=multi:newConnection() - s.OnUserLoggerOut=multi:newConnection() - s.OnAlreadyLoggedIn=multi:newConnection() - s.OnPasswordForgotten=multi:newConnection() - s.OnDataRecieved:connect(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered - local cmd,arg1,arg2,arg3,arg4 = data:match("!identity! (%S-) '(.-)' '(.-)' '(.-)' <%-|(.+)|%->") - if cmd=="register" then - local user,pass,nick,dTable = arg1,arg2,arg3,arg4 - if self:_isRegistered(user) then - self:send(ip,"!identity! REGISTERED <-|"..user.."|->",port) - else - if not(self.userFolder:sub(-1,-1)=="/" or self.userFolder:sub(-1,-1)=="\\") then - self.userFolder=self.userFolder.."/" - end - local rets=self.OnUserRegistered:Fire(user,pass,nick,loadstring("return "..(dTable or "{}"))()) - if #user<=self.minimumUserLength then - self:send(ip,"!identity! REGISTERREFUSED <-|Username too short|->",port) - return - end - if #user<=self.minimumNickLength then - self:send(ip,"!identity! REGISTERREFUSED <-|Nickname too short|->",port) - return - end - for i=1,#rets do - if rets[i][1]==false then - print("Server refused to accept registration request!") - self:send(ip,"!identity! REGISTERREFUSED <-|Unspecified Error|->",port) - return - end - end - multi:newFunction(function(func) -- anom func, allows for fancy multitasking - local dupnickfilemanager=bin.stream(self.userFolder.."Nicks.dat",false) - local isValid=func:newCondition(function() return t~=nil end) - local tab={} - local t=dupnickfilemanager:getBlock("s") - if self.allowDuplicateNicks==false then - while func:condition(isValid) do - tab[#tab]=t - if t==nick then - self:send(ip,"!identity! REGISTERREFUSED <-|Duplicate Nicks are not allowed|->",port) - dupnickfilemanager:close() - return - end - end - t=dupnickfilemanager:getBlock("s") - end - dupnickfilemanager:addBlock(nick.."|"..bin.new(user):getHash(32)) - dupnickfilemanager:close() - bin.new(string.format("%s|%s|%s|%s\n",user,pass,nick,dTable)):tofile(self.userFolder..net.hash(user)..".dat") - self:send(ip,"!identity! REGISTEREDGOOD <-|"..user.."|->",port) - func=nil -- we dont want 1000s+ of these anom functions lying around - return - end)()-- lets call the function - end - return - elseif cmd=="login" then - local user,pass = arg1,arg2 - local _pass=s:getUserCred(user) - if not(self:_isRegistered(user)) then - self:send(ip,"!identity! LOGINBAD <-|nil|->",port) - return - end - if pass==_pass then - if self:userLoggedIn(cid) then - self.OnAlreadyLoggedIn:Fire(self,user,cid,ip,port) - self:send(ip,"!identity! ALREADYLOGGEDIN <-|nil|->",port) - return - end - local handle=self:loginUser(user,cid) -- binds the cid to username - self:send(ip,"!identity! LOGINGOOD <-|"..bin.ToStr(handle).."|->",port) - self.OnUserLoggedIn:Fire(user,cid,ip,port,bin.ToStr(handle)) - return - else - self:send(ip,"!identity! LOGINBAD <-|nil|->",port) - return - end - elseif cmd=="logout" then - self:logoutUser(user) - self.OnClientClosed:Fire(self,"User logged out!",cid,ip,port) - elseif cmd=="sync" then - local dTable = loadstring("return "..(arg4 or "{}"))() - local handle = self:getUserDataHandle(self:userLoggedIn(cid)) - table.merge(handle,dTable) - elseif cmd=="pass" then - local user=arg1 - if self:_isRegistered(user) then - self.OnPasswordForgotten:Fire(arg1,cid) - self:send(ip,"!identity! PASSREQUESTHANDLED <-|NONE|->",port) - else - self:send(ip,"!identity! NOUSER <-|"..user.."|->",port) - end - end - end) - s.OnClientClosed:connect(function(self,reason,cid,ip,port) - self.OnUserLoggerOut:Fire(self,self:userLoggedIn(cid),cid,reason) - end) - end,"identity") - --Client Stuff - net.OnClientCreated:connect(function(c) - c.userdata={} - c.OnUserLoggedIn=multi:newConnection() - c.OnBadLogin=multi:newConnection() - c.OnUserAlreadyRegistered=multi:newConnection() - c.OnUserAlreadyLoggedIn=multi:newConnection() - c.OnUserRegistered=multi:newConnection() - c.OnNoUserWithName=multi:newConnection() - c.OnPasswordRequest=multi:newConnection() - c.OnUserRegisterRefused=multi:newConnection() - function c:logout() - self:send("!identity! logout 'NONE' 'NONE' 'NONE' <-|nil|->") - end - c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered - local cmd,arg1 = data:match("!identity! (%S-) <%-|(.+)|%->") - if cmd=="REGISTERED" then - self.OnUserAlreadyRegistered:Fire(self,arg1) - elseif cmd=="REGISTEREDGOOD" then - self.OnUserRegistered:Fire(self,arg1) - elseif cmd=="REGISTERREFUSED" then - self.OnUserRegisterRefused:Fire(self,arg1) - elseif cmd=="ALREADYLOGGEDIN" then - self.OnUserAlreadyLoggedIn:Fire(self,arg1) - elseif cmd=="LOGINBAD" then - self.OnBadLogin:Fire(self) - elseif cmd=="LOGINGOOD" then - local dTable=loadstring("return "..(arg1 or "{}"))() - table.merge(self.userdata,dTable) - self.OnUserLoggedIn:Fire(self,self.userdata) - elseif cmd=="SYNC" then - local dTable=loadstring("return "..(arg1 or "{}"))() - table.merge(self.userdata,dTable) - elseif cmd=="NOUSER" then - self.OnNoUserWithName:Fire(self,arg1) - elseif cmd=="PASSREQUESTHANDLED" then - self.OnPasswordRequest:Fire(self) - end - end,"identity") - function c:syncUserData() - self:send(string.format("!identity! sync 'NONE' 'NONE' 'NONE' <-|%s|->",bin.ToStr(dTable))) - end - function c:forgotPass(user) - self:send(string.format("!identity! pass '%s' 'NONE' 'NONE' <-|nil|->",user)) - end - function c:getUserDataHandle() - return self.userdata - end - function c:logIn(user,pass) - self:send(string.format("!identity! login '%s' '%s' 'NONE' <-|nil|->",user,net.hash(pass))) - end - function c:register(user,pass,nick,dTable) - if dTable then - self:send(string.format("!identity! register '%s' '%s' '%s' <-|%s|->",user,net.hash(pass),nick,bin.ToStr(dTable))) - else - self:send(string.format("!identity! register '%s' '%s' '%s' <-|nil|->",user,net.hash(pass),nick)) - end - end - end) -end -if net.autoInit then - net.identity:init() -end diff --git a/mulit/examples/love2d Threading Example/core/net/inbox.lua b/mulit/examples/love2d Threading Example/core/net/inbox.lua deleted file mode 100644 index d76f37c..0000000 --- a/mulit/examples/love2d Threading Example/core/net/inbox.lua +++ /dev/null @@ -1,70 +0,0 @@ -require("net.identity") -require("net.aft") -require("net.users") -require("net.db") -net:registerModule("inbox",{1,0,0}) ---self.OnUserLoggedIn:Fire(user,cid,ip,port,bin.ToStr(handle)) ---allows the storing of messages that the user can recieve and view whenever. Allows user to also send messeges to users that are even offline! ---requires an account setup and nick name to be set at account creation -if not io.dirExists("INBOX") then - io.mkDir("INBOX") -end -net.inbox.dbfmt=db.format([=[ -[INBOX]{ - string MSG 0x800 -- contents of the message -} -[MAIL]{ - string NAME 0x20 -- username - string UID 0x10 -- User ID - string NICK 0x20 -- Nickname - number[3] DATE -- list of numbers - table INBO INBOX -- Inbox -} -]=]) -net.OnServerCreated:connect(function(s) - s.OnUserLoggedIn(function(user,cid,ip,port,dTable) - if not io.dirExists("INBOX/"..self:getUSERID(cid)) then -- Make sure inbox stuff is set up - io.mkDir("INBOX/"..self:getUSERID(cid)) - bin.new():tofile("info.dat") - end - end) - s.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP) - if self:userLoggedIn(cid) then -- If the user is logged in we do the tests - local cmd,arg1,arg2=data:match("!inbox! (%S+) (%S+) (%S+)") - if cmd=="SEND" then - -- - elseif cmd=="LIST" then - -- - elseif cmd=="OPEN" then - -- - elseif cmd=="DELETE" then - -- - elseif cmd=="CLEAR" then - -- - end - else - return - end - end,"inbox") -end) -net.OnClientCreated:connect(function(c) - c.OnDataRecieved(function(self,data) - -- - end,"inbox") - function c:sendMessage(USERID,msg) -- USERID who, msg being sent. Server handles time stamps - self:send("!inbox! SEND "..USERID.." "..msg) - end - function c:checkInbox() -- returns list of msgIDs - self:send("!inbox! LIST NIL NIL") - end - function c:checkMsg(msgId) - self:send("!inbox! OPEN "..msgId.." NIL") -- server sends back msg content as a file - end - function c:deleteMessage(msgID) - self:send("!inbox! DELETE "..msgId.." NIL") - end - function c:clearInbox() - self:send("!inbox! CLEAR NIL NIL") - end - -- -end) diff --git a/mulit/examples/love2d Threading Example/core/net/init.lua b/mulit/examples/love2d Threading Example/core/net/init.lua deleted file mode 100644 index 21f3db9..0000000 --- a/mulit/examples/love2d Threading Example/core/net/init.lua +++ /dev/null @@ -1,664 +0,0 @@ ---[[ - UPCOMMING ADDITIONS - AUDP - advance udp/ Ensures packets arrive and handles late packets. - P2P - peer to peer (Server to set up initial connection) - Relay - offput server load (locally) - Threading - Simple threading (UDP/AUDP Only) - Priority handling -]] ---[[ - TODO: Finish stuff for Priority handling -]] -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -function string.trim(s) - local from = s:match"^%s*()" - return from > #s and "" or s:match(".*%S", from) -end -socket=require("socket") -http=require("socket.http") -mime=require("mime") -net={} -net.Version={2,0,0} -- This will probably stay this version for quite a while... The modules on the otherhand will be more inconsistant -net._VERSION="2.0.0" -net.OnServerCreated=multi:newConnection() -net.OnClientCreated=multi:newConnection() -net.loadedModules={} -net.autoInit=true -function net.normalize(input) - local enc=mime.b64(input) - return enc -end -function net.denormalize(input) - local unenc=mime.unb64(input) - return unenc -end -function net.getLocalIP() - local someRandomIP = "192.168.1.122" - local someRandomPort = "3102" - local mySocket = socket.udp() - mySocket:setpeername(someRandomIP,someRandomPort) - local dat = (mySocket:getsockname()) - mySocket:close() - return dat -end -function net.getExternalIP() - local data=http.request("http://whatismyip.org/") - return data:match("600;\">(%d-.%d-.%d-.%d-)") -end -function net:registerModule(mod,version) - if net[mod] then - error("Module by the name: "..mod.." has already been registered! Remember some modules are internal and use certain names!") - end - table.insert(self.loadedModules,mod) - net[mod]={} - if version then - net[mod].Version=version - net[mod]._VERSION=version[1].."."..version[2].."."..version[3] - else - net[mod].Version={1,0,0} - net[mod]._VERSION={1,0,0} - end - return {Version=version,_VERSION=version[1].."."..version[2].."."..version[3]} -end -function net.getModuleVersion(ext) - if not ext then - return string.format("%d.%d.%d",net.Version[1],net.Version[2],net.Version[3]) - end - return string.format("%d.%d.%d",net[ext].Version[1],net[ext].Version[2],net[ext].Version[3]) -end -function net.resolveID(obj) - local num=math.random(10000000,99999999) - if obj[tostring(num)] then - return net.resolveID(obj) - end - obj.ids[tostring(num)]=true - return tostring(num) -end -function net.inList(list,dat) - for i,v in pairs(list) do - if v==dat then - return true - end - end - return false -end -function net.setTrigger(funcW,funcE) - multi:newTrigger(func) -end -net:registerModule("net",net.Version) --- Client broadcast -function net:newCastedClient(name) -- connects to the broadcasted server - local listen = socket.udp() -- make a new socket - listen:setsockname(net.getLocalIP(), 11111) - listen:settimeout(0) - local timer=multi:newTimer() - while true do - local data, ip, port = listen:receivefrom() - if timer:Get()>3 then - error("Timeout! Server by the name: "..name.." has not been found!") - end - if data then - local n,tp,ip,port=data:match("(%S-)|(%S-)|(%S-):(%d+)") - if n:match(name) then - print("Found Server!",n,tp,ip,port) - if tp=="tcp" then - return net:newTCPClient(ip,tonumber(port)) - else - return net:newClient(ip,tonumber(port)) - end - end - end - end -end --- UDP Stuff -function net:newServer(port,servercode) - local c={} - c.udp=assert(socket.udp()) - c.udp:settimeout(0) - c.udp:setsockname("*", port) - c.ips={} - c.Type="udp" - c.port=port - c.ids={} - c.servercode=servercode - c.bannedIPs={} - c.bannedCIDs={} - c.autoNormalization=false - function c:setUpdateRate(n) - print("Not needed in a udp server!") - end - function c:banCID(cid) - table.insert(self.bannedCIDs,cid) - end - function c:banIP(ip) - table.insert(self.bannedIPs,cid) - end - c.broad=socket.udp() - c.hostip=net.getLocalIP() - function c:broadcast(name) - local loop=multi:newTLoop(function(dt,loop) - self.broad:setoption('broadcast',true) - self.broad:sendto(name.."|"..self.Type.."|"..self.hostip..":"..self.port, "255.255.255.255", 11111) - self.broad:setoption('broadcast',false) - end,1) - end - function c:send(ip,data,port,cid) - if self.autoNormalization then - data=net.normalize(data) - end - if self.servercode then - cid=cid or self:CIDFrom(ip,port) - if not self.ips[cid] then - print("Can't determine cid from client... sending the client a new one!") - local cid=net.resolveID(self) - print("Sending unique cid to client: "..cid) - self.ips[cid]={ip,port,0,self.servercode==nil} - print(ip) - self.udp:sendto("I!"..cid,ip,port) - if self.servercode then - self.udp:sendto("S!",ip,port) - end - return - end - if net.inList(self.bannedIPs,ip) or net.inList(self.bannedCIDs,cid) then - self.udp:sendto("BANNED CLIENT", ip, port or self.port) - elseif self.ips[cid][4] then - self.udp:sendto(data, ip, port or self.port) - elseif self.ips[cid][4]==false then - self.udp:sendto("Make sure your server code is correct!", ip, port) - end - else - self.udp:sendto(data, ip, port or self.port) - end - end - function c:pollClientModules(ip,port) - self:send(ip,"L!",port) - end - function c:CIDFrom(ip,port) - for i,v in pairs(self.ips) do - if(ip==v[1] and v[2]==port) then - return i - end - end - end - function c:sendAll(data) - for i,v in pairs(self.ips) do - self:send(v[1],data,v[2],i) - end - end - function c:sendAllBut(data,cid) - for i,v in pairs(self.ips) do - if i~=cid then - self:send(v[1],data,v[2],i) - end - end - end - function c:clientRegistered(cid) - return self.ips[cid] - end - function c:clientLoggedIn(cid) - if not self.clientRegistered(cid) then - return nil - end - return self.ips[cid][4] - end - function c:update() - local data,ip,port=self.udp:receivefrom() - if net.inList(self.bannedIPs,ip) or net.inList(self.bannedCIDs,cid) then - print("We will ingore data from a banned client!") - return - end - if data then - if self.autoNormalization then - data=net.denormalize(data) - end - if data:sub(1,4)=="pong" then - --print("Recieved pong from: "..data:sub(5,-1)) - self.ips[data:sub(5,-1)][3]=os.clock() - elseif data:sub(1,2)=="S!" then - local cid=self:CIDFrom(ip,port) - if data:sub(3,-1)==self.servercode then - print("Servercode Accepted: "..self.servercode) - if self.ips[cid] then - self.ips[cid][4]=true - else - print("Server can't keep up! CID: "..cid.." has been skipped! Sending new CID to the client!") - local cid=net.resolveID(self) - print("Sending unique cid to client: "..cid) - self.ips[cid]={ip,port,0,self.servercode==nil} - print(ip) - self.udp:sendto("I!"..cid,ip,port) - if self.servercode then - self.udp:sendto("S!",ip,port) - end - end - else - self.udp:sendto("Make sure your server code is correct!", ip, port) - end - elseif data:sub(1,2)=="C!" then - local hook=(data:sub(11,-1)):match("!(.-)!") - self.OnDataRecieved:getConnection(hook):Fire(self,data:sub(11,-1),data:sub(3,10),ip,port) - elseif data:sub(1,2)=="E!" then - self.ips[data:sub(3,10)]=nil - obj.ids[data:sub(3,10)]=false - self.OnClientClosed:Fire(self,"Client Closed Connection!",data:sub(3,10),ip,port) - elseif data=="I!" then - local cid=net.resolveID(self) - print("Sending unique cid to client: "..cid) - self.ips[cid]={ip,port,os.clock(),self.servercode==nil} - print(ip) - self.udp:sendto("I!"..cid,ip,port) - if self.servercode then - self.udp:sendto("S!",ip,port) - end - self.OnClientConnected:Fire(self,cid,ip,port) - elseif data:sub(1,2)=="L!" then - cid,cList=data:sub(3,10),data:sub(11,-1) - local list={} - for m,v in cList:gmatch("(%S-):(%S-)|") do - list[m]=v - end - self.OnClientsModulesList:Fire(list,cid,ip,port) - end - end - for cid,dat in pairs(self.ips) do - if not((os.clock()-dat[3])<65) then - self.ips[cid]=nil - self.OnClientClosed:Fire(self,"Client lost Connection: ping timeout",cid,ip,port) - end - end - end - c.OnClientsModulesList=multi:newConnection() - c.OnDataRecieved=multi:newConnection() - c.OnClientClosed=multi:newConnection() - c.OnClientConnected=multi:newConnection() - c.connectiontest=multi:newAlarm(30) - c.connectiontest.link=c - c.connectiontest:OnRing(function(alarm) - --print("pinging clients!") - alarm.link:sendAll("ping") - alarm:Reset() - end) - multi:newLoop(function() - c:update() - end) - net.OnServerCreated:Fire(c) - return c -end - -function net:newClient(host,port,servercode,nonluaServer) - local c={} - c.ip=assert(socket.dns.toip(host)) - c.udp=assert(socket.udp()) - c.udp:settimeout(0) - c.udp:setpeername(c.ip, port) - c.cid="NIL" - c.lastPing=0 - c.Type="udp" - c.servercode=servercode - c.autoReconnect=true - c.autoNormalization=false - function c:pollPing(n) - return not((os.clock()-self.lastPing)<(n or 60)) - end - function c:send(data) - if self.autoNormalization then - data=net.normalize(data) - end - self.udp:send("C!"..self.cid..data) - end - function c:sendRaw(data) - if self.autoNormalization then - data=net.normalize(data) - end - self.udp:send(data) - end - function c:getCID() - if self:IDAssigned() then - return self.cid - end - end - function c:close() - self:send("E!") - end - function c:IDAssigned() - return self.cid~="NIL" - end - function c:update() - local data=self.udp:receive() - if data then - if self.autoNormalization then - data=net.denormalize(data) - end - if data:sub(1,2)=="I!" then - self.cid=data:sub(3,-1) - self.OnClientReady:Fire(self) - elseif data=="S!" then - self.udp:send("S!"..(self.servercode or "")) - elseif data=="L!" then - local mods="" - local m="" - for i=1,#net.loadedModules do - m=net.loadedModules[i] - mods=mods..m..":"..net.getModuleVersion(m).."|" - end - self.udp:send("L!"..self.cid..mods) - elseif data=="ping" then - self.lastPing=os.clock() - self.OnPingRecieved:Fire(self) - self.udp:send("pong"..self.cid) - else - local hook=data:match("!(.-)!") - self.OnDataRecieved:getConnection(hook):Fire(self,data) - end - end - end - function c:reconnect() - if not nonluaServer then - self.cid="NIL" - c.udp:send("I!") - end - self.OnConnectionRegained:Fire(self) - end - c.pingEvent=multi:newEvent(function(self) return self.link:pollPing() end) - c.pingEvent:OnEvent(function(self) - if self.link.autoReconnect then - self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout! Attempting to reconnect...") - self.link.OnClientDisconnected:Fire(self,"closed") - self.link:reconnect() - else - self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout!") - self.link.OnClientDisconnected:Fire(self,"closed") - end - end) - c.pingEvent.link=c - c.OnPingRecieved=multi:newConnection() - c.OnDataRecieved=multi:newConnection() - c.OnServerNotAvailable=multi:newConnection() - c.OnClientReady=multi:newConnection() - c.OnClientDisconnected=multi:newConnection() - c.OnConnectionRegained=multi:newConnection() - c.notConnected=multi:newFunction(function(self) - self:hold(3) - if self.link:IDAssigned()==false then - self.link.OnServerNotAvailable:Fire("Can't connect to the server: no response from server") - end - end) - c.notConnected.link=c - if not nonluaServer then - c.udp:send("I!") - end - multi:newLoop(function() - c:update() - end) - multi:newJob(function() c.notConnected() end) - net.OnClientCreated:Fire(c) - return c -end ---TCP Stuff -function net:newTCPServer(port) - local c={} - c.tcp=assert(socket.bind("*", port)) - c.tcp:settimeout(0) - c.ip,c.port=c.tcp:getsockname() - c.ips={} - c.port=port - c.ids={} - c.bannedIPs={} - c.Type="tcp" - c.rMode="*l" - c.sMode="*l" - c.updaterRate=1 - c.autoNormalization=false - c.updates={} - c.links={} - c.broad=socket.udp() - c.hostip=net.getLocalIP() - function c:broadcast(name) - local loop=multi:newTLoop(function(dt,loop) - self.broad:setoption('broadcast',true) - self.broad:sendto(name.."|"..self.Type.."|"..self.hostip..":"..self.port, "255.255.255.255", 11111) - self.broad:setoption('broadcast',false) - end,1) - end - function c:setUpdateRate(n) - self.updaterRate=n - end - function c:setReceiveMode(mode) - self.rMode=mode - end - function c:setSendMode(mode) - self.rMode=mode - end - function c:banCID(cid) - print("Function not supported on a tcp server!") - end - function c:banIP(ip) - table.insert(self.bannedIPs,cid) - end - function c:send(handle,data) - if self.autoNormalization then - data=net.normalize(data) - end - if self.sMode=="*l" then - handle:send(data.."\n") - else - handle:send(data) - end - end - function c:sendAllData(handle,data) - if self.autoNormalization then - data=net.normalize(data) - end - handle:send(data) - end - function c:pollClientModules(ip,port) - self:send(ip,"L!",port) - end - function c:CIDFrom(ip,port) - print("Method not supported when using a TCP Server!") - return "CIDs in TCP work differently!" - end - function c:sendAll(data) - for i,v in pairs(self.ips) do - self:send(v,data) - end - end - function c:sendAllBut(data,cid) - for i,v in pairs(self.ips) do - if not(cid==i) then - self:send(v,data) - end - end - end - function c:clientRegistered(cid) - return self.ips[cid] - end - function c:clientLoggedIn(cid) - return self.ips[cid] - end - function c:getUpdater(cid) - return self.updates[cid] - end - function c:update() - local client = self.tcp:accept(self.rMode) - if not client then return end - table.insert(self.ips,client) - client:settimeout(0) - --client:setoption('tcp-nodelay', true) - client:setoption('keepalive', true) - ip,port=client:getpeername() - if ip and port then - print("Got connection from: ",ip,port) - local updater=multi:newUpdater(skip) - self.updates[client]=updater - self.OnClientConnected:Fire(self,self.client,self.client,ip) - updater:OnUpdate(function(self) - local data, err = self.client:receive(self.rMode or self.Link.rMode) - if err=="closed" then - for i=1,#self.Link.ips do - if self.Link.ips[i]==self.client then - table.remove(self.Link.ips,i) - end - end - self.Link.OnClientClosed:Fire(self.Link,"Client Closed Connection!",self.client,self.client,ip) - self.Link.links[self.client]=nil -- lets clean up - self:Destroy() - end - if data then - if self.autoNormalization then - data=net.denormalize(data) - end - if net.inList(self.Link.bannedIPs,ip) then - print("We will ingore data from a banned client!") - return - end - local hook=data:match("!(.-)!") - self.Link.OnDataRecieved:getConnection(hook):Fire(self.Link,data,self.client,self.client,ip,self) - if data:sub(1,2)=="L!" then - cList=data - local list={} - for m,v in cList:gmatch("(%S-):(%S-)|") do - list[m]=v - end - self.Link.OnClientsModulesList:Fire(list,self.client,self.client,ip) - end - end - end) - updater:setSkip(self.updaterRate) - updater.client=client - updater.Link=self - function updater:setReceiveMode(mode) - self.rMode=mode - end - self.links[client]=updater - end - end - c.OnClientsModulesList=multi:newConnection() - c.OnDataRecieved=multi:newConnection() - c.OnClientClosed=multi:newConnection() - c.OnClientConnected=multi:newConnection() - multi:newLoop(function() - c:update() - end) - net.OnServerCreated:Fire(c) - return c -end -function net:newTCPClient(host,port) - local c={} - c.ip=assert(socket.dns.toip(host)) - c.port=port - c.tcp=socket.connect(c.ip,port) - if not c.tcp then - print("Can't connect to the server: no response from server") - return false - end - c.tcp:settimeout(0) - --c.tcp:setoption('tcp-nodelay', true) - c.tcp:setoption('keepalive', true) - c.Type="tcp" - c.autoReconnect=true - c.rMode="*l" - c.sMode="*l" - c.autoNormalization=false - function c:setReceiveMode(mode) - self.rMode=mode - end - function c:setSendMode(mode) - self.sMode=mode - end - function c:send(data) - if self.autoNormalization then - data=net.normalize(data) - end - if self.sMode=="*l" then - ind,err=self.tcp:send(data.."\n") - else - ind,err=self.tcp:send(data) - end - if err=="closed" then - self.OnClientDisconnected:Fire(self,err) - elseif err=="timeout" then - self.OnClientDisconnected:Fire(self,err) - elseif err then - print(err) - end - end - function c:sendRaw(data) - if self.autoNormalization then - data=net.normalize(data) - end - self.tcp:send(data) - end - function c:getCID() - return "No Cid on a tcp client!" - end - function c:close() - self.tcp:close() - end - function c:IDAssigned() - return true - end - function c:update() - if not self.tcp then return end - local data,err=self.tcp:receive() - if err=="closed" then - self.OnClientDisconnected:Fire(self,err) - elseif err=="timeout" then - self.OnClientDisconnected:Fire(self,err) - elseif err then - print(err) - end - if data then - if self.autoNormalization then - data=net.denormalize(data) - end - local hook=data:match("!(.-)!") - self.OnDataRecieved:getConnection(hook):Fire(self,data) - end - end - function c:reconnect() - multi:newFunction(function(func) - self.tcp=socket.connect(self.ip,self.port) - if self.tcp==nil then - print("Can't connect to the server: No response from server!") - func:hold(3) - self:reconnect() - return - end - self.OnConnectionRegained:Fire(self) - self.tcp:settimeout(0) - --self.tcp:setoption('tcp-nodelay', true) - self.tcp:setoption('keepalive', true) - end) - end - c.event=multi:newEvent(function(event) - return event.link:IDAssigned() - end) - c.event:OnEvent(function(event) - event.link.OnClientReady:Fire(event.link) - end) - c.event.link=c - c.OnClientReady=multi:newConnection() - c.OnClientDisconnected=multi:newConnection() - c.OnDataRecieved=multi:newConnection() - c.OnConnectionRegained=multi:newConnection() - multi:newLoop(function() - c:update() - end) - net.OnClientCreated:Fire(c) - return c -end diff --git a/mulit/examples/love2d Threading Example/core/net/logging.lua b/mulit/examples/love2d Threading Example/core/net/logging.lua deleted file mode 100644 index be82728..0000000 --- a/mulit/examples/love2d Threading Example/core/net/logging.lua +++ /dev/null @@ -1,7 +0,0 @@ -net.OnServerCreated:connect(function(s) - print("The logging Module has been loaded onto the server!") - s.OnDataRecieved:fConnect(function(self,data,cid,ip,port) - log(tostring(ip)..":"..tostring(port),"Server-log.log") - log(data,"Server-log.log") - end) -end) diff --git a/mulit/examples/love2d Threading Example/core/net/loggingWIP.lua b/mulit/examples/love2d Threading Example/core/net/loggingWIP.lua deleted file mode 100644 index be82728..0000000 --- a/mulit/examples/love2d Threading Example/core/net/loggingWIP.lua +++ /dev/null @@ -1,7 +0,0 @@ -net.OnServerCreated:connect(function(s) - print("The logging Module has been loaded onto the server!") - s.OnDataRecieved:fConnect(function(self,data,cid,ip,port) - log(tostring(ip)..":"..tostring(port),"Server-log.log") - log(data,"Server-log.log") - end) -end) diff --git a/mulit/examples/love2d Threading Example/core/net/p2p.lua b/mulit/examples/love2d Threading Example/core/net/p2p.lua deleted file mode 100644 index a1ece36..0000000 --- a/mulit/examples/love2d Threading Example/core/net/p2p.lua +++ /dev/null @@ -1,31 +0,0 @@ -net:registerModule("p2p",{1,0,0}) -net.p2p.peerdata={} ---[[ -PID(peerID)= - -]] -function net.newP2PClient(host,port) - -- -end -function net.aft:init() -- calling this initilizes the library and binds it to the servers and clients created - --Server Stuff - net.OnServerCreated:connect(function(s) - print("The aft(Advance File Transfer) Module has been loaded onto the server!") - if s.Type~="udp" then - print("As of right now p2p is only avaliable using udp!") - return "ERR_NOT_UDP" - end - s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered - -- - end,"p2p") -- some new stuff - end) - --Client Stuff - net.OnClientCreated:connect(function(c) - c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered - -- - end,"p2p") - end) -end -if net.autoInit then - net.aft.init() -end diff --git a/mulit/examples/love2d Threading Example/core/net/p2pWIP.lua b/mulit/examples/love2d Threading Example/core/net/p2pWIP.lua deleted file mode 100644 index a1ece36..0000000 --- a/mulit/examples/love2d Threading Example/core/net/p2pWIP.lua +++ /dev/null @@ -1,31 +0,0 @@ -net:registerModule("p2p",{1,0,0}) -net.p2p.peerdata={} ---[[ -PID(peerID)= - -]] -function net.newP2PClient(host,port) - -- -end -function net.aft:init() -- calling this initilizes the library and binds it to the servers and clients created - --Server Stuff - net.OnServerCreated:connect(function(s) - print("The aft(Advance File Transfer) Module has been loaded onto the server!") - if s.Type~="udp" then - print("As of right now p2p is only avaliable using udp!") - return "ERR_NOT_UDP" - end - s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered - -- - end,"p2p") -- some new stuff - end) - --Client Stuff - net.OnClientCreated:connect(function(c) - c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered - -- - end,"p2p") - end) -end -if net.autoInit then - net.aft.init() -end diff --git a/mulit/examples/love2d Threading Example/core/net/relay.lua b/mulit/examples/love2d Threading Example/core/net/relay.lua deleted file mode 100644 index f1f267c..0000000 --- a/mulit/examples/love2d Threading Example/core/net/relay.lua +++ /dev/null @@ -1,24 +0,0 @@ -require("net") -net:registerModule("relay",{1,0,0}) -net.OnServerCreated:connect(function(s) - s.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP) - local IP="" - if self.Type=="tcp" then - error("Relays only work when using UDP or AUDP! They will not function with TCP! Support may one day be added for TCP!") - else - IP=IP_OR_HANDLE - end - local cmd,dat=data:match("!relay! (%S-) (.+)") - if cmd == "RELAY" then - -- - elseif cmd == "LOAD" then - local cpuload=multi:getLoad() - self:send(IP_OR_HANDLE,"!relay! LOAD "..cpuload,PORT_OR_IP) - end - end,"relay") -end) -net.OnClientCreated:connect(function(c) - c.OnDataRecieved(function(self,data) - -- - end,"relay") -end) diff --git a/mulit/examples/love2d Threading Example/core/net/settings.lua b/mulit/examples/love2d Threading Example/core/net/settings.lua deleted file mode 100644 index de9c190..0000000 --- a/mulit/examples/love2d Threading Example/core/net/settings.lua +++ /dev/null @@ -1,48 +0,0 @@ -require("net") ---General Stuff ---[[ What this module does! -Adds -net.settings:init() -server:regSetting(namespace,setting) -]] -net:registerModule("settings",{1,0,0}) -net.settings.config={} -function net.settings:init() -- calling this initilizes the library and binds it to the servers and clients created - --Server Stuff - net.OnServerCreated:connect(function(s) - print("The Settings Module has been loaded onto the server!") - s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered - local namespace,args=data:match("!settings! (%s+) (.+)") - local args - if namespace then - for i,v in pairs(net.settings.config) do - args={data:match(v[1])} - if #args~=0 then - v[2]:Fire(self,data,cid,ip,port,unpack(args)) - break - end - end - end - end,"settings") - function s:regSetting(namespace,settings) - if not net.settings.config[namespace] then - net.settings.config[namespace]={} - end - local connection=multi:newConnection() - table.insert(net.settings.config[namespace],{"!settings! "..namespace.." "..settings,connection}) - return connection - end - end) - --Client Stuff - net.OnClientCreated:connect(function(c) - c.OnDataRecieved:(function(self,data) -- when the client recieves data this method is triggered - --First Lets make sure we are getting Setting data - end,"setings") - function sendSetting(namespace,args) - self:send("!settings! "..namespace.." "..args) - end - end) -end -if net.autoInit then - net.settings:init() -end diff --git a/mulit/examples/love2d Threading Example/core/net/settingsWIP.lua b/mulit/examples/love2d Threading Example/core/net/settingsWIP.lua deleted file mode 100644 index de9c190..0000000 --- a/mulit/examples/love2d Threading Example/core/net/settingsWIP.lua +++ /dev/null @@ -1,48 +0,0 @@ -require("net") ---General Stuff ---[[ What this module does! -Adds -net.settings:init() -server:regSetting(namespace,setting) -]] -net:registerModule("settings",{1,0,0}) -net.settings.config={} -function net.settings:init() -- calling this initilizes the library and binds it to the servers and clients created - --Server Stuff - net.OnServerCreated:connect(function(s) - print("The Settings Module has been loaded onto the server!") - s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered - local namespace,args=data:match("!settings! (%s+) (.+)") - local args - if namespace then - for i,v in pairs(net.settings.config) do - args={data:match(v[1])} - if #args~=0 then - v[2]:Fire(self,data,cid,ip,port,unpack(args)) - break - end - end - end - end,"settings") - function s:regSetting(namespace,settings) - if not net.settings.config[namespace] then - net.settings.config[namespace]={} - end - local connection=multi:newConnection() - table.insert(net.settings.config[namespace],{"!settings! "..namespace.." "..settings,connection}) - return connection - end - end) - --Client Stuff - net.OnClientCreated:connect(function(c) - c.OnDataRecieved:(function(self,data) -- when the client recieves data this method is triggered - --First Lets make sure we are getting Setting data - end,"setings") - function sendSetting(namespace,args) - self:send("!settings! "..namespace.." "..args) - end - end) -end -if net.autoInit then - net.settings:init() -end diff --git a/mulit/examples/love2d Threading Example/core/net/sft.lua b/mulit/examples/love2d Threading Example/core/net/sft.lua deleted file mode 100644 index b695fc9..0000000 --- a/mulit/examples/love2d Threading Example/core/net/sft.lua +++ /dev/null @@ -1,179 +0,0 @@ -require("net") ---General Stuff ---[[ What this module does! -Adds - -]] -function io.fileExists(path) - g=io.open(path or '','r') - if path =='' then - p='empty path' - return nil - end - if g~=nil and true or false then - p=(g~=nil and true or false) - end - if g~=nil then - io.close(g) - else - return false - end - return p -end -net:registerModule("sft",{1,0,0}) -function net.sft:init() -- calling this initilizes the library and binds it to the servers and clients created - --Server Stuff - net.OnServerCreated:connect(function(s) - print("The sft(Simple File Transfer) Module has been loaded onto the server!") - if s.Type~="tcp" then - print("It is recomended that you use tcp to transfer files!") - end - s.transfers={} - s.OnUploadRequest=multi:newConnection() -- create a sft event - s.OnFileUploaded=multi:newConnection() -- create a sft event - s.OnDownloadRequest=multi:newConnection() - s.OnDataRecieved(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered - --First Lets make sure we are getting sft data - --filename,dat=data:match("!sft! (%S-) (%S+)") - local cmd,arg1,arg2=data:match("!sft! (%S-) (%S-) (.+)") - if cmd=="tstart" then - local rets=self.OnUploadRequest:Fire(self,cid,ip,port) - for i=1,#rets do - if rets[i][1]==false then - print("Server refused to accept upload request!") - self:send(ip,"!sft! CANTUPLOAD NIL NIL",port) - return - end - end - local ID,streamable=arg1:match("(.+)|(.+)") - local file,hash=arg2:match("(.+)|(.+)") - if streamable~="NIL" then - self.transfers[ID]={bin.stream(streamable,false),hash,file} - else - self.transfers[ID]={bin.new(""),hash,file} - end - return - elseif cmd=="transfer" then - if self.transfers[arg1]~=nil then - self.transfers[arg1][1]:tackE(bin.fromhex(arg2)) - --print(self.transfers[arg1][1]:getSize()) - end - return - elseif cmd=="tend" then - if self.transfers[arg1]~=nil then - if self.transfers[arg1][1]:getHash(32)==self.transfers[arg1][2] then - self.OnFileUploaded:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Good!") - else - print("Hash Error!") - self.OnFileUploaded:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Bad!") - end - self.transfers[arg1]=nil - end - return - end - local filename=cmd - local dat=arg1 - if filename==nil then return end - local rets=self.OnDownloadRequest:Fire(self,cid,ip,port) - for i=1,#rets do - if rets[i][1]==false then - print("Server refused to accept download request!") - self:send(ip,"!sft! CANTREQUEST NIL NIL",port) - return - end - end - if io.fileExists(filename) then - --Lets first load the file - local file=bin.stream(filename,false) - local size=file:getSize() - local pieceSize=512 - local pieces=math.ceil(size/pieceSize) - local step=multi:newStep(1,pieces) - step.TransferID=tostring(math.random(1000,9999)) - step.sender=self - step.ip=ip - step.port=port - step.pieceSize=pieceSize - step:OnStart(function(self) - self.sender:send(self.ip,"!sft! TSTART "..self.TransferID.."|"..dat.." "..filename.."|"..file:getHash(32),self.port) - end) - step:OnStep(function(pos,self) - self:hold(.01) - self.sender:send(self.ip,"!sft! TRANSFER "..self.TransferID.." "..bin.tohex(file:sub(((self.pieceSize*pos)+1)-self.pieceSize,self.pieceSize*pos)),self.port) - end) - step:OnEnd(function(self) - self.sender:send(self.ip,"!sft! TEND "..self.TransferID.." NIL",self.port) - end) - else - self:send(ip,"!sft! CANTREQUEST NIL NIL",port) - end - end,"sft") - end) - --Client Stuff - net.OnClientCreated:connect(function(c) - c.transfers={} - c.OnTransferStarted=multi:newConnection() -- create a sft event - c.OnTransferFinished=multi:newConnection() -- create a sft event - c.OnFileRequestFailed=multi:newConnection() -- create a sft event - c.OnFileUploadFailed=multi:newConnection() -- create a sft event - c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered - --First Lets make sure we are getting sft data - local cmd,arg1,arg2=data:match("!sft! (%S-) (%S-) (.+)") - if cmd=="TSTART" then - local ID,streamable=arg1:match("(.+)|(.+)") - local file,hash=arg2:match("(.+)|(.+)") - if streamable~="NIL" then - self.transfers[ID]={bin.stream(streamable,false),hash,file} - else - self.transfers[ID]={bin.new(""),hash,file} - end - self.OnTransferStarted:Fire(self) - elseif cmd=="TRANSFER" then - self.transfers[arg1][1]:tackE(bin.fromhex(arg2)) - elseif cmd=="TEND" then - if self.transfers[arg1][1]:getHash(32)==self.transfers[arg1][2] then - self.OnTransferFinished:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Good!") - else - print("Hash Error!") - self.OnTransferFinished:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Bad!") - end - self.transfers[arg1]=nil - elseif cmd=="CANTREQUEST" then - self.OnFileRequestFailed:Fire(self,"Could not request the file for some reason!") - elseif cmd=="CANTUPLOAD" then - self.OnFileUploadFailed:Fire(self,"Could not upload the file for some reason!") - end - end,"sft") - function c:uploadFile(filename) - if io.fileExists(filename) then - local file=bin.stream(filename,false) - local size=file:getSize() - local pieceSize=512 - local pieces=math.ceil(size/pieceSize) - local step=multi:newStep(1,pieces) - step.TransferID=tostring(math.random(1000,9999)) - step.sender=self - step.pieceSize=pieceSize - step:OnStart(function(self) - self.sender:send("!sft! tstart "..self.TransferID.."|NIL "..filename.."|"..file:getHash(32)) - end) - step:OnStep(function(pos,self) - self:hold(.01) - self.sender:send("!sft! transfer "..self.TransferID.." "..bin.tohex(file:sub(((self.pieceSize*pos)+1)-self.pieceSize,self.pieceSize*pos))) - end) - step:OnEnd(function(self) - print("Request done!") - self.sender:send("!sft! tend "..self.TransferID.." NIL") - end) - else - self.OnFileUploadFailed:Fire(self,filename,"File does not exist!") - end - end - function c:requestFile(filename) - self:send("!sft! "..filename.." NIL NIL NIL") - end - end) -end -if net.autoInit then - net.sft.init() -end diff --git a/mulit/examples/love2d Threading Example/core/net/status.lua b/mulit/examples/love2d Threading Example/core/net/status.lua deleted file mode 100644 index ae79213..0000000 --- a/mulit/examples/love2d Threading Example/core/net/status.lua +++ /dev/null @@ -1,44 +0,0 @@ -print([[ -the 'admin' module STATUS: 0 -the 'aft' module STATUS: 9 -the 'chatting' module STATUS: 5 -the 'db' module STATUS: 1 -the 'email' module STATUS: 2 -the 'identity' module STATUS: 7 -the 'inbox' module STATUS: 1 -the 'init' module STATUS: 9 Not a module, but the core of the program -the 'logging' module STATUS: 8 -the 'p2p' module STATUS: 1 -the 'settings' module STATUS: 3 -the 'sft' module STATUS: 10 -the 'status' module STATUS: 5 -the 'threading' module STATUS: 1 -the 'users' module STATUS: 1 -the 'version' module STATUS: 2 - -STATUS: -0: The idea is there but no progress to actual coding has been made -1: The idea has been coded and thoughts well defined. However only a frame is existing atm -2: The module has limited functionality, but gets its basic function through -3: The module has decent functionality, but needs much more -4: The module functions are stable and works great, however not all of the original idea has been completed -5: The module functions are stable and works great, most of the functions have been fleshed out aside for a few minor ones -6: The module has all features completed and is stable for average use, minor bugs are present. -7: The module has few to no bugs, and is currently being made more secure -8: The module is very secure and odds are it wont crash unless they were implemented wrong -9: The module has most if not all exception handled so even incorrect implementation will be 'error free' Probably wont change, but if it does it will be a huge change! -10: The module is never going to change from its current status! It is done. - -NOTE: once a module reaches a status of 4, it will always be backward compatable. server-client relations will be safe! - -Each module has a version -1.0.0 -A.M.m -addition.Major.minor -whenever a new addition is added the A is increased... You must update to make use of that feature -When a major addition or change Major is incresed. This can be code breaking... However I will try my best to make at least client side code compatible with future changes -when a minor addition or change is made minor in incresed - -Why client side stabality in code changes? -Until the update module can seamless update your modules I will ensure that client code can work regardless of server version starting from this version -]]) diff --git a/mulit/examples/love2d Threading Example/core/net/threading.lua b/mulit/examples/love2d Threading Example/core/net/threading.lua deleted file mode 100644 index 50299ef..0000000 --- a/mulit/examples/love2d Threading Example/core/net/threading.lua +++ /dev/null @@ -1,41 +0,0 @@ ---[=[ About This Module! - This module is server side only! (Might add client side if requested) - Aim is to make each lane (thread) have no more than 'n' number of connections - This module hyjacks the multi:newConnection() function to seemlessly add support for threads without you having to change much - As long as each server-client connection is isolated you should be fine - The chatting module however IS NOT an isolated module, so take a look at how data was handled in that module to allow for both - threaded and non threaded use - - How? - When this module is loaded all server creation is altered by passing a proxyServer instead of an actual server object - for example: - proxy=net:newTCPServer(12345) - proxy:OnDataRecieved(function(self,data,cid,ip,port) - self:send("My data!") - end) - the real server instance could be on any of the threads. Careful! While using this is seemless becareful of IO opperations! -]=] ---~ net:registerModule("threading",{1,0,0}) ---~ if not(lanes) then error("Require the lanes module!") end ---~ local serverlinda = lanes.linda() ---~ net.threading.newServer=net.newServer -- store the original method ---~ net.threading.newTCPServer=net.newTCPServer -- store the original method ---~ net.threading.proxy={} -- namespace for the proxy stuff. Because of the desgin intention of both UDP/TCP servers Only one proxy is needed -print({}) - ---~ lanes=require("lanes") ---~ serverlinda = lanes.linda() ---~ mt={ ---~ __index=function(t,k) print("IND",t,k) end, ---~ __newindex=function(t,k,v) print("NewIND",t,k,v) end, ---~ } ---~ test={} ---~ setmetatable(test,mt) ---~ test.a="hi" ---~ test.a=true ---~ g=test['a'] ---~ print(test.b) - - ---~ setmetatable(net.threading.proxy,mt) -- set the proxies metatable, to prevent bleeding only create one server. - diff --git a/mulit/examples/love2d Threading Example/core/net/threadingWIP.lua b/mulit/examples/love2d Threading Example/core/net/threadingWIP.lua deleted file mode 100644 index c83b2c2..0000000 --- a/mulit/examples/love2d Threading Example/core/net/threadingWIP.lua +++ /dev/null @@ -1,37 +0,0 @@ ---[=[ About This Module! - This module is server side only! (Might add client side if requested) - Aim is to make each lane (thread) have no more than 'n' number of connections - This module hyjacks the multi:newConnection() function to seemlessly add support for threads without you having to change much - As long as each server-client connection is isolated you should be fine - The chatting module however IS NOT an isolated module, so take a look at how data was handled in that module to allow for both - threaded and non threaded use - - How? - When this module is loaded all server creation is altered by passing a proxyServer instead of an actual server object - for example: - proxy=net:newTCPServer(12345) - proxy:OnDataRecieved(function(self,data,cid,ip,port) - self:send("My data!") - end) - the real server instance could be on any of the threads. Careful! While using this is seemless becareful of IO opperations! -]=] ---~ net:registerModule("threading",{1,0,0}) ---~ if not(lanes) then error("Require the lanes module!") end ---~ local serverlinda = lanes.linda() ---~ net.threading.newServer=net.newServer -- store the original method ---~ net.threading.newTCPServer=net.newTCPServer -- store the original method ---~ net.threading.proxy={} -- namespace for the proxy stuff. Because of the desgin intention of both UDP/TCP servers Only one proxy is needed -lanes=require("lanes") -serverlinda = lanes.linda() -mt={ - __index=function(t,k) print("IND",t,k) end, - __newindex=function(t,k,v) print("NewIND",t,k,v) end, -} -test={} -setmetatable(test,mt) -test.a="hi" -test.a=true -g=test['a'] -print(test.b) ---~ setmetatable(net.threading.proxy,mt) -- set the proxies metatable, to prevent bleeding only create one server. - diff --git a/mulit/examples/love2d Threading Example/core/net/users.lua b/mulit/examples/love2d Threading Example/core/net/users.lua deleted file mode 100644 index f99f2ec..0000000 --- a/mulit/examples/love2d Threading Example/core/net/users.lua +++ /dev/null @@ -1,37 +0,0 @@ -require("net.identity") --[[ This module extends the functions of the identity module -It aims to make the handling of users who are not online more seamless. -Without this handling offline users is a pain. -]] -net:registerModule("users",{1,0,0}) -net.users.online={} -- all online users and offline users -net.users.offline={} -- all online users and offline users -net.OnServerCreated:connect(function(s) - s.OnUserLoggedIn(function(user,cid,ip,port,dTable) - -- - end) - s.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP) - if self:userLoggedIn(cid) then -- If the user is logged in we do the tests - -- - else - return - end - end,"users") -end) -net.OnClientCreated:connect(function(c) - c.OnUserList=multi:newConnection() - c.OnDataRecieved(function(self,data) - -- - end,"users") - function c:searchUsers(nickname) -- sends a query to the server, returns list of userids and nicks close to the query - -- - end - function c:addFriend(USERID) - -- - end - function c:removeFriend(USERID) - -- - end - function c:getFriends(USERID) - -- - end -end) diff --git a/mulit/examples/love2d Threading Example/core/net/version.lua b/mulit/examples/love2d Threading Example/core/net/version.lua deleted file mode 100644 index 258bb4b..0000000 --- a/mulit/examples/love2d Threading Example/core/net/version.lua +++ /dev/null @@ -1,43 +0,0 @@ -require("net") -require("net.aft") -net:registerModule("version",{1,0,0}) -- allows communication of versions for modules -net.version.HOSTS={ - ["Lua"]=1, - ["LuaJIT"]=1, - ["Love2d"]=2, -- Yes love2d uses luaJIT, but the filesystem works a bit differently - ["Corona"]=3, -} -net.version.OS={ - ["Windows"]=1, - ["Unix"]=2, - ["RPI"]=3, -} ---net.version.EOL="\60\69\110\100\45\79\102\45\70\105\108\101\45\84\114\97\110\115\102\101\114\62" -net.OnServerCreated:connect(function(s) - s.OnDataRecieved(function(self,data,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP) - local cmd,arg1,arg2=data:match("!version! ") - end,"version") - s.OnClientConnected(function(self,CID_OR_HANDLE,IP_OR_HANDLE,PORT_OR_IP) - multi:newFunction(function(func) -- anom func, allows for fancy multitasking - multi:newFunction(function(self) - local range=self:newRange() - for i in range(1,#self.loadedModules) do - local mod=self.loadedModules[i] - self:send(IP_OR_HANDLE,"!version! CHECK "..mod.." NIL",PORT_OR_IP) -- sends command to client to return the version of the module - end - end)() - func=nil -- we dont want 1000s+ of these anom functions lying around - end)()-- lets call the function - self:send(IP_OR_HANDLE,"!version! HOST NIL NIL",PORT_OR_IP) - end) -end) -net.OnClientCreated:connect(function(c) - c.OnDataRecieved(function(self,data) - local cmd,module,arg1=data:match("!version! (%S+) (%S+) (%S+)") - if cmd=="CHECK" then - self:send("!version! VER "..self.loadedModules[module].." "..net.getModuleVersion(module)) - elseif cmd=="UPDATE" then - -- - end - end,"version") -end) diff --git a/mulit/examples/love2d Threading Example/core/parseManager/AICM.lua b/mulit/examples/love2d Threading Example/core/parseManager/AICM.lua deleted file mode 100644 index 23496fa..0000000 --- a/mulit/examples/love2d Threading Example/core/parseManager/AICM.lua +++ /dev/null @@ -1,37 +0,0 @@ -AICM={} -AICM.functions={ - getAICMVersion=function(self) - return "1.0.0" - end, -} -function AICM:InitSyntax(obj,name) - obj:debug("Now using the Artificial Intelligence Communication module!") - obj.OnExtendedBlock(self.blockModule) - obj.OnCustomSyntax(self.syntaxModule) - obj:define(self.functions) -end -AICM.syntaxModule=function(self,line) - pVars,mStr=line:match("p%((.-)%)(.+)") - if pVars then - local vRef,vars=pVars:match("(.-):(.+)") - if vars:find(",") then - vars={unpack(vars:split(","))} - else - vars={vars} - end - tab={self:varExists(vRef):match(mStr)} -- self:varExists allows for all internal structures to just work - for i=1,#tab do - if vars[i] then - self._variables[vars[i]]=tab[i] - end - end - self:p() -- requried to progress the script - return { - text=line, - Type="AICMModule" - } - end -end -AICM.blockModule=function(obj,name,t,chunk,filename) - -- -end diff --git a/mulit/examples/love2d Threading Example/core/parseManager/EBIM.lua b/mulit/examples/love2d Threading Example/core/parseManager/EBIM.lua deleted file mode 100644 index 08ac193..0000000 --- a/mulit/examples/love2d Threading Example/core/parseManager/EBIM.lua +++ /dev/null @@ -1,71 +0,0 @@ -EBIM={} -EBIM.functions={ - getEBIMVersion=function(self) - return "1.0.0" - end, -} -EBIM.registry={} -function EBIM:registerEBlock(name,func) - self.registry[name]=func -end -function EBIM:InitSyntax(obj,name) - obj:debug("Now using the Extended Block Interface module!") - obj.OnExtendedBlock(self.blockModule) - obj.OnCustomSyntax(self.syntaxModule) - obj:define(self.functions) -end -EBIM.syntaxModule=function(self,line) - local cmd,args=line:match("(.-) (.+):") - if cmd then - local goal=nil - local _tab={} - for i=self.pos+1,#self._cblock do - if self._cblock[i]=="end"..cmd then - goal=i - break - else - table.insert(_tab,self._cblock[i]) - end - end - if goal==nil then - self:pushError("'end"..cmd.."' Expected to close '"..cmd.."'") - end - if EBIM.registry[cmd] then - EBIM.registry[cmd](self,args,_tab) - self.pos=goal+1 - else - self:pushError("Unknown command: "..cmd) - end - return { - Type="EBIM-Data", - text=cmd.." Block" - } - else - return - end -end -EBIM.blockModule=function(obj,name,t,chunk,filename) - --print(">: ",obj,name,t,chunk,filename) -end -EBIM:registerEBlock("string",function(self,args,tab) - local str={} - for i=1,#tab do - table.insert(str,tab[i]) - end - self:setVariable(args,table.concat(str,"\n")) -end) -EBIM:registerEBlock("list",function(self,args,tab) - local str={} - for i=1,#tab do - table.insert(str,self:varExists(tab[i])) - end - self:setVariable(args,str) -end) -EBIM:registerEBlock("dict",function(self,args,tab) - local str={} - for i=1,#tab do - local a,b=tab[i]:match("(.-):%s*(.+)") - str[a]=self:varExists(b) - end - self:setVariable(args,str) -end) diff --git a/mulit/examples/love2d Threading Example/core/parseManager/bytecode.lua b/mulit/examples/love2d Threading Example/core/parseManager/bytecode.lua deleted file mode 100644 index 26fb46f..0000000 --- a/mulit/examples/love2d Threading Example/core/parseManager/bytecode.lua +++ /dev/null @@ -1,44 +0,0 @@ --- In an attempt to speed up my library I will use a virtual machine that runs bytecode -compiler={} -compiler.cmds={ -- list of all of the commands - EVAL="\01", -- evaluate - SPLT="\02", -- split - TRIM="\03", -- trim - VEXT="\04", -- variable exists - ILST="\05", -- is a list - LSTR="\06", -- load string - FCAL="\07", -- Function call - SVAR="\08", -- set variable - LOAD="\09", -- load file - LAOD="\10", -- _load file - DEFN="\11", -- define external functions - HCBK="\12", -- Has c Block - CMBT="\13", -- combine truths - SETB="\14", -- set block - STRT="\15", -- start - PERR="\16", -- push error - PROG="\17", -- progress - PHED="\18", -- parse header - SSLT="\19", -- split string - NEXT="\20", -- next - -- Needs refining... One step at a time right! -} -function compiler:compile(filename) -- compiles the code into bytecode - -- First we load the code but don't run it - local engine=parseManager:load(filename) - -- This captures all of the methods and important info. This also ensures that the compiler and interperter stay in sync! - local bytecodeheader=bin.new() -- header will contain the order of blocks and important flags - local bytecode=bin.newDataBuffer() -- lets leave it at unlimited size because we don't know how long it will need to be - local functions={} -- will be populated with the important methods that must be preloaded - local prebytecode={} -- this contains bytecode that has yet to be sterilized - for blockname,blockdata in pairs(engine._chunks) do - -- lets get some variables ready - local code,_type,nextblock,filename=blockdata[1],blockdata[2],blockdata.next,blockdata.file - -- note nextblock may be nil on 2 condidions. The first is when the leaking flag is disabled and the other is when the block in question was the last block defined - local lines=bin._lines(code) - print("\n["..blockname.."]\n") - for i=1,#lines do - print(lines[i]) - end - end -end diff --git a/mulit/examples/love2d Threading Example/core/parseManager/init.lua b/mulit/examples/love2d Threading Example/core/parseManager/init.lua deleted file mode 100644 index af90212..0000000 --- a/mulit/examples/love2d Threading Example/core/parseManager/init.lua +++ /dev/null @@ -1,1277 +0,0 @@ -function trim(s) - return s:match'^()%s*$' and '' or s:match'^%s*(.*%S)' -end -parseManager={} -parseManager._VERSION={1,0,0} -dialogueManager=parseManager -- for backwards purposes -parseManager.OnExtendedBlock=multi:newConnection(true) -- true protects the module from crashes -parseManager.OnCustomSyntax=multi:newConnection(true) -- true protects the module from crashes -function string:split( inSplitPattern, outResults ) - if not outResults then - outResults = {} - end - local theStart = 1 - local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart ) - while theSplitStart do - table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) ) - theStart = theSplitEnd + 1 - theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart ) - end - table.insert( outResults, string.sub( self, theStart ) ) - return outResults -end -function parseManager:debug(txt) - if self.stats.debugging then - self._methods:debug(txt) - end -end -function parseManager.split(s,pat) - local pat=pat or "," - local res = {} - local start = 1 - local state = 0 - local c = '.' - local elem = '' - for i = 1, #s do - c = s:sub(i, i) - if state == 0 or state == 3 then -- start state or space after comma - if state == 3 and c == ' ' then - state = 0 -- skipped the space after the comma - else - state = 0 - if c == '"' or c=="'" then - state = 1 - elem = elem .. '"' - elseif c=="[" then - state = 1 - elem = elem .. '[' - elseif c == pat then - res[#res + 1] = elem - elem = '' - state = 3 -- skip over the next space if present - else - elem = elem .. c - end - end - elseif state == 1 then -- inside quotes - if c == '"' or c=="'" then --quote detection could be done here - state = 0 - elem = elem .. '"' - elseif c=="]" then - state = 0 - elem = elem .. ']' - elseif c == '\\' then - state = 2 - else - elem = elem .. c - end - elseif state == 2 then -- after \ in string - elem = elem .. c - state = 1 - end - end - res[#res + 1] = elem - return res -end -parseManager._chunks={} -parseManager._cblock={} -parseManager._cblockname="" -parseManager._pos=1 -parseManager._labels={ - -- {chunkname,pos} -} -parseManager.stats={ - leaking=false, - debugging=false, - topdown=true, - forseelabels=true, -} -parseManager._types={} -parseManager.__index=parseManager -parseManager._variables={__TYPE="ENV"} -parseManager.defualtENV=parseManager._variables -function parseManager:varExists(var) - if var==nil or var=="nil" then return end - if type(var)=="userdata" then return var end - if tonumber(var) then - return tonumber(var) - end - local aa,bb=var:match("(.-)%[\"(.-)\"%]") - if aa and bb then - return self.defualtENV[aa][bb] - end - if var:find('"') then - return self:parseHeader(var:sub(2,-2),self.defualtENV) - end - if var:find("%[%]") then - return {} - end - if var:sub(1,1)=="[" and var:sub(-1,-1)=="]" then - local list=var:match("[(.+)]") - if not list then - self:pushError("Invalid List assignment!") - end - local t=list:split(",") - local nlist={} - local a=":)" - for i=1,#t do - a=self:varExists(t[i]) - if a then - table.insert(nlist,a) - end - end - return nlist - end - if var=="true" then - return true - elseif var=="false" then - return false - end - local a,b=var:match("(.-)%[(.-)%]") - if a and b then - if type(self.defualtENV[a])=="table" then - if b=="-1" then - return self.defualtENV[a][#self.defualtENV[a]] - elseif b=="#" then - return self.defualtENV[a][math.random(1,#self.defualtENV[a])] - else - return self.defualtENV[a][tonumber(b) or self:varExists(b)] - end - end - if type(self.defualtENV[var])=="table" then - return self.defualtENV[var] - end - end - return self.defualtENV[var] or var -- if all tests fail, just pass on the data for the function to manage -end -function parseManager:isList(var) - local a,b=var:match("(.-)%[(.-)%]") - if not a or b then return end - if type(self.defualtENV[a])=="table" then - if b=="-1" then - return self.defualtENV[a][#self.defualtENV[a]] - else - return self.defualtENV[a][tonumber(b)] - end - end - return -end -function parseManager:loadString(data) - self:_load(bin.new(data),self) -end -parseManager.loadeddata={} -parseManager.envs={} -parseManager._methods={ - getLength=function(self,list) - return #(self:varExists(list) or {}) - end, - emptyList=function(self) - return {} - end, - DEBUG=function(self,text) - print(text) - end, - DIS=function(self,var) - print(var) - end, - SEED=function(self,n) - math.randomseed(tonumber(self:varExists(n) or n) or os.time()) - end, - delElem=function(self,l,i) - table.remove(l,i) - end, - addElem=function(self,l,d,i) - table.insert(l,(i or -1),d) - return l - end, - RANDOM=function(self,v1,v2) - if v1 then - return math.random(1,v1) - elseif v1 or v2 then - return math.random(tonumber(v1),tonumber(v2)) - else - return math.random() - end - end, - CALC=function(self,eq) - return self:evaluate(eq) - end, - GOTOV=function(self,label) - print(self:varExists(label)) - self._methods.GOTO(self,self:varExists(label)) - end, - GOTO=function(self,label) - label=label:gsub("-","") - if label=="__LASTGOTO" then - self:setBlock(self._labels.__LASTGOTO[1]) - self.pos=self._labels[label][2] - return true - end - --search current block for a label - if self.pos==nil then - error("Attempt to load a non existing block from the host script!") - end - for i=self.pos,#self._cblock do - local line=self._cblock[i] - local labeltest=line:match("::(.-)::") - if labeltest==label then - self._labels["__LASTGOTO"]={self._cblockname,self.pos} - self.pos=i - return true - end - end - --search for saved labels - if self._labels[label] then - self._labels["__LASTGOTO"]={self._cblockname,self.pos} - self:setBlock(self._labels[label][1]) - self.pos=self._labels[label][2] - return true - end - --search other blocks if enabled for labels - if self.stats.forseelabels then - for i,v in pairs(self._chunks) do - local chunks=bin._lines(v[1]) - for p=1,#chunks do - local line=chunks[p] - local labeltest=line:match("::(.-)::") - if labeltest==label then - self._labels["__LASTGOTO"]={self._cblockname,self.pos} - self:setBlock(i) - self.pos=p-1 - return true - end - end - end - end - if self.stats.forseelabels then - if self._methods.GOTOV(self,label) then return end - end - self:pushError("Attempt to goto a non existing label! You can only access labels in the current scope! Or labels that the code has seen thus far! "..label.." does not exist as a label!") - end, - QUIT=function() - os.exit() - end, - EXIT=function(self) - self.pos=math.huge - end, - TYPE=function(self,val) - return type(val) - end, - SAVE=function(self,filename) - if trim(filename)=="" then filename="saveData.sav" end - local t=bin.new() - t:addBlock(self.defualtENV) - t:addBlock(self._cblockname) - t:addBlock(self.pos) - t:addBlock(self._labels) - t:tofile(filename) - end, - UNSAVE=function(self,filename) - if trim(filename)=="" then filename="saveData.sav" end - self.defualtENV={} - os.remove(filename) - end, - RESTORE=function(self) - if not(self.loadeddata.load) then self:pushError("A call to RESTORE without calling LOAD") end - self.defualtENV=self.loadeddata:getBlock("t") - self:setBlock(self.loadeddata:getBlock("s")) - self.pos=self.loadeddata:getBlock("n") - self._labels=self.loadeddata:getBlock("t") - end, - LOAD=function(self,filename) - print(filename) - if not filename then filename="saveData.sav" end - if io.fileExists(filename) then - self.loadeddata=bin.load(filename) - return 1 - end - return 0 - end, - JUMP=function(self,to) - self:setBlock(to) - end, - SKIP=function(self,n) - self.pos=self.pos+tonumber(n) - end, - PRINT=function(self,text) print(text) end, - TRIGGER=function(self,to) - self:setBlock(to) - end, - COMPARE=function(self,t,v1,v2,trueto,falseto) -- if a blockname is __STAY then it will continue on - if t=="=" or t=="==" then - if v1==v2 then - self:setBlock(trueto) - else - self:setBlock(falseto) - end - elseif t==">=" then - if v1>=v2 then - self:setBlock(trueto) - else - self:setBlock(falseto) - end - elseif t=="<=" then - if v1<=v2 then - self:setBlock(trueto) - else - self:setBlock(falseto) - end - elseif t==">" then - if v1>v2 then - self:setBlock(trueto) - else - self:setBlock(falseto) - end - elseif t=="<" then - if v1"..a - end) - local choicetest=line:find("<$") or line:find("^<") - local lasttest=line:match("^\"(.+)\"$") - local labeltest=line:match("::(.-)::") - local var,list=line:match("([%w_]-)=%[(.+)%]") - local assignA,assignB=line:match("(.-)=(.+)") - local cond,f1,f2=line:match("^if%s*(.-)%s*then%s*([%w-%(%)]-)%s*|%s*([%w-%(%)]*)") - if choicetest then - local c=self._chunks[self._cblockname][1] - local test=bin.new(c:match("\"<(.-)>")) - test:fullTrim(true) - local header=line:match("\"(.-)\"<") - local stuff=test:lines() - local cho,met={},{} - for i=1,#stuff do - local a1,a2=stuff[i]:match("\"(.-)\" (.+)") - a1=tostring(self:parseHeader(a1,env)) - table.insert(cho,a1) - table.insert(met,a2) - end - return { - Type="choice", - text=tostring(self:parseHeader(header,env)), - choices=cho, - methods=met, - blocktype=self._chunks[self._cblockname][2] - } - elseif cond and f1 and f2 then - conds={["andors"]={}} - mtc="" - for a,b in cond:gmatch("(.-)([and ]+[or ]+)") do - b=b:gsub(" ","") - mtc=mtc..".-"..b - v1,c,v2=a:match("(.-)%s*([<>!~=]+)%s*(.+)") - table.insert(conds,{v1,c,v2}) - table.insert(conds.andors,b) - end - a=cond:match(mtc.."%s*(.+)") - v1,c,v2=a:match("(.-)%s*([<>!~=]+)%s*(.+)") - table.insert(conds,{v1,c,v2}) - truths={} - for i=1,#conds do - conds[i][1]=conds[i][1]:gsub("\"","") - conds[i][3]=conds[i][3]:gsub("\"","") - if conds[i][2]=="==" then - table.insert(truths,tostring((self:varExists(conds[i][1]) or conds[i][1]))==tostring((self:varExists(conds[i][3]) or conds[i][3]))) - elseif conds[i][2]=="!=" or conds[i][2]=="~=" then - table.insert(truths,tostring((self:varExists(conds[i][1]) or conds[i][1]))~=tostring((self:varExists(conds[i][3]) or conds[i][3]))) - elseif conds[i][2]==">=" then - table.insert(truths,tonumber((self:varExists(conds[i][1]) or conds[i][1]))>=tonumber((self:varExists(conds[i][3]) or conds[i][3]))) - elseif conds[i][2]=="<=" then - table.insert(truths,tonumber((self:varExists(conds[i][1]) or conds[i][1]))<=tonumber((self:varExists(conds[i][3]) or conds[i][3]))) - elseif conds[i][2]==">" then - table.insert(truths,tonumber((self:varExists(conds[i][1]) or conds[i][1]))>tonumber((self:varExists(conds[i][3]) or conds[i][3]))) - elseif conds[i][2]=="<" then - table.insert(truths,tonumber((self:varExists(conds[i][1]) or conds[i][1]))])(.+)") - if d then - if d=="<-" then - self:setVariable(assignA,self.defualtENV[_env][vv]) - self:p() - return { - Type="assignment", - var=assignA, - value=assignB, - env=true, - text=assignA.."="..assignB - } - elseif d=="->" then - self.defualtENV[_env][assignA]=self:varExists(vv) - self:p() - return { - Type="assignment", - var=assignA, - value=assignB, - env=true, - text=assignA.."="..assignB - } - end - end - local a1,a2=parseManager.split(assignA),parseManager.split(assignB) - for i=1,#a1 do - local a=self._methods.CALC(self,a2[i]) - if a then - a2[i]=a - end - local t=tonumber(a2[i]) - if not t then - t=a2[i] - end - env[a1[i]]=t - end - self:p() - return { - Type="assignment", - var=assignA, - value=assignB, - text=assignA.."="..assignB - } - else - local rets=self.OnCustomSyntax:Fire(self,line) - for i=1,#rets do - if type(rets[i][1])=="table" then - return rets[i][1] - else - return { - Type="unknown", - text=line - } - end - end - self:p() - return { - Type="unknown", - text=line - } - end -end -function parseManager:RunCode(code,entry,sel,env) -- returns an env or selectVarName - local file = bin.new("ENTRY "..(entry or "START").."\n"..code) - local run=parseManager:load(file) - run._methods = self._methods - run.defualtENV=self.defualtENV - run.defualtENV=self.defualtENV - for i,v in pairs(env or {}) do - run.defualtENV[i]=v - end - local t=run:start() - while true do - if t.Type=="text" then - print(t.text) - t=run:next() - elseif t.Type=="condition" then - t=run:next() - elseif t.Type=="assignment" then - t=run:next() - elseif t.Type=="label" then - t=run:next() - elseif t.Type=="method" then - t=run:next() - elseif t.Type=="choice" then - t=run:next(nil,math.random(1,#t.choices),nil,t) - elseif t.Type=="end" then - if t.text=="leaking" then -- go directly to the block right under the current block if it exists - t=run:next() - else - return (run.defualtENV[sel] or run.defualtENV) - end - elseif t.Type=="error" then - error(t.text) - else - t=run:next() - end - end -end -parseManager.symbols={} -- {sym,code} -function parseManager:registerSymbol(sym,code) - self.symbols[#self.symbols+1]={sym,code} -end -function parseManager:populateSymbolList(o) - local str="" - for i=1,#self.symbols do - str=self.symbols[i][1]..str - end - return str -end -function parseManager:isRegisteredSymbol(o,r,v) - for i=1,#self.symbols do - if self.symbols[i][1]==o then - return parseManager:RunCode(self.symbols[i][2],"CODE","ret-urn",{["l"]=r,["r"]=v,["mainenv"]=self.defualtENV}) - end - end - return false --self:pushError("Invalid Symbol "..o.."!") -end -function parseManager:evaluate(cmd,v) - v=v or 0 - local loop - local count=0 - local function helper(o,v,r) - if type(v)=="string" then - if v:find("%D") then - v=self:varExists(v) - end - end - if type(r)=="string" then - if r:find("%D") then - r=self:varExists(r) - end - end - local r=tonumber(r) or 0 - local gg=self:isRegisteredSymbol(o,r,v) - if gg then - return gg - elseif o=="+" then - return r+v - elseif o=="-" then - return r-v - elseif o=="/" then - return r/v - elseif o=="*" then - return r*v - elseif o=="^" then - return r^v - end - end - for i,v in pairs(math) do - cmd=cmd:gsub(i.."(%b())",function(a) - a=a:sub(2,-2) - if a:sub(1,1)=="-" then - a="0"..a - end - return v(self:evaluate(a)) - end) - end - cmd=cmd:gsub("%b()",function(a) - return self:evaluate(a:sub(2,-2)) - end) - for l,o,r in cmd:gmatch("(.*)([%+%^%-%*/"..self:populateSymbolList().."])(.*)") do - loop=true - count=count+1 - if l:find("[%+%^%-%*/]") then - v=self:evaluate(l,v) - v=helper(o,r,v) - else - if count==1 then - v=helper(o,r,l) - end - end - end - if not loop then return self:varExists(cmd) end - return v -end -parseManager.constructType=function(self,name,t,data,filename) - if t~="construct" then return end - --print(name,t,"[CODE]{"..data.."}") - self:registerSymbol(name,"[CODE]{"..data.."}") -end --- Let's add function -Stack = {} -function Stack:Create() - local t = {} - t._et = {} - function t:push(...) - if ... then - local targs = {...} - for _,v in ipairs(targs) do - table.insert(self._et, v) - end - end - end - function t:pop(num) - local num = num or 1 - local entries = {} - for i = 1, num do - if #self._et ~= 0 then - table.insert(entries, self._et[#self._et]) - table.remove(self._et) - else - break - end - end - return unpack(entries) - end - function t:getn() - return #self._et - end - function t:list() - for i,v in pairs(self._et) do - print(i, v) - end - end - return t -end -parseManager.funcstack=Stack:Create() -parseManager:define{ - __TRACEBACK=function(self) -- internal function to handle function calls - local t=self.funcstack:pop() - self:setBlock(t[1]) - self.pos=t[2] - -- We finished the function great. Lets restore the old env - self._methods.setENV(self,t[3]) - end -} -parseManager.funcType=function(link,name,t,data,filename) - local test,args=t:match("(function)%(*([%w,]*)%)*") - if not test then return false end - local vars={} - if args~="" then - for k, v in ipairs(parseManager.split(args)) do - table.insert(vars,v) - end - -- Time to collect local vars to populate we will use these below - end - link._chunks[name][1]=link._chunks[name][1].."\n__TRACEBACK()" - local func=function(self,...) - -- Here we will use the vars. First lets capture the args from the other side - local args={...} - -- Here we will play a matching game assigning vars to values. This cannot be done yet... - -- Now we have to change the enviroment so function vars are local to the function. - -- Also we need functions to be able to access the globals too - -- Now we invoke the createnv method - local env=self._methods.createENV(self) - -- A little messy compared to how its done within the interpreted language - -- Now we need a copy of the previous Env - -- We then invoke getEnv method - local lastEnv=self._methods.getENV(self) - -- Great now we have a new enviroment to play with and the current one - -- Next we need to store the current one somewhere - self.funcstack:push({self._cblockname,self.pos,lastEnv}) - -- We use a stack to keep track of function calls. Before I tried something else and it was a horrible mess - -- Stacks make it real nice and easy to use. We store a bit of data into the stack to use later - if self.funcstack:getn()>1024 then self:pushError("Stack Overflow!") end - -- Throw an error if the stack reaches 1024 elements. We don't want it to go forever and odds are neither does the user - -- Lets set that new env and prepare for the jump. To do this we invoke setEnv - self._methods.setENV(self,env) - -- Now lets play match making - for i=1,#vars do - self:setVariable(vars[i],args[i]) -- this method defualts to the current env - end - -- We are ready to make the jump with our stored data - self._methods.JUMP(self,name) - -- we need to be able to catch returns... This is where things get tricky. - -- We need a way to run the other code while also waiting here so we can return data - -- What we can do is return a reference to the enviroment and from there you can take what you want from the function - -- This is a really strange way to do things, but whats wrong with different - return env - end - link._methods[name]=func -end -parseManager.OnExtendedBlock(parseManager.funcType) -parseManager.constructType=function(link,name,t,data,filename) - local test,args=t:match("(construct)%(*([%w,]*)%)*") - if not test then return false end - local vars={} - if args~="" then - for k, v in ipairs(parseManager.split(args)) do - table.insert(vars,v) - end - end - link._chunks[name][1]=link._chunks[name][1].."\n__TRACEBACK()" - local func=function(self,...) - local args={...} - local env=self._methods.createENV(self) - local lastEnv=self._methods.getENV(self) - self.funcstack:push({self._cblockname,self.pos,lastEnv}) - if self.funcstack:getn()>1024 then self:pushError("Stack Overflow!") end - self._methods.setENV(self,env) - for i=1,#vars do - self:setVariable(vars[i],args[i]) - end - self._methods.JUMP(self,name) - return env - end - link._methods[name]=func -end -parseManager.OnExtendedBlock(parseManager.constructType) diff --git a/mulit/examples/love2d Threading Example/core/parseManager/interpreter.lua b/mulit/examples/love2d Threading Example/core/parseManager/interpreter.lua deleted file mode 100644 index e4a5b84..0000000 --- a/mulit/examples/love2d Threading Example/core/parseManager/interpreter.lua +++ /dev/null @@ -1,10 +0,0 @@ -engine={} -function engine:init(bytecodeFile) - self.code=bin.load(bytecodeFile).data -end ---[[OP-CODES - -]] -function engine:run(assessors) - -- -end diff --git a/mulit/examples/love2d Threading Example/core/test.dat b/mulit/examples/love2d Threading Example/core/test.dat deleted file mode 100644 index 8b9302a..0000000 Binary files a/mulit/examples/love2d Threading Example/core/test.dat and /dev/null differ diff --git a/mulit/examples/love2d Threading Example/core/test.lua b/mulit/examples/love2d Threading Example/core/test.lua deleted file mode 100644 index f551bde..0000000 --- a/mulit/examples/love2d Threading Example/core/test.lua +++ /dev/null @@ -1,18 +0,0 @@ -require("Library") -local clock = os.clock -function sleep(n) -- seconds - local t0 = clock() - while clock() - t0 <= n do end -end -function tester(test) - sleep(1) - return test*10 -end ---~ require("bin") ---~ test=bin.namedBlockManager() ---~ test["name"]="Ryan" ---~ test["age"]=21 ---~ test:tofile("test.dat") ---~ test2=bin.namedBlockManager("test.dat") ---~ print(test2["name"]) ---~ print(test2["age"]) diff --git a/mulit/examples/love2d Threading Example/main.lua b/mulit/examples/love2d Threading Example/main.lua deleted file mode 100644 index 8ed71a6..0000000 --- a/mulit/examples/love2d Threading Example/main.lua +++ /dev/null @@ -1,69 +0,0 @@ -require("core.Library") -GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library ---IMPORTANT --- Do not make the above local, this is the one difference that the lanesManager does not have --- If these are local the functions will have the upvalues put into them that do not exist on the threaded side --- You will need to ensure that the function does not refer to any upvalues in its code. It will print an error if it does though --- Also each thread has a .1 second delay! This is used to generate a random values for each thread! -require("core.GuiManager") -- allows the use of graphics in the program. -gui.ff.Color=Color.Black -function comma_value(amount) - local formatted = amount - while true do - formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') - if (k==0) then - break - end - end - return formatted -end -multi:newSystemThread("test1",function() -- Another difference is that the multi library is already loaded in the threaded enviroment as well as a call to multi:mainloop() - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 1"):OnBench(function(self,c) GLOBAL["T1"]=c multi:Stop() end) -end) -multi:newSystemThread("test2",function() -- spawns a thread in another lua process - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 2"):OnBench(function(self,c) GLOBAL["T2"]=c multi:Stop() end) -end) -multi:newSystemThread("test3",function() -- spawns a thread in another lua process - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 3"):OnBench(function(self,c) GLOBAL["T3"]=c multi:Stop() end) -end) -multi:newSystemThread("test4",function() -- spawns a thread in another lua process - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 4"):OnBench(function(self,c) GLOBAL["T4"]=c multi:Stop() end) -end) -multi:newSystemThread("test5",function() -- spawns a thread in another lua process - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 5"):OnBench(function(self,c) GLOBAL["T5"]=c multi:Stop() end) -end) -multi:newSystemThread("test6",function() -- spawns a thread in another lua process - multi:benchMark(sThread.waitFor("Bench"),nil,"Thread 6"):OnBench(function(self,c) GLOBAL["T6"]=c multi:Stop() end) -end) -multi:newSystemThread("Combiner",function() -- spawns a thread in another lua process - function comma_value(amount) - local formatted = amount - while true do - formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') - if (k==0) then - break - end - end - return formatted - end - local b=comma_value(tostring(sThread.waitFor("T1")+sThread.waitFor("T2")+sThread.waitFor("T3")+sThread.waitFor("T4")+sThread.waitFor("T5")+sThread.waitFor("T6"))) - GLOBAL["DONE"]=b -end) -multi:newThread("test0",function() - -- sThread.waitFor("DONE") -- lets hold the main thread completely so we don't eat up cpu - -- os.exit() - -- when the main thread is holding there is a chance that error handling on the system threads may not work! - -- instead we can do this - while true do - thread.skip(1) -- allow error handling to take place... Otherwise lets keep the main thread running on the low - -- Before we held just because we could... But this is a game and we need to have logic continue - --sThreadM.sleep(.001) -- Sleeping for .001 is a greeat way to keep cpu usage down. Make sure if you aren't doing work to rest. Abuse the hell out of GLOBAL if you need to :P - if GLOBAL["DONE"] then - t.text="Bench: "..GLOBAL["DONE"] - end - end -end) -GLOBAL["Bench"]=3 -t=gui:newTextLabel("no done yet!",0,0,300,100) -t:centerX() -t:centerY() diff --git a/mulit/examples/love2d Threading Example/main2.lua b/mulit/examples/love2d Threading Example/main2.lua deleted file mode 100644 index f049404..0000000 --- a/mulit/examples/love2d Threading Example/main2.lua +++ /dev/null @@ -1,65 +0,0 @@ -require("core.Library") -GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library ---IMPORTANT --- Do not make the above local, this is the one difference that the lanesManager does not have --- If these are local the functions will have the upvalues put into them that do not exist on the threaded side --- You will need to ensure that the function does not refer to any upvalues in its code. It will print an error if it does though --- Also each thread has a .1 second delay! This is used to generate a random values for each thread! -require("core.GuiManager") -gui.ff.Color=Color.Black -function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a channel on both ends - local c={} - c.name=name - if love then - if love.thread then - function c:init() - self.chan=love.thread.getChannel(self.name) - function self:push(v) - self.chan:push(v) - end - function self:pop() - return self.chan:pop() - end - GLOBAL[self.name]=self - return self - end - return c - else - error("Make sure you required the love.thread module!") - end - else - c.linda=lanes.linda() - function c:push(v) - self.linda:send("Q",v) - end - function c:pop() - return ({self.linda:receive(0,"Q")})[2] - end - function c:init() - return self - end - GLOBAL[name]=c - end - return c -end -queue=multi:newSystemThreadedQueue("QUEUE"):init() -queue:push("This is a test") -queue:push("This is a test2") -queue:push("This is a test3") -queue:push("This is a test4") -multi:newSystemThread("test2",function() - queue=sThread.waitFor("QUEUE"):init() - data=queue:pop() - while data do - print(data) - data=queue:pop() - end - queue:push("DONE!") -end) -multi:newThread("test!",function() - thread.hold(function() return queue:pop() end) - t.text="Done!" -end) -t=gui:newTextLabel("no done yet!",0,0,300,100) -t:centerX() -t:centerY() diff --git a/mulit/examples/love2d Threading Example/main3.lua b/mulit/examples/love2d Threading Example/main3.lua deleted file mode 100644 index c025a66..0000000 --- a/mulit/examples/love2d Threading Example/main3.lua +++ /dev/null @@ -1,37 +0,0 @@ -require("core.Library") -GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library ---IMPORTANT --- Do not make the above local, this is the one difference that the lanesManager does not have --- If these are local the functions will have the upvalues put into them that do not exist on the threaded side --- You will need to ensure that the function does not refer to any upvalues in its code. It will print an error if it does though --- Also each thread has a .1 second delay! This is used to generate a random values for each thread! -require("core.GuiManager") -gui.ff.Color=Color.Black -queue=multi:newSystemThreadedQueue("QUEUE"):init() -queue:push(1) -queue:push(2) -queue:push(3) -queue:push(4) -queue:push(5) -queue:push(6) -multi:newSystemThread("STHREAD_1",function() - queue=sThread.waitFor("QUEUE"):init() - GLOBAL["QUEUE"]=nil - data=queue:pop() - while data do - print(data) - data=queue:pop() - end -end) -multi:newThread("THREAD_1",function() - while true do - if GLOBAL["QUEUE"]==nil then - t.text="Deleted a Global!" - break - end - thread.skip() -- give cpu time to other processes - end -end) -t=gui:newTextLabel("no done yet!",0,0,300,100) -t:centerX() -t:centerY() diff --git a/mulit/examples/love2d Threading Example/main4.lua b/mulit/examples/love2d Threading Example/main4.lua deleted file mode 100644 index b12e7a5..0000000 --- a/mulit/examples/love2d Threading Example/main4.lua +++ /dev/null @@ -1,19 +0,0 @@ -require("core.Library") -GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library -require("core.GuiManager") -gui.ff.Color=Color.Black -test=multi:newSystemThreadedTable("YO"):init() -test["test1"]="lol" -multi:newSystemThread("test",function() - tab=sThread.waitFor("YO"):init() - print(tab["test1"]) - sThread.sleep(3) - tab["test2"]="Whats so funny?" -end) -multi:newThread("test2",function() - print(test:waitFor("test2")) - t.text="DONE!" -end) -t=gui:newTextLabel("no done yet!",0,0,300,100) -t:centerX() -t:centerY() diff --git a/mulit/examples/love2d Threading Example/main5.lua b/mulit/examples/love2d Threading Example/main5.lua deleted file mode 100644 index d491c6a..0000000 --- a/mulit/examples/love2d Threading Example/main5.lua +++ /dev/null @@ -1,32 +0,0 @@ -require("core.Library") -GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library -require("core.GuiManager") -gui.ff.Color=Color.Black -jQueue=multi:newSystemThreadedJobQueue() -- this internally creates System threads, We told it to use a maximum of 3 cores at any given time -jQueue:registerJob("TEST_JOB",function(a,s) - math.randomseed(s) - print("testing...") - -- We will push a random # - TEST_JOB2() -- You can call other registered functions as well! - return math.random(0,255) -- send the result to the main thread -end) -jQueue:registerJob("TEST_JOB2",function(a,s) - print("Test Works!") -end) -jQueue:start() -tableOfOrder={} -jQueue.OnJobCompleted(function(JOBID,n) - -- JOBID is the completed job, starts at 1 and counts up by 1. - -- Threads finish at different times so jobids may be returned out of order! Be sure to have a way to order them - tableOfOrder[JOBID]=n -- we order ours by putting them into a table - if #tableOfOrder==10 then - print("We got all of the pieces!") - end -end) -for i=1,10 do -- Job Name of registered function, ... varargs - jQueue:pushJob("TEST_JOB","This is a test!",math.random(1,1000000)) -end -print("I pushed all of the jobs :)") -t=gui:newTextLabel("no done yet!",0,0,300,100) -t:centerX() -t:centerY() diff --git a/mulit/examples/love2d Threading Example/main6.lua b/mulit/examples/love2d Threading Example/main6.lua deleted file mode 100644 index bd24ca9..0000000 --- a/mulit/examples/love2d Threading Example/main6.lua +++ /dev/null @@ -1,14 +0,0 @@ -require("core.Library") -GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2d version of the lanesManager and requires the entire multi library -require("core.GuiManager") -gui.ff.Color=Color.Black -cmd=multi:newSystemThreadedExecute("C:/SystemThreadedExecuteTest.lua") -cmd.OnCMDFinished(function(code) - print("Got Code: "..code) -end) -multi:newTLoop(function() - print("...") -end,1) -t=gui:newTextLabel("no done yet!",0,0,300,100) -t:centerX() -t:centerY() diff --git a/mulit/examples/love2d Threading Example/multi/all.lua b/mulit/examples/love2d Threading Example/multi/all.lua deleted file mode 100644 index d14aac6..0000000 --- a/mulit/examples/love2d Threading Example/multi/all.lua +++ /dev/null @@ -1 +0,0 @@ -require("multi") diff --git a/mulit/examples/love2d Threading Example/multi/compat/backwards[1,5,0].lua b/mulit/examples/love2d Threading Example/multi/compat/backwards[1,5,0].lua deleted file mode 100644 index a0f52a8..0000000 --- a/mulit/examples/love2d Threading Example/multi/compat/backwards[1,5,0].lua +++ /dev/null @@ -1,305 +0,0 @@ ---[[ -MIT License - -Copyright (c) 2017 Ryan Ward - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] -multi.OnObjectCreated(function(obj) - if obj.Type=="loop" then - function obj:Act() - for i=1,#self.func do - self.func[i](self.Parent.clock()-self.Start,self) - end - end - elseif obj.Type=="step" then - function obj:Act() - if self~=nil then - if self.spos==0 then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - elseif obj.Type=="tstep" then - function c:Act() - if self.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - end -end) -if thread then - function multi:newThreadedLoop(name,func) - local c=self:newTBase() - c.Type='loopThread' - c.Start=os.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - function c:OnLoop(func) - table.insert(self.func,func) - end - c.rest=false - c.updaterate=0 - c.restRate=.75 - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) - else - for i=1,#c.func do - c.func[i](os.clock()-self.Start,c) - end - thread.sleep(c.updaterate) - end - end - end) - self:create(c) - return c - end - function multi:newThreadedStep(name,start,reset,count,skip) - local c=self:newTBase() - local think=1 - c.Type='stepThread' - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.rest=true - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - c.updaterate=0 - c.restRate=.1 - multi:newThread(name,function(ref) - while true do - if c.rest then - ref:sleep(c.restRate) - else - if c~=nil then - if c.spos==0 then - if c.pos==c.start then - for fe=1,#c.funcS do - c.funcS[fe](c) - end - end - for i=1,#c.func do - c.func[i](c.pos,c) - end - c.pos=c.pos+c.count - if c.pos-c.count==c.endAt then - c:Pause() - for fe=1,#c.funcE do - c.funcE[fe](c) - end - c.pos=c.start - end - end - end - c.spos=c.spos+1 - if c.spos>=c.skip then - c.spos=0 - end - ref:sleep(c.updaterate) - end - end - end) - self:create(c) - return c - end - function multi:newThreadedTStep(name,start,reset,count,set) - local c=self:newTBase() - local think=1 - c.Type='tstepThread' - c.Priority=self.Priority_Low - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=os.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=self.start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=os.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - c.updaterate=0 - c.restRate=0 - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) - else - if os.clock()-c.timer>=c.set then - c:Reset() - if c.pos==c.start then - for fe=1,#c.funcS do - c.funcS[fe](c) - end - end - for i=1,#c.func do - c.func[i](c.pos,c) - end - c.pos=c.pos+c.count - if c.pos-c.count==c.endAt then - c:Pause() - for fe=1,#c.funcE do - c.funcE[fe](c) - end - c.pos=c.start - end - end - thread.skip(c.updaterate) - end - end - end) - self:create(c) - return c - end -end diff --git a/mulit/examples/love2d Threading Example/multi/compat/love2d.lua b/mulit/examples/love2d Threading Example/multi/compat/love2d.lua deleted file mode 100644 index cc4015d..0000000 --- a/mulit/examples/love2d Threading Example/multi/compat/love2d.lua +++ /dev/null @@ -1,114 +0,0 @@ ---[[ -MIT License - -Copyright (c) 2017 Ryan Ward - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] -require("multi") -os.sleep=love.timer.sleep -function love.run() - if love.math then - love.math.setRandomSeed(os.time()) - end - if love.event then - love.event.pump() - end - if love.load then love.load(arg) end - if love.timer then love.timer.step() end - local dt = 0 - while true do - -- Process events. - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - if multi.boost then - for i=1,multi.boost-1 do - multi:uManager(dt) - end - end - multi:uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - multi.dManager() - love.graphics.setColor(255,255,255,255) - if multi.draw then multi.draw() end - love.graphics.present() - end - end -end -multi.drawF={} -function multi:dManager() - for ii=1,#multi.drawF do - multi.drawF[ii]() - end -end -function multi:onDraw(func,i) - i=i or 1 - table.insert(self.drawF,i,func) -end -function multi:lManager() - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return nil - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - multi:uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - multi.dManager() - love.graphics.setColor(255,255,255,255) - if multi.draw then multi.draw() end - love.graphics.present() - end -end diff --git a/mulit/examples/love2d Threading Example/multi/init.lua b/mulit/examples/love2d Threading Example/multi/init.lua deleted file mode 100644 index 1c98dfa..0000000 --- a/mulit/examples/love2d Threading Example/multi/init.lua +++ /dev/null @@ -1,2141 +0,0 @@ ---[[ -MIT License - -Copyright (c) 2017 Ryan Ward - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] -if table.unpack then - unpack=table.unpack -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -_print=print -function print(...) - if not __SUPPRESSPRINTS then - _print(...) - end -end -multi = {} -multi.Version="1.8.6" -multi._VERSION="1.8.6" -multi.stage='mostly-stable' -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.ender={} -multi.Children={} -multi.Paused={} -multi.Active=true -multi.fps=60 -multi.Id=-1 -multi.Type='mainprocess' -multi.Rest=0 -multi._type=type -multi.Jobs={} -multi.queue={} -multi.jobUS=2 -multi.clock=os.clock -multi.time=os.time -multi.LinkedPath=multi -multi.isRunning=false -multi.queuefinal=function(self) - self:Destroy() - if self.Parent.Mainloop[#self.Parent.Mainloop] then - if self.Parent.Mainloop[#self.Parent.Mainloop].Type=="alarm" then - self.Parent.Mainloop[#self.Parent.Mainloop]:Reset() - self.Parent.Mainloop[#self.Parent.Mainloop].Active=true - else - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end - else - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end -end ---Do not change these ever...Any other number will not work (Unless you are using enablePriority2() then change can be made. Just ensure that Priority_Idle is the greatest and Priority_Core is 1!) -multi.Priority_Core=1 -multi.Priority_High=4 -multi.Priority_Above_Normal=16 -multi.Priority_Normal=64 -multi.Priority_Below_Normal=256 -multi.Priority_Low=1024 -multi.Priority_Idle=4096 -multi.PList={multi.Priority_Core,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Idle} -multi.PStep=1 ---^^^^ -multi.PriorityTick=1 -- Between 1 and 4 any greater and problems arise -multi.Priority=multi.Priority_Core -multi.threshold=256 -multi.threstimed=.001 -function multi:setThreshold(n) - self.threshold=n or 120 -end -function multi:setThrestimed(n) - self.threstimed=n or .001 -end -function multi:getLoad() - return multi:newFunction(function(self) - multi.scheduler:Pause() - local sample=#multi.Mainloop - local FFloadtest=0 - multi:benchMark(multi.threstimed):OnBench(function(_,l3) FFloadtest=l3*(1/multi.threstimed) end) - self:hold(function() return FFloadtest~=0 end) - local val=FFloadtest/sample - multi.scheduler:Resume() - if val>multi.threshold then - return 0 - else - return 100-((val/multi.threshold)*100) - end - end)() -end -function multi:setDomainName(name) - self[name]={} -end -function multi:linkDomain(name) - return self[name] -end -function multi:_Pause() - self.Active=false -end -function multi:setPriority(s) - if type(s)==number then - self.Priority=s - elseif type(s)=='string' then - if s:lower()=='core' or s:lower()=='c' then - self.Priority=self.Priority_Core - elseif s:lower()=='high' or s:lower()=='h' then - self.Priority=self.Priority_High - elseif s:lower()=='above' or s:lower()=='an' then - self.Priority=self.Priority_Above_Normal - elseif s:lower()=='normal' or s:lower()=='n' then - self.Priority=self.Priority_Normal - elseif s:lower()=='below' or s:lower()=='bn' then - self.Priority=self.Priority_Below_Normal - elseif s:lower()=='low' or s:lower()=='l' then - self.Priority=self.Priority_Low - elseif s:lower()=='idle' or s:lower()=='i' then - self.Priority=self.Priority_Idle - end - end -end --- System -function os.getOS() - if package.config:sub(1,1)=='\\' then - return 'windows' - else - return 'unix' - end -end -if os.getOS()=='windows' then - function os.sleep(n) - if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end - end -else - function os.sleep(n) - os.execute('sleep ' .. tonumber(n)) - end -end -function multi:getParentProcess() - return self.Mainloop[self.CID] -end -multi.GetParentProcess=multi.getParentProcess -function multi:Stop() - self.Active=false -end -function multi:condition(cond) - if not self.CD then - self:Pause() - self.held=true - self.CD=cond.condition - elseif not(cond.condition()) then - self.held=false - self:Resume() - self.CD=nil - return false - end - self.Parent:Do_Order() - return true -end -multi.Condition=multi.condition -function multi:isHeld() - return self.held -end -multi.IsHeld=multi.isHeld -function multi.executeFunction(name,...) - if type(_G[name])=='function' then - _G[name](...) - else - print('Error: Not a function') - end -end -function multi:waitFor(obj) - local value=false - self.__waiting=function() - value=true - end - obj:connectFinal(self.__waiting) - self:hold(function() return value end) -end -multi.WaitFor=multi.waitFor -function multi:reboot(r) - local before=collectgarbage('count') - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=='table' then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end - collectgarbage() - local after=collectgarbage('count') - print([[Before rebooting total Ram used was ]]..before..[[Kb -After rebooting total Ram used is ]]..after..[[ Kb -A total of ]]..(before-after)..[[Kb was cleaned up]]) -end -function multi:getChildren() - return self.Mainloop -end -function multi:getVersion() - return multi.Version -end -function multi:getPlatform() - if love then - if love.thread then - return "love2d" - end - else - return "lanes" - end -end -function multi:canSystemThread() - return false -end ---Processor -function multi:getError() - if self.error then - return self.error - end -end -function multi:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:enablePriority() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PList[PS.PStep])%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>7 then - PS.PStep=1 - end - end -end -function multi:enablePriority2() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PStep)%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>self.Priority_Idle then - PS.PStep=1 - end - end -end -multi.disablePriority=multi.unProtect -function multi:fromfile(path,int) - int=int or self - local test2={} - local test=bin.load(path) - local tp=test:getBlock('s') - if tp=='event' then - test2=int:newEvent(test:getBlock('f')) - local t=test:getBlock('t') - for i=1,#t do - test2:OnEvent(t[i]) - end - elseif tp=='alarm' then - test2=int:newAlarm(test:getBlock('n')) - elseif tp=='loop' then - test2=int:newLoop(test:getBlock('t')[1]) - elseif tp=='step' or tp=='tstep' then - local func=test:getBlock('t') - local funcE=test:getBlock('t') - local funcS=test:getBlock('t') - local tab=test:getBlock('t') - test2=int:newStep() - table.merge(test2,tab) - test2.funcE=funcE - test2.funcS=funcS - test2.func=func - elseif tp=='trigger' then - test2=int:newTrigger(test:getBlock('f')) - elseif tp=='connector' then - test2=int:newConnection() - test2.func=test:getBlock('t') - elseif tp=='timer' then - test2=int:newTimer() - test2.count=tonumber(test:getBlock('n')) - else - print('Error: The file you selected is not a valid multi file object!') - return false - end - return test2 -end -function multi:benchMark(sec,p,pt) - local temp=self:newLoop(function(self,t) - if self.clock()-self.init>self.sec then - if pt then - print(pt.." "..self.c.." Steps in "..sec.." second(s)!") - end - self.tt(self.sec,self.c) - self:Destroy() - else - self.c=self.c+1 - end - end) - temp.Priority=p or 1 - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=self.clock() - temp.c=0 - return temp -end -function multi:tofile(path) - local items=self:getChildren() - io.mkDir(io.getName(path)) - for i=1,#items do - items[i]:tofile(io.getName(path)..'\\item'..item[i]..'.dat') - end - local int=bin.new() - int:addBlock('process') - int:addBlock(io.getName(path)) - int:addBlock(#self.Mainloop) - int:addBlock(self.Active) - int:addBlock(self.Rest) - int:addBlock(self.Jobs) - int:tofile() -end -function multi.startFPSMonitior() - if not multi.runFPS then - multi.doFPS(s) - multi.runFPS=true - end -end -function multi.doFPS(s) - multi:benchMark(1):OnBench(doFPS) - if s then - multi.fps=s - end -end ---Helpers -function multi:IsAnActor() - return ({watcher=true,tstep=true,step=true,updater=true,loop=true,alarm=true,event=true})[self.Type] -end -function multi:OnMainConnect(func) - table.insert(self.func,func) -end -function multi:protect() - function self:Do_Order() - local Loop=self.Mainloop - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - self.CID=_D - local status, err=pcall(Loop[_D].Act,Loop[_D]) - if err and not(Loop[_D].error) then - Loop[_D].error=err - self.OnError:Fire(Loop[_D],err) - end - end - end - end -end -function multi:unProtect() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:reallocate(o,n) - n=n or #o.Mainloop+1 - local int=self.Parent - self:Destroy() - self.Parent=o - table.insert(o.Mainloop,n,self) - self.Active=true -end -multi.Reallocate=multi.Reallocate -function multi:setJobSpeed(n) - self.jobUS=n -end -function multi:hasJobs() - return #self.Jobs>0,#self.Jobs -end -function multi:getJobs() - return #self.Jobs -end -function multi:removeJob(name) - for i=#self.Jobs,1,-1 do - if self.Jobs[i][2]==name then - table.remove(self.Jobs,i) - end - end -end -function multi:FreeMainEvent() - self.func={} -end -function multi:connectFinal(func) - if self.Type=='event' then - self:OnEvent(func) - elseif self.Type=='alarm' then - self:OnRing(func) - elseif self.Type=='step' or self.Type=='tstep' then - self:OnEnd(func) - else - print("Warning!!! "..self.Type.." doesn't contain a Final Connection State! Use "..self.Type..":Break(function) to trigger it's final event!") - self:OnBreak(func) - end -end -multi.ConnectFinal=multi.connectFinal -function multi:Break() - self:Pause() - self.Active=nil - for i=1,#self.ender do - if self.ender[i] then - self.ender[i](self) - end - end -end -function multi:OnBreak(func) - table.insert(self.ender,func) -end -function multi:isPaused() - return not(self.Active) -end -multi.IsPaused=multi.isPaused -function multi:isActive() - return self.Active -end -multi.IsActive=multi.isActive -function multi:getType() - return self.Type -end -multi.GetType=multi.getType -function multi:Sleep(n) - self:hold(n) -end -multi.sleep=multi.Sleep --- Advance Timer stuff -function multi:SetTime(n) - if not n then n=3 end - local c=multi:newBase() - c.Type='timemaster' - c.timer=multi:newTimer() - c.timer:Start() - c.set=n - c.link=self - self._timer=c.timer - function c:Act() - if self.timer:Get()>=self.set then - self.link:Pause() - for i=1,#self.link.funcTM do - self.link.funcTM[i](self.link) - end - self:Destroy() - end - end - return c -end -multi.ResetTime=multi.SetTime -function multi:ResolveTimer(...) - self._timer:Pause() - for i=1,#self.funcTMR do - self.funcTMR[i](self,...) - end - self:Pause() -end -function multi:OnTimedOut(func) - self.funcTM[#self.funcTM+1]=func -end -function multi:OnTimerResolved(func) - self.funcTMR[#self.funcTMR+1]=func -end --- Timer stuff done -function multi:Pause() - if self.Type=='mainprocess' then - print("You cannot pause the main process. Doing so will stop all methods and freeze your program! However if you still want to use multi:_Pause()") - else - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - end -end -function multi:Resume() - if self.Type=='process' or self.Type=='mainprocess' then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:resurrect() - table.insert(self.Parent.Mainloop,self) - self.Active=true -end -multi.Resurrect=multi.resurrect -function multi:Destroy() - if self.Type=='process' or self.Type=='mainprocess' then - local c=self:getChildren() - for i=1,#c do - self.OnObjectDestroyed:Fire(c[i]) - c[i]:Destroy() - end - else - for i=1,#self.Parent.Mainloop do - if self.Parent.Mainloop[i]==self then - self.Parent.OnObjectDestroyed:Fire(self) - table.remove(self.Parent.Mainloop,i) - break - end - end - self.Active=false - end -end - -function multi:hold(task) - self:Pause() - self.held=true - if type(task)=='number' then - local timer=multi:newTimer() - timer:Start() - while timer:Get()0 then ---~ for i=1,#self.Parent.FC do ---~ self.Parent.FC[i]:Fire(...) ---~ end ---~ end - if self.Parent.protect then - local t=pcall(self.func,...) - if t then - return t - end - else - return self.func(...) - end - end, - Remove=function(self) - for i=1,#self.Link do - if self.Link[i][2]~=nil then - if self.Link[i][2]==self.ID then - table.remove(self.Link,i) - self.remove=function() end - self.Link=nil - self.ID=nil - return true - end - end - end - end - } - if name then - self.connections[name]=temp - end - return temp - end - c.Connect=c.connect - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:tofile(path) - end - return c -end -multi.OnObjectCreated=multi:newConnection() -multi.OnObjectDestroyed=multi:newConnection() -function multi:newJob(func,name) - if not(self.Type=='mainprocess' or self.Type=='process') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='process' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Parent=self - c.Type='job' - c.trigfunc=func or function() end - function c:Act() - self:trigfunc(self) - end - table.insert(self.Jobs,{c,name}) - if self.JobRunner==nil then - self.JobRunner=self:newAlarm(self.jobUS) - self.JobRunner:OnRing(function(self) - if #self.Parent.Jobs>0 then - if self.Parent.Jobs[1] then - self.Parent.Jobs[1][1]:Act() - table.remove(self.Parent.Jobs,1) - end - end - self:Reset(self.Parent.jobUS) - end) - end -end -function multi:newRange() - local selflink=self - local temp={ - getN = function(self) selflink:Do_Order() self.n=self.n+self.c if self.n>self.b then self.Link.held=false self.Link:Resume() return nil end return self.n end, - } - setmetatable(temp,{ - __call=function(self,a,b,c) - self.c=c or 1 - self.n=a-self.c - self.a=a - self.b=b - self.Link=selflink--.Parent.Mainloop[selflink.CID] or - self.Link:Pause() - self.Link.held=true - return function() return self:getN() end - end - }) - self:create(temp) - return temp -end -multi.NewRange=multi.newRange -function multi:newCondition(func) - local c={['condition']=func,Type="condition"} - self:create(c) - return c -end -multi.NewCondition=multi.newCondition -function multi:mainloop() - if not multi.isRunning then - multi.isRunning=true - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - self:Do_Order() - end - else - return "Already Running!" - end -end -function multi:protectedMainloop() - multi:protect() - if not multi.isRunning then - multi.isRunning=true - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - self:Do_Order() - end - else - return "Already Running!" - end -end -function multi:unprotectedMainloop() - multi:unProtect() - if not multi.isRunning then - multi.isRunning=true - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - else - return "Already Running!" - end -end -function multi:prioritizedMainloop1() - multi:enablePriority() - if not multi.isRunning then - multi.isRunning=true - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PList[PS.PStep])%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>7 then - PS.PStep=1 - end - end - else - return "Already Running!" - end -end -function multi:prioritizedMainloop2() - multi:enablePriority2() - if not multi.isRunning then - multi.isRunning=true - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PStep)%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>self.Priority_Idle then - PS.PStep=1 - end - end - else - return "Already Running!" - end -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - rawset(self,'Start',self.clock()) -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - function self:uManager(dt) - self:Do_Order() - end - self:Do_Order() - end -end ---Core Actors -function multi:newCustomObject(objRef,t) - local c={} - if t=='process' then - c=self:newBase() - if type(objRef)=='table' then - table.merge(c,objRef) - end - if not c.Act then - function c:Act() - -- Empty function - end - end - else - c=objRef or {} - end - if not c.Type then - c.Type='coustomObject' - end - self:create(c) - return c -end -function multi:newEvent(task) - local c=self:newBase() - c.Type='event' - c.Task=task or function() end - function c:Act() - if self.Task(self) then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:SetTask(func) - self.Task=func - end - function c:OnEvent(func) - table.insert(self.func,func) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.Task) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newUpdater(skip) - local c=self:newBase() - c.Type='updater' - c.pos=1 - c.skip=skip or 1 - function c:Act() - if self.pos>=self.skip then - self.pos=0 - for i=1,#self.func do - self.func[i](self) - end - end - self.pos=self.pos+1 - end - function c:setSkip(n) - self.skip=n - end - c.OnUpdate=self.OnMainConnect - self:create(c) - return c -end -function multi:newAlarm(set) - local c=self:newBase() - c.Type='alarm' - c.Priority=self.Priority_Low - c.timer=self:newTimer() - c.set=set or 0 - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.set) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.timer:Get()>=self.set then - self:Pause() - self.Active=false - for i=1,#self.func do - self.func[i](self) - end - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer:Resume() - end - function c:Reset(n) - if n then self.set=n end - self:Resume() - self.timer:Reset() - end - function c:OnRing(func) - table.insert(self.func,func) - end - function c:Pause() - self.timer:Pause() - self.Parent.Pause(self) - end - self:create(c) - return c -end -function multi:newLoop(func) - local c=self:newBase() - c.Type='loop' - c.Start=self.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - for i=1,#self.func do - self.func[i](self,self.Parent.clock()-self.Start) - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - self:create(c) - return c -end -function multi:newFunction(func) - local c={} - c.func=func - mt={ - __index=multi, - __call=function(self,...) if self.Active then return self:func(...) end local t={...} return "PAUSED" end - } - c.Parent=self - function c:Pause() - self.Active=false - end - function c:Resume() - self.Active=true - end - setmetatable(c,mt) - self:create(c) - return c -end -function multi:newStep(start,reset,count,skip) - local c=self:newBase() - think=1 - c.Type='step' - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self,self.pos) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - self:create(c) - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newTLoop(func,set) - local c=self:newBase() - c.Type='tloop' - c.set=set or 0 - c.timer=self:newTimer() - c.life=0 - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.timer:Get()>=self.set then - self.life=self.life+1 - for i=1,#self.func do - self.func[i](self,self.life) - end - self.timer:Reset() - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer:Resume() - end - function c:Pause() - self.timer:Pause() - self.Parent.Pause(self) - end - function c:OnLoop(func) - table.insert(self.func,func) - end - self:create(c) - return c -end -function multi:newTrigger(func) - local c={} - c.Type='trigger' - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(...) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.trigfunc) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newTStep(start,reset,count,set) - local c=self:newBase() - think=1 - c.Type='tstep' - c.Priority=self.Priority_Low - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=self.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=self.start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=self.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self,self.pos) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=self.clock() - self:Resume() - end - self:create(c) - return c -end -function multi:newWatcher(namespace,name) - local function WatcherObj(ns,n) - if self.Type=='queue' then - print("Cannot create a watcher on a queue! Creating on 'multi' instead!") - self=multi - end - local c=self:newBase() - c.Type='watcher' - c.ns=ns - c.n=n - c.cv=ns[n] - function c:OnValueChanged(func) - table.insert(self.func,func) - end - function c:Act() - if self.cv~=self.ns[self.n] then - for i=1,#self.func do - self.func[i](self,self.cv,self.ns[self.n]) - end - self.cv=self.ns[self.n] - end - end - self:create(c) - return c - end - if type(namespace)~='table' and type(namespace)=='string' then - return WatcherObj(_G,namespace) - elseif type(namespace)=='table' and (type(name)=='string' or 'number') then - return WatcherObj(namespace,name) - else - print('Warning, invalid arguments! Nothing returned!') - end -end --- Threading stuff -thread={} -multi.GlobalVariables={} -if os.getOS()=="windows" then - thread.__CORES=tonumber(os.getenv("NUMBER_OF_PROCESSORS")) -else - thread.__CORES=tonumber(io.popen("nproc --all"):read("*n")) -end -function thread.sleep(n) - coroutine.yield({"_sleep_",n or 0}) -end -function thread.hold(n) - coroutine.yield({"_hold_",n or function() return true end}) -end -function thread.skip(n) - coroutine.yield({"_skip_",n or 0}) -end -function thread.kill() - coroutine.yield({"_kill_",":)"}) -end -function thread.yeild() - coroutine.yield({"_sleep_",0}) -end -function thread.getCores() - return thread.__CORES -end -function thread.set(name,val) - multi.GlobalVariables[name]=val - return true -end -function thread.get(name) - return multi.GlobalVariables[name] -end -function thread.waitFor(name) - thread.hold(function() return thread.get(name)~=nil end) - return thread.get(name) -end -function thread.testFor(name,val,sym) - thread.hold(function() return thread.get(name)~=nil end) - return thread.get(name) -end -function multi:newTBase(ins) - local c = {} - c.Active=true - c.func={} - c.ender={} - c.Id=0 - c.PId=0 - c.Parent=self - c.held=false - return c -end -function multi:newThread(name,func) - local c={} - c.ref={} - c.Name=name - c.thread=coroutine.create(func) - c.sleep=1 - c.Type="thread" - c.firstRunDone=false - c.timer=multi.scheduler:newTimer() - c.ref.Globals=self:linkDomain("Globals") - function c.ref:send(name,val) - ret=coroutine.yield({Name=name,Value=val}) - self:syncGlobals(ret) - end - function c.ref:get(name) - return self.Globals[name] - end - function c.ref:kill() - err=coroutine.yield({"_kill_"}) - if err then - error("Failed to kill a thread! Exiting...") - end - end - function c.ref:sleep(n) - if type(n)=="function" then - ret=coroutine.yield({"_hold_",n}) - self:syncGlobals(ret) - elseif type(n)=="number" then - n = tonumber(n) or 0 - ret=coroutine.yield({"_sleep_",n}) - self:syncGlobals(ret) - else - error("Invalid Type for sleep!") - end - end - function c.ref:syncGlobals(v) - self.Globals=v - end - table.insert(self:linkDomain("Threads"),c) - if not multi.scheduler:isActive() then - multi.scheduler:Resume() - end -end -multi:setDomainName("Threads") -multi:setDomainName("Globals") -multi.scheduler=multi:newLoop() -multi.scheduler.Type="scheduler" -function multi.scheduler:setStep(n) - self.skip=tonumber(n) or 24 -end -multi.scheduler.skip=0 -multi.scheduler.counter=0 -multi.scheduler.Threads=multi:linkDomain("Threads") -multi.scheduler.Globals=multi:linkDomain("Globals") -multi.scheduler:OnLoop(function(self) - self.counter=self.counter+1 - for i=#self.Threads,1,-1 do - ret={} - if coroutine.status(self.Threads[i].thread)=="dead" then - table.remove(self.Threads,i) - else - if self.Threads[i].timer:Get()>=self.Threads[i].sleep then - if self.Threads[i].firstRunDone==false then - self.Threads[i].firstRunDone=true - self.Threads[i].timer:Start() - _,ret=coroutine.resume(self.Threads[i].thread,self.Threads[i].ref) - else - _,ret=coroutine.resume(self.Threads[i].thread,self.Globals) - end - if _==false then - self.Parent.OnError:Fire(self.Threads[i],ret) - print("Error in thread: <"..self.Threads[i].Name.."> "..ret) - end - if ret==true or ret==false then - print("Thread Ended!!!") - ret={} - end - end - if ret then - if ret[1]=="_kill_" then - table.remove(self.Threads,i) - elseif ret[1]=="_sleep_" then - self.Threads[i].timer:Reset() - self.Threads[i].sleep=ret[2] - elseif ret[1]=="_skip_" then - self.Threads[i].timer:Reset() - self.Threads[i].sleep=math.huge - local event=multi:newEvent(function(evnt) return multi.scheduler.counter>=evnt.counter end) - event.link=self.Threads[i] - event.counter=self.counter+ret[2] - event:OnEvent(function(evnt) - evnt.link.sleep=0 - end) - elseif ret[1]=="_hold_" then - self.Threads[i].timer:Reset() - self.Threads[i].sleep=math.huge - local event=multi:newEvent(ret[2]) - event.link=self.Threads[i] - event:OnEvent(function(evnt) - evnt.link.sleep=0 - end) - elseif ret.Name then - self.Globals[ret.Name]=ret.Value - end - end - end - end -end) -multi.scheduler:Pause() -multi.OnError=multi:newConnection() -function multi:newThreadedAlarm(name,set) - local c=self:newTBase() - c.Type='alarmThread' - c.timer=self:newTimer() - c.set=set or 0 - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.set) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - self.timer:Resume() - end - function c:Reset(n) - if n then self.set=n end - self.rest=false - self.timer:Reset(n) - end - function c:OnRing(func) - table.insert(self.func,func) - end - function c:Pause() - self.timer:Pause() - self.rest=true - end - c.rest=false - c.updaterate=multi.Priority_Low -- skips - c.restRate=0 -- secs - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) -- rest a bit more when a thread is paused - else - if c.timer:Get()>=c.set then - c:Pause() - for i=1,#c.func do - c.func[i](c) - end - end - thread.skip(c.updaterate) -- lets rest a bit - end - end - end) - self:create(c) - return c -end -function multi:newThreadedUpdater(name,skip) - local c=self:newTBase() - c.Type='updaterThread' - c.pos=1 - c.skip=skip or 1 - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - c.OnUpdate=self.OnMainConnect - c.rest=false - c.updaterate=0 - c.restRate=.75 - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) -- rest a bit more when a thread is paused - else - for i=1,#c.func do - c.func[i](c) - end - c.pos=c.pos+1 - thread.skip(c.skip) - end - end - end) - self:create(c) - return c -end -function multi:newThreadedTStep(name,start,reset,count,set) - local c=self:newTBase() - local think=1 - c.Type='tstepThread' - c.Priority=self.Priority_Low - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=os.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=self.start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=os.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - c.updaterate=0--multi.Priority_Low -- skips - c.restRate=0 - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) -- rest a bit more when a thread is paused - else - if os.clock()-c.timer>=c.set then - c:Reset() - if c.pos==c.start then - for fe=1,#c.funcS do - c.funcS[fe](c) - end - end - for i=1,#c.func do - c.func[i](c.pos,c) - end - c.pos=c.pos+c.count - if c.pos-c.count==c.endAt then - c:Pause() - for fe=1,#c.funcE do - c.funcE[fe](c) - end - c.pos=c.start - end - end - thread.skip(c.updaterate) -- lets rest a bit - end - end - end) - self:create(c) - return c -end -function multi:newThreadedTLoop(name,func,n) - local c=self:newTBase() - c.Type='tloopThread' - c.restN=n or 1 - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - function c:OnLoop(func) - table.insert(self.func,func) - end - c.rest=false - c.updaterate=0 - c.restRate=.75 - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) -- rest a bit more when a thread is paused - else - for i=1,#c.func do - c.func[i](c) - end - thread.sleep(c.restN) -- lets rest a bit - end - end - end) - self:create(c) - return c -end -function multi:newThreadedStep(name,start,reset,count,skip) - local c=self:newTBase() - local think=1 - c.Type='stepThread' - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.rest=true - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - c.updaterate=0 - c.restRate=.1 - multi:newThread(name,function(ref) - while true do - if c.rest then - ref:sleep(c.restRate) -- rest a bit more when a thread is paused - else - if c~=nil then - if c.spos==0 then - if c.pos==c.start then - for fe=1,#c.funcS do - c.funcS[fe](c) - end - end - for i=1,#c.func do - c.func[i](c.pos,c) - end - c.pos=c.pos+c.count - if c.pos-c.count==c.endAt then - c:Pause() - for fe=1,#c.funcE do - c.funcE[fe](c) - end - c.pos=c.start - end - end - end - c.spos=c.spos+1 - if c.spos>=c.skip then - c.spos=0 - end - ref:sleep(c.updaterate) -- lets rest a bit - end - end - end) - self:create(c) - return c -end -function multi:newThreadedProcess(name) - local c = {} - setmetatable(c, multi) - function c:newBase(ins) - local ct = {} - setmetatable(ct, self.Parent) - ct.Active=true - ct.func={} - ct.ender={} - ct.Id=0 - ct.PId=0 - ct.Act=function() end - ct.Parent=self - ct.held=false - ct.ref=self.ref - table.insert(self.Mainloop,ct) - return ct - end - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type='process' - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.Active=true - c.Id=-1 - c.Rest=0 - c.updaterate=.01 - c.restRate=.1 - c.Jobs={} - c.queue={} - c.jobUS=2 - c.rest=false - function c:getController() - return nil - end - function c:Start() - self.rest=false - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - function c:Remove() - self.ref:kill() - end - function c:kill() - err=coroutine.yield({"_kill_"}) - if err then - error("Failed to kill a thread! Exiting...") - end - end - function c:sleep(n) - if type(n)=="function" then - ret=coroutine.yield({"_hold_",n}) - elseif type(n)=="number" then - n = tonumber(n) or 0 - ret=coroutine.yield({"_sleep_",n}) - else - error("Invalid Type for sleep!") - end - end - c.hold=c.sleep - multi:newThread(name,function(ref) - while true do - if c.rest then - ref:Sleep(c.restRate) -- rest a bit more when a thread is paused - else - c:uManager() - ref:sleep(c.updaterate) -- lets rest a bit - end - end - end) - return c -end -function multi:newThreadedLoop(name,func) - local c=self:newTBase() - c.Type='loopThread' - c.Start=os.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - function c:OnLoop(func) - table.insert(self.func,func) - end - c.rest=false - c.updaterate=0 - c.restRate=.75 - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) -- rest a bit more when a thread is paused - else - for i=1,#c.func do - c.func[i](os.clock()-self.Start,c) - end - thread.sleep(c.updaterate) -- lets rest a bit - end - end - end) - self:create(c) - return c -end -function multi:newThreadedEvent(name,task) - local c=self:newTBase() - c.Type='eventThread' - c.Task=task or function() end - function c:OnEvent(func) - table.insert(self.func,func) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.Task) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - c.rest=false - c.updaterate=0 - c.restRate=1 - multi:newThread(name,function(ref) - while true do - if c.rest then - ref:sleep(c.restRate) -- rest a bit more when a thread is paused - else - if c.Task(self) then - for _E=1,#c.func do - c.func[_E](c) - end - c:Pause() - end - ref:sleep(c.updaterate) -- lets rest a bit - end - end - end) - self:create(c) - return c -end diff --git a/mulit/examples/love2d Threading Example/multi/integration/lanesManager.lua b/mulit/examples/love2d Threading Example/multi/integration/lanesManager.lua deleted file mode 100644 index a490ce8..0000000 --- a/mulit/examples/love2d Threading Example/multi/integration/lanesManager.lua +++ /dev/null @@ -1,133 +0,0 @@ ---[[ -MIT License - -Copyright (c) 2017 Ryan Ward - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] -function os.getOS() - if package.config:sub(1,1)=='\\' then - return 'windows' - else - return 'unix' - end -end --- Step 1 get lanes -lanes=require("lanes").configure() ---~ package.path="lua/?/init.lua;lua/?.lua;"..package.path -require("multi") -- get it all and have it on all lanes -function multi:canSystemThread() - return true -end -local multi=multi --- Step 2 set up the linda objects -local __GlobalLinda = lanes.linda() -- handles global stuff -local __SleepingLinda = lanes.linda() -- handles sleeping stuff --- For convience a GLOBAL table will be constructed to handle requests -local GLOBAL={} -setmetatable(GLOBAL,{ - __index=function(t,k) - return __GlobalLinda:get(k) - end, - __newindex=function(t,k,v) - __GlobalLinda:set(k,v) - end, -}) --- Step 3 rewrite the thread methods to use lindas -local THREAD={} -function THREAD.set(name,val) - __GlobalLinda:set(name,val) -end -function THREAD.get(name) - __GlobalLinda:get(name) -end -local function randomString(n) - local str = '' - local strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'} - for i=1,n do - str = str..''..strings[math.random(1,#strings)] - end - return str -end -function THREAD.waitFor(name) - local function wait() - math.randomseed(os.time()) - __SleepingLinda:receive(.001,randomString(12)) - end - repeat wait() until __GlobalLinda:get(name) - return __GlobalLinda:get(name) -end -function THREAD.testFor(name,val,sym) - -- -end -function THREAD.getCores() - return THREAD.__CORES -end -if os.getOS()=="windows" then - THREAD.__CORES=tonumber(os.getenv("NUMBER_OF_PROCESSORS")) -else - THREAD.__CORES=tonumber(io.popen("nproc --all"):read("*n")) -end -function THREAD.kill() -- trigger the lane destruction - -- coroutine.yield({"_kill_",":)"}) -end ---[[ Step 4 We need to get sleeping working to handle timing... We want idle wait, not busy wait -Idle wait keeps the CPU running better where busy wait wastes CPU cycles... Lanes does not have a sleep method -however, a linda recieve will in fact be a idle wait! So we use that and wrap it in a nice package]] -function THREAD.sleep(n) - math.randomseed(os.time()) - __SleepingLinda:receive(n,randomString(12)) -end -function THREAD.hold(n) - local function wait() - math.randomseed(os.time()) - __SleepingLinda:receive(.001,randomString(12)) - end - repeat wait() until n() -end --- Step 5 Basic Threads! -function multi:newSystemThread(name,func) - local c={} - local __self=c - c.name=name - c.Type="sthread" - c.thread=lanes.gen("*", func)() - function c:kill() - --self.status:Destroy() - self.thread:cancel() - print("Thread: '"..self.name.."' has been stopped!") - end - c.status=multi:newUpdater(multi.Priority_IDLE) - c.status.link=c - c.status:OnUpdate(function(self) - local v,err,t=self.link.thread:join(.001) - if err then - multi.OnError:Fire(self.link,err) - print("Error in systemThread: '"..self.link.name.."' <"..err..">") - self:Destroy() - end - end) - return c -end -print("Integrated Lanes!") -multi.integration={} -- for module creators -multi.integration.GLOBAL=GLOBAL -multi.integration.THREAD=THREAD -require("multi.integration.shared") -return {init=function() return GLOBAL,THREAD end} diff --git a/mulit/examples/love2d Threading Example/multi/integration/loveManager.lua b/mulit/examples/love2d Threading Example/multi/integration/loveManager.lua deleted file mode 100644 index 56260c7..0000000 --- a/mulit/examples/love2d Threading Example/multi/integration/loveManager.lua +++ /dev/null @@ -1,359 +0,0 @@ -require("multi.compat.love2d") -function multi:canSystemThread() - return true -end -multi.integration={} -multi.integration.love2d={} -multi.integration.love2d.ThreadBase=[[ -tab={...} -__THREADNAME__=tab[2] -__THREADID__=tab[1] -require("love.filesystem") -require("love.system") -require("love.timer") -require("multi") -GLOBAL={} -setmetatable(GLOBAL,{ - __index=function(t,k) - __sync__() - return __proxy__[k] - end, - __newindex=function(t,k,v) - __sync__() - __proxy__[k]=v - if type(v)=="userdata" then - __MainChan__:push(v) - else - __MainChan__:push("SYNC "..type(v).." "..k.." "..resolveData(v)) - end - end, -}) -function __sync__() - local data=__mythread__:pop() - while data do - love.timer.sleep(.001) - if type(data)=="string" then - local cmd,tp,name,d=data:match("(%S-) (%S-) (%S-) (.+)") - if name=="__DIEPLZ"..__THREADID__.."__" then - error("Thread: "..__THREADID__.." has been stopped!") - end - if cmd=="SYNC" then - __proxy__[name]=resolveType(tp,d) - end - else - __proxy__[name]=data - end - data=__mythread__:pop() - end -end -function ToStr(val, name, skipnewlines, depth) - skipnewlines = skipnewlines or false - depth = depth or 0 - local tmp = string.rep(" ", depth) - if name then - if type(name) == "string" then - tmp = tmp .. "[\""..name.."\"] = " - else - tmp = tmp .. "["..(name or "").."] = " - end - end - if type(val) == "table" then - tmp = tmp .. "{" .. (not skipnewlines and " " or "") - for k, v in pairs(val) do - tmp = tmp .. ToStr(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and " " or "") - end - tmp = tmp .. string.rep(" ", depth) .. "}" - elseif type(val) == "number" then - tmp = tmp .. tostring(val) - elseif type(val) == "string" then - tmp = tmp .. string.format("%q", val) - elseif type(val) == "boolean" then - tmp = tmp .. (val and "true" or "false") - elseif type(val) == "function" then - tmp = tmp .. "loadDump([===["..dump(val).."]===])" - else - tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\"" - end - return tmp -end -function resolveType(tp,d) - if tp=="number" then - return tonumber(d) - elseif tp=="bool" then - return (d=="true") - elseif tp=="function" then - return loadDump("[==["..d.."]==]") - elseif tp=="table" then - return loadstring("return "..d)() - elseif tp=="nil" then - return nil - else - return d - end -end -function resolveData(v) - local data="" - if type(v)=="table" then - return ToStr(v) - elseif type(v)=="function" then - return dump(v) - elseif type(v)=="string" or type(v)=="number" or type(v)=="bool" or type(v)=="nil" then - return tostring(v) - end - return data -end -sThread={} -local function randomString(n) - local c=os.clock() - local a=0 - while os.clock()" - c.thread=love.thread.newThread(multi.integration.love2d.ThreadBase:gsub("INSERT_USER_CODE",dump(func))) - c.thread:start(c.ID,c.name) - function c:kill() - multi.integration.GLOBAL["__DIEPLZ"..self.ID.."__"]="__DIEPLZ"..self.ID.."__" - end - return c -end -function love.threaderror( thread, errorstr ) - multi.OnError:Fire(thread,errorstr) - print("Error in systemThread: "..tostring(thread)..": "..errorstr) -end -local THREAD={} -function THREAD.set(name,val) - GLOBAL[name]=val -end -function THREAD.get(name) - return GLOBAL[name] -end -function THREAD.waitFor(name) - multi.OBJ_REF:Pause() - repeat multi:lManager() until GLOBAL[name] - multi.OBJ_REF:Resume() - return GLOBAL[name] -end -function THREAD.getCores() - return love.system.getProcessorCount() -end -function THREAD.sleep(n) - love.timer.sleep(n) -end -function THREAD.hold(n) - multi.OBJ_REF:Pause() - repeat multi:lManager() until n() - multi.OBJ_REF:Resume() -end -__channels__={} -multi.integration.GLOBAL=GLOBAL -multi.integration.THREAD=THREAD -updater=multi:newUpdater() -updater:OnUpdate(function(self) - local data=multi.integration.love2d.mainChannel:pop() - while data do - --print("MAIN:",data) - if type(data)=="string" then - local cmd,tp,name,d=data:match("(%S-) (%S-) (%S-) (.+)") - if cmd=="SYNC" then - __proxy__[name]=resolveType(tp,d) - for i=1,#__channels__ do - -- send data to other threads - if type(v)=="userdata" then - __channels__[i]:push(v) - else - __channels__[i]:push("SYNC "..tp.." "..name.." "..d) - end - end - elseif cmd=="NEWTHREAD" then - __channels__[#__channels__+1]=love.thread.getChannel(tp) - for k,v in pairs(__proxy__) do -- sync the global with each new thread - if type(v)=="userdata" then - __channels__[#__channels__]:push(v) - else - __channels__[#__channels__]:push("SYNC "..type(v).." "..k.." "..resolveData(v)) - end - end - end - else - __proxy__[name]=data - end - data=multi.integration.love2d.mainChannel:pop() - end -end) -require("multi.integration.shared") -print("Integrated Love2d!") -return { - init=function(t) - if t then - if t.threadNamespace then - multi.integration.THREADNAME=t.threadNamespace - multi.integration.love2d.ThreadBase:gsub("sThread",t.threadNamespace) - end - if t.globalNamespace then - multi.integration.GLOBALNAME=t.globalNamespace - multi.integration.love2d.ThreadBase:gsub("GLOBAL",t.globalNamespace) - end - end - return GLOBAL,THREAD - end -} diff --git a/mulit/examples/love2d Threading Example/multi/integration/shared.lua b/mulit/examples/love2d Threading Example/multi/integration/shared.lua deleted file mode 100644 index 63ff000..0000000 --- a/mulit/examples/love2d Threading Example/multi/integration/shared.lua +++ /dev/null @@ -1,359 +0,0 @@ ---[[ -MIT License - -Copyright (c) 2017 Ryan Ward - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] -function multi.randomString(n) - local str = '' - local strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'} - for i=1,n do - str = str..''..strings[math.random(1,#strings)] - end - return str -end -function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a channel on both ends - local c={} -- where we will store our object - c.name=name -- set the name this is important for the love2d side - if love then -- check love - if love.thread then -- make sure we can use the threading module - function c:init() -- create an init function so we can mimic on bith love2d and lanes - self.chan=love.thread.getChannel(self.name) -- create channel by the name self.name - function self:push(v) -- push to the channel - self.chan:push({type(v),resolveData(v)}) - end - function self:pop() -- pop from the channel - local tab=self.chan:pop() - --print(tab) - if not tab then return end - return resolveType(tab[1],tab[2]) - end - function self:peek() - local tab=self.chan:peek() - --print(tab) - if not tab then return end - return resolveType(tab[1],tab[2]) - end - GLOBAL[self.name]=self -- send the object to the thread through the global interface - return self -- return the object - end - return c - else - error("Make sure you required the love.thread module!") -- tell the user if he/she didn't require said module - end - else - c.linda=lanes.linda() -- lanes is a bit eaiser, create the linda on the main thread - function c:push(v) -- push to the queue - self.linda:send("Q",v) - end - function c:pop() -- pop the queue - return ({self.linda:receive(0,"Q")})[2] - end - function c:peek() - return self.linda:get("Q") - end - function c:init() -- mimic the feature that love2d requires, so code can be consistent - return self - end - multi.integration.GLOBAL[name]=c -- send the object to the thread through the global interface - end - return c -end -function multi:systemThreadedBenchmark(n,p) - n=n or 1 - local cores=multi.integration.THREAD.getCores() - local queue=multi:newSystemThreadedQueue("QUEUE") - multi.integration.GLOBAL["__SYSTEMBENCHMARK__"]=n - local sThread=multi.integration.THREAD - local GLOBAL=multi.integration.GLOBAL - for i=1,cores do - multi:newSystemThread("STHREAD_BENCH",function() - require("multi") - if multi:getPlatform()=="love2d" then - GLOBAL=_G.GLOBAL - sThread=_G.sThread - end -- we cannot have upvalues... in love2d globals not locals must be used - queue=sThread.waitFor("QUEUE"):init() -- always wait for when looking for a variable at the start of the thread! - multi:benchMark(sThread.waitFor("__SYSTEMBENCHMARK__")):OnBench(function(self,count) - queue:push(count) - multi:Stop() - end) - multi:mainloop() - end) - end - local c={} - c.tt=function() end - c.p=p - function c:OnBench(func) - self.tt=func - end - multi:newThread("THREAD_BENCH",function() - thread.sleep(n+.1) - GLOBAL["QUEUE"]=nil -- time to clean up - local num=0 - data=queue:pop() - while data do - num=num+data - data=queue:pop() - end - if p then - print(tostring(p)..num) - end - c.tt(c,num) - end) - return c -end -function multi:newSystemThreadedTable(name,n) - local c={} -- where we will store our object - c.name=name -- set the name this is important for the love2d side - c.cores=n - c.hasT={} - if love then -- check love - if love.thread then -- make sure we can use the threading module - function c:init() -- create an init function so we can mimic on bith love2d and lanes - self.tab={} - self.chan=love.thread.getChannel(self.name) -- create channel by the name self.name - function self:waitFor(name) -- pop from the channel - repeat self:sync() until self[name] - return self[name] - end - function self:sync() - local data=self.chan:peek() - if data then - local cmd,tp,name,d=data:match("(%S-) (%S-) (%S-) (.+)") - if not self.hasT[name] then - if type(data)=="string" then - if cmd=="SYNC" then - self.tab[name]=resolveType(tp,d) -- this is defined in the loveManager.lua file - self.hasT[name]=true - end - else - self.tab[name]=data - end - self.chan:pop() - end - end - end - function self:reset(name) - self.hasT[core]=nil - end - setmetatable(self,{ - __index=function(t,k) - self:sync() - return self.tab[k] - end, - __newindex=function(t,k,v) - self:sync() - self.tab[k]=v - if type(v)=="userdata" then - self.chan:push(v) - else - for i=1,self.cores do - self.chan:push("SYNC "..type(v).." "..k.." "..resolveData(v)) -- this is defined in the loveManager.lua file - end - end - end, - }) - GLOBAL[self.name]=self -- send the object to the thread through the global interface - return self -- return the object - end - return c - else - error("Make sure you required the love.thread module!") -- tell the user if he/she didn't require said module - end - else - c.linda=lanes.linda() -- lanes is a bit eaiser, create the linda on the main thread - function c:waitFor(name) - while self[name]==nil do - -- Waiting - end - return self[name] - end - function c:sync() - return -- just so we match the love2d side - end - function c:init() -- set the metatable - setmetatable(self,{ - __index=function(t,k) - return self.linda:get(k) - end, - __newindex=function(t,k,v) - self.linda:set(k,v) - end, - }) - return self - end - multi.integration.GLOBAL[name]=c -- send the object to the thread through the global interface - end - return c -end -function multi:newSystemThreadedJobQueue(numOfCores) - local c={} - c.jobnum=1 - c.cores=numOfCores or multi.integration.THREAD.getCores() - c.queueIN=multi:newSystemThreadedQueue("THREADED_JQ"):init() - c.queueOUT=multi:newSystemThreadedQueue("THREADED_JQO"):init() - c.queueALL=multi:newSystemThreadedQueue("THREADED_QALL"):init() - c.REG=multi:newSystemThreadedQueue("THREADED_JQ_F_REG"):init() - -- registerJob(name,func) - -- pushJob(...) - function c:registerJob(name,func) - for i=1,self.cores do - self.REG:push({name,func}) - end - end - function c:pushJob(name,...) - self.queueOUT:push({self.jobnum,name,...}) - self.jobnum=self.jobnum+1 - end - local GLOBAL=multi.integration.GLOBAL -- set up locals incase we are using lanes - local sThread=multi.integration.THREAD -- set up locals incase we are using lanes - function c:doToAll(func) - local TaskName=multi.randomString(16) - for i=1,self.cores do - self.queueALL:push({TaskName,func}) - end - end - function c:start() - self:doToAll(function() - _G["__started__"]=true - SFunc() - end) - end - GLOBAL["__JQ_COUNT__"]=c.cores - for i=1,c.cores do - multi:newSystemThread("System Threaded Job Queue Worker Thread #"..i,function() - require("multi") - __sleep__=.001 - if love then -- lets make sure we don't reference upvalues if using love2d - GLOBAL=_G.GLOBAL - sThread=_G.sThread - __sleep__=.1 - end - JQI=sThread.waitFor("THREADED_JQO"):init() -- Grab it - JQO=sThread.waitFor("THREADED_JQ"):init() -- Grab it - REG=sThread.waitFor("THREADED_JQ_F_REG"):init() -- Grab it - QALL=sThread.waitFor("THREADED_QALL"):init() -- Grab it - sThread.sleep(.1) -- lets wait for things to work out - GLOBAL["THREADED_JQ"]=nil -- remove it - GLOBAL["THREADED_JQO"]=nil -- remove it - GLOBAL["THREADED_JQ_F_REG"]=nil -- remove it - QALLT={} - FUNCS={} - SFunc=multi:newFunction(function(self) - MainLoop:Pause() - self:hold(.1) - MainLoop:Resume() - self:Pause() - end) - multi:newLoop(function() - local rd=REG:peek() - if rd then - if not FUNCS[rd[1]] then - FUNCS[rd[1]]=rd[2] - rd=nil -- lets clean up - REG:pop() - end - end - local d=QALL:peek() - if d then - if not QALLT[d[1]] then - QALLT[d[1]]=true - d[2]() - d=nil -- lets clean up - QALL:pop() - end - end - end) - setmetatable(_G,{ - __index=function(t,k) - return FUNCS[k] - end - }) - MainLoop=multi:newLoop(function(self) - if __started__ then - local job=JQI:pop() - if job then - local d=QALL:peek() - if d then - if not QALLT[d[1]] then - QALLT[d[1]]=true - d[2]() - d=nil -- lets clean up - QALL:pop() - end - end - local ID=table.remove(job,1) -- return and remove - local name=table.remove(job,1) -- return and remove - if FUNCS[name] then - JQO:push({ID,FUNCS[name](unpack(job))}) - else - self:hold(function() return FUNCS[name] end) - JQO:push({ID,FUNCS[name](unpack(job))}) - end - end - end - end) - if not love then - multi:mainloop() - end - end) - end - c.OnJobCompleted=multi:newConnection() - c.updater=multi:newLoop(function(self) - local data=self.link.queueIN:pop() - while data do - if data then - self.link.OnJobCompleted:Fire(unpack(data)) - end - data=self.link.queueIN:pop() - end - end) - c.updater.link=c - return c -end -function multi:newSystemThreadedExecute(cmd) - local c={} - local GLOBAL=multi.integration.GLOBAL -- set up locals incase we are using lanes - local sThread=multi.integration.THREAD -- set up locals incase we are using lanes - local name="Execute_Thread"..multi.randomString(16) - c.name=name - GLOBAL[name.."CMD"]=cmd - multi:newSystemThread(name,function() - if love then -- lets make sure we don't reference upvalues if using love2d - GLOBAL=_G.GLOBAL - sThread=_G.sThread - name=__THREADNAME__ -- global data same as the name we used in this functions creation - end -- Lanes should take the local upvalues ^^^ - cmd=sThread.waitFor(name.."CMD") - local ret=os.execute(cmd) - GLOBAL[name.."R"]=ret - end) - c.OnCMDFinished=multi:newConnection() - c.looper=multi:newLoop(function(self) - local ret=GLOBAL[self.link.name.."R"] - if ret then - self.link.OnCMDFinished:Fire(ret) - self:Destroy() - end - end) - c.looper.link=c - return c -end diff --git a/mulit/multi/all.lua b/mulit/multi/all.lua deleted file mode 100644 index d14aac6..0000000 --- a/mulit/multi/all.lua +++ /dev/null @@ -1 +0,0 @@ -require("multi") diff --git a/mulit/multi/compat/backwards[1,5,0].lua b/mulit/multi/compat/backwards[1,5,0].lua deleted file mode 100644 index a0f52a8..0000000 --- a/mulit/multi/compat/backwards[1,5,0].lua +++ /dev/null @@ -1,305 +0,0 @@ ---[[ -MIT License - -Copyright (c) 2017 Ryan Ward - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] -multi.OnObjectCreated(function(obj) - if obj.Type=="loop" then - function obj:Act() - for i=1,#self.func do - self.func[i](self.Parent.clock()-self.Start,self) - end - end - elseif obj.Type=="step" then - function obj:Act() - if self~=nil then - if self.spos==0 then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - elseif obj.Type=="tstep" then - function c:Act() - if self.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - end -end) -if thread then - function multi:newThreadedLoop(name,func) - local c=self:newTBase() - c.Type='loopThread' - c.Start=os.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - function c:OnLoop(func) - table.insert(self.func,func) - end - c.rest=false - c.updaterate=0 - c.restRate=.75 - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) - else - for i=1,#c.func do - c.func[i](os.clock()-self.Start,c) - end - thread.sleep(c.updaterate) - end - end - end) - self:create(c) - return c - end - function multi:newThreadedStep(name,start,reset,count,skip) - local c=self:newTBase() - local think=1 - c.Type='stepThread' - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.rest=true - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - c.updaterate=0 - c.restRate=.1 - multi:newThread(name,function(ref) - while true do - if c.rest then - ref:sleep(c.restRate) - else - if c~=nil then - if c.spos==0 then - if c.pos==c.start then - for fe=1,#c.funcS do - c.funcS[fe](c) - end - end - for i=1,#c.func do - c.func[i](c.pos,c) - end - c.pos=c.pos+c.count - if c.pos-c.count==c.endAt then - c:Pause() - for fe=1,#c.funcE do - c.funcE[fe](c) - end - c.pos=c.start - end - end - end - c.spos=c.spos+1 - if c.spos>=c.skip then - c.spos=0 - end - ref:sleep(c.updaterate) - end - end - end) - self:create(c) - return c - end - function multi:newThreadedTStep(name,start,reset,count,set) - local c=self:newTBase() - local think=1 - c.Type='tstepThread' - c.Priority=self.Priority_Low - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=os.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=self.start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=os.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - c.updaterate=0 - c.restRate=0 - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) - else - if os.clock()-c.timer>=c.set then - c:Reset() - if c.pos==c.start then - for fe=1,#c.funcS do - c.funcS[fe](c) - end - end - for i=1,#c.func do - c.func[i](c.pos,c) - end - c.pos=c.pos+c.count - if c.pos-c.count==c.endAt then - c:Pause() - for fe=1,#c.funcE do - c.funcE[fe](c) - end - c.pos=c.start - end - end - thread.skip(c.updaterate) - end - end - end) - self:create(c) - return c - end -end diff --git a/mulit/multi/compat/love2d.lua b/mulit/multi/compat/love2d.lua deleted file mode 100644 index cc4015d..0000000 --- a/mulit/multi/compat/love2d.lua +++ /dev/null @@ -1,114 +0,0 @@ ---[[ -MIT License - -Copyright (c) 2017 Ryan Ward - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] -require("multi") -os.sleep=love.timer.sleep -function love.run() - if love.math then - love.math.setRandomSeed(os.time()) - end - if love.event then - love.event.pump() - end - if love.load then love.load(arg) end - if love.timer then love.timer.step() end - local dt = 0 - while true do - -- Process events. - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - if multi.boost then - for i=1,multi.boost-1 do - multi:uManager(dt) - end - end - multi:uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - multi.dManager() - love.graphics.setColor(255,255,255,255) - if multi.draw then multi.draw() end - love.graphics.present() - end - end -end -multi.drawF={} -function multi:dManager() - for ii=1,#multi.drawF do - multi.drawF[ii]() - end -end -function multi:onDraw(func,i) - i=i or 1 - table.insert(self.drawF,i,func) -end -function multi:lManager() - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return nil - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - multi:uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - multi.dManager() - love.graphics.setColor(255,255,255,255) - if multi.draw then multi.draw() end - love.graphics.present() - end -end diff --git a/mulit/multi/init.lua b/mulit/multi/init.lua deleted file mode 100644 index 1c98dfa..0000000 --- a/mulit/multi/init.lua +++ /dev/null @@ -1,2141 +0,0 @@ ---[[ -MIT License - -Copyright (c) 2017 Ryan Ward - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] -if table.unpack then - unpack=table.unpack -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -_print=print -function print(...) - if not __SUPPRESSPRINTS then - _print(...) - end -end -multi = {} -multi.Version="1.8.6" -multi._VERSION="1.8.6" -multi.stage='mostly-stable' -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.ender={} -multi.Children={} -multi.Paused={} -multi.Active=true -multi.fps=60 -multi.Id=-1 -multi.Type='mainprocess' -multi.Rest=0 -multi._type=type -multi.Jobs={} -multi.queue={} -multi.jobUS=2 -multi.clock=os.clock -multi.time=os.time -multi.LinkedPath=multi -multi.isRunning=false -multi.queuefinal=function(self) - self:Destroy() - if self.Parent.Mainloop[#self.Parent.Mainloop] then - if self.Parent.Mainloop[#self.Parent.Mainloop].Type=="alarm" then - self.Parent.Mainloop[#self.Parent.Mainloop]:Reset() - self.Parent.Mainloop[#self.Parent.Mainloop].Active=true - else - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end - else - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end -end ---Do not change these ever...Any other number will not work (Unless you are using enablePriority2() then change can be made. Just ensure that Priority_Idle is the greatest and Priority_Core is 1!) -multi.Priority_Core=1 -multi.Priority_High=4 -multi.Priority_Above_Normal=16 -multi.Priority_Normal=64 -multi.Priority_Below_Normal=256 -multi.Priority_Low=1024 -multi.Priority_Idle=4096 -multi.PList={multi.Priority_Core,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Idle} -multi.PStep=1 ---^^^^ -multi.PriorityTick=1 -- Between 1 and 4 any greater and problems arise -multi.Priority=multi.Priority_Core -multi.threshold=256 -multi.threstimed=.001 -function multi:setThreshold(n) - self.threshold=n or 120 -end -function multi:setThrestimed(n) - self.threstimed=n or .001 -end -function multi:getLoad() - return multi:newFunction(function(self) - multi.scheduler:Pause() - local sample=#multi.Mainloop - local FFloadtest=0 - multi:benchMark(multi.threstimed):OnBench(function(_,l3) FFloadtest=l3*(1/multi.threstimed) end) - self:hold(function() return FFloadtest~=0 end) - local val=FFloadtest/sample - multi.scheduler:Resume() - if val>multi.threshold then - return 0 - else - return 100-((val/multi.threshold)*100) - end - end)() -end -function multi:setDomainName(name) - self[name]={} -end -function multi:linkDomain(name) - return self[name] -end -function multi:_Pause() - self.Active=false -end -function multi:setPriority(s) - if type(s)==number then - self.Priority=s - elseif type(s)=='string' then - if s:lower()=='core' or s:lower()=='c' then - self.Priority=self.Priority_Core - elseif s:lower()=='high' or s:lower()=='h' then - self.Priority=self.Priority_High - elseif s:lower()=='above' or s:lower()=='an' then - self.Priority=self.Priority_Above_Normal - elseif s:lower()=='normal' or s:lower()=='n' then - self.Priority=self.Priority_Normal - elseif s:lower()=='below' or s:lower()=='bn' then - self.Priority=self.Priority_Below_Normal - elseif s:lower()=='low' or s:lower()=='l' then - self.Priority=self.Priority_Low - elseif s:lower()=='idle' or s:lower()=='i' then - self.Priority=self.Priority_Idle - end - end -end --- System -function os.getOS() - if package.config:sub(1,1)=='\\' then - return 'windows' - else - return 'unix' - end -end -if os.getOS()=='windows' then - function os.sleep(n) - if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end - end -else - function os.sleep(n) - os.execute('sleep ' .. tonumber(n)) - end -end -function multi:getParentProcess() - return self.Mainloop[self.CID] -end -multi.GetParentProcess=multi.getParentProcess -function multi:Stop() - self.Active=false -end -function multi:condition(cond) - if not self.CD then - self:Pause() - self.held=true - self.CD=cond.condition - elseif not(cond.condition()) then - self.held=false - self:Resume() - self.CD=nil - return false - end - self.Parent:Do_Order() - return true -end -multi.Condition=multi.condition -function multi:isHeld() - return self.held -end -multi.IsHeld=multi.isHeld -function multi.executeFunction(name,...) - if type(_G[name])=='function' then - _G[name](...) - else - print('Error: Not a function') - end -end -function multi:waitFor(obj) - local value=false - self.__waiting=function() - value=true - end - obj:connectFinal(self.__waiting) - self:hold(function() return value end) -end -multi.WaitFor=multi.waitFor -function multi:reboot(r) - local before=collectgarbage('count') - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=='table' then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end - collectgarbage() - local after=collectgarbage('count') - print([[Before rebooting total Ram used was ]]..before..[[Kb -After rebooting total Ram used is ]]..after..[[ Kb -A total of ]]..(before-after)..[[Kb was cleaned up]]) -end -function multi:getChildren() - return self.Mainloop -end -function multi:getVersion() - return multi.Version -end -function multi:getPlatform() - if love then - if love.thread then - return "love2d" - end - else - return "lanes" - end -end -function multi:canSystemThread() - return false -end ---Processor -function multi:getError() - if self.error then - return self.error - end -end -function multi:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:enablePriority() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PList[PS.PStep])%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>7 then - PS.PStep=1 - end - end -end -function multi:enablePriority2() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PStep)%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>self.Priority_Idle then - PS.PStep=1 - end - end -end -multi.disablePriority=multi.unProtect -function multi:fromfile(path,int) - int=int or self - local test2={} - local test=bin.load(path) - local tp=test:getBlock('s') - if tp=='event' then - test2=int:newEvent(test:getBlock('f')) - local t=test:getBlock('t') - for i=1,#t do - test2:OnEvent(t[i]) - end - elseif tp=='alarm' then - test2=int:newAlarm(test:getBlock('n')) - elseif tp=='loop' then - test2=int:newLoop(test:getBlock('t')[1]) - elseif tp=='step' or tp=='tstep' then - local func=test:getBlock('t') - local funcE=test:getBlock('t') - local funcS=test:getBlock('t') - local tab=test:getBlock('t') - test2=int:newStep() - table.merge(test2,tab) - test2.funcE=funcE - test2.funcS=funcS - test2.func=func - elseif tp=='trigger' then - test2=int:newTrigger(test:getBlock('f')) - elseif tp=='connector' then - test2=int:newConnection() - test2.func=test:getBlock('t') - elseif tp=='timer' then - test2=int:newTimer() - test2.count=tonumber(test:getBlock('n')) - else - print('Error: The file you selected is not a valid multi file object!') - return false - end - return test2 -end -function multi:benchMark(sec,p,pt) - local temp=self:newLoop(function(self,t) - if self.clock()-self.init>self.sec then - if pt then - print(pt.." "..self.c.." Steps in "..sec.." second(s)!") - end - self.tt(self.sec,self.c) - self:Destroy() - else - self.c=self.c+1 - end - end) - temp.Priority=p or 1 - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=self.clock() - temp.c=0 - return temp -end -function multi:tofile(path) - local items=self:getChildren() - io.mkDir(io.getName(path)) - for i=1,#items do - items[i]:tofile(io.getName(path)..'\\item'..item[i]..'.dat') - end - local int=bin.new() - int:addBlock('process') - int:addBlock(io.getName(path)) - int:addBlock(#self.Mainloop) - int:addBlock(self.Active) - int:addBlock(self.Rest) - int:addBlock(self.Jobs) - int:tofile() -end -function multi.startFPSMonitior() - if not multi.runFPS then - multi.doFPS(s) - multi.runFPS=true - end -end -function multi.doFPS(s) - multi:benchMark(1):OnBench(doFPS) - if s then - multi.fps=s - end -end ---Helpers -function multi:IsAnActor() - return ({watcher=true,tstep=true,step=true,updater=true,loop=true,alarm=true,event=true})[self.Type] -end -function multi:OnMainConnect(func) - table.insert(self.func,func) -end -function multi:protect() - function self:Do_Order() - local Loop=self.Mainloop - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - self.CID=_D - local status, err=pcall(Loop[_D].Act,Loop[_D]) - if err and not(Loop[_D].error) then - Loop[_D].error=err - self.OnError:Fire(Loop[_D],err) - end - end - end - end -end -function multi:unProtect() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:reallocate(o,n) - n=n or #o.Mainloop+1 - local int=self.Parent - self:Destroy() - self.Parent=o - table.insert(o.Mainloop,n,self) - self.Active=true -end -multi.Reallocate=multi.Reallocate -function multi:setJobSpeed(n) - self.jobUS=n -end -function multi:hasJobs() - return #self.Jobs>0,#self.Jobs -end -function multi:getJobs() - return #self.Jobs -end -function multi:removeJob(name) - for i=#self.Jobs,1,-1 do - if self.Jobs[i][2]==name then - table.remove(self.Jobs,i) - end - end -end -function multi:FreeMainEvent() - self.func={} -end -function multi:connectFinal(func) - if self.Type=='event' then - self:OnEvent(func) - elseif self.Type=='alarm' then - self:OnRing(func) - elseif self.Type=='step' or self.Type=='tstep' then - self:OnEnd(func) - else - print("Warning!!! "..self.Type.." doesn't contain a Final Connection State! Use "..self.Type..":Break(function) to trigger it's final event!") - self:OnBreak(func) - end -end -multi.ConnectFinal=multi.connectFinal -function multi:Break() - self:Pause() - self.Active=nil - for i=1,#self.ender do - if self.ender[i] then - self.ender[i](self) - end - end -end -function multi:OnBreak(func) - table.insert(self.ender,func) -end -function multi:isPaused() - return not(self.Active) -end -multi.IsPaused=multi.isPaused -function multi:isActive() - return self.Active -end -multi.IsActive=multi.isActive -function multi:getType() - return self.Type -end -multi.GetType=multi.getType -function multi:Sleep(n) - self:hold(n) -end -multi.sleep=multi.Sleep --- Advance Timer stuff -function multi:SetTime(n) - if not n then n=3 end - local c=multi:newBase() - c.Type='timemaster' - c.timer=multi:newTimer() - c.timer:Start() - c.set=n - c.link=self - self._timer=c.timer - function c:Act() - if self.timer:Get()>=self.set then - self.link:Pause() - for i=1,#self.link.funcTM do - self.link.funcTM[i](self.link) - end - self:Destroy() - end - end - return c -end -multi.ResetTime=multi.SetTime -function multi:ResolveTimer(...) - self._timer:Pause() - for i=1,#self.funcTMR do - self.funcTMR[i](self,...) - end - self:Pause() -end -function multi:OnTimedOut(func) - self.funcTM[#self.funcTM+1]=func -end -function multi:OnTimerResolved(func) - self.funcTMR[#self.funcTMR+1]=func -end --- Timer stuff done -function multi:Pause() - if self.Type=='mainprocess' then - print("You cannot pause the main process. Doing so will stop all methods and freeze your program! However if you still want to use multi:_Pause()") - else - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - end -end -function multi:Resume() - if self.Type=='process' or self.Type=='mainprocess' then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:resurrect() - table.insert(self.Parent.Mainloop,self) - self.Active=true -end -multi.Resurrect=multi.resurrect -function multi:Destroy() - if self.Type=='process' or self.Type=='mainprocess' then - local c=self:getChildren() - for i=1,#c do - self.OnObjectDestroyed:Fire(c[i]) - c[i]:Destroy() - end - else - for i=1,#self.Parent.Mainloop do - if self.Parent.Mainloop[i]==self then - self.Parent.OnObjectDestroyed:Fire(self) - table.remove(self.Parent.Mainloop,i) - break - end - end - self.Active=false - end -end - -function multi:hold(task) - self:Pause() - self.held=true - if type(task)=='number' then - local timer=multi:newTimer() - timer:Start() - while timer:Get()0 then ---~ for i=1,#self.Parent.FC do ---~ self.Parent.FC[i]:Fire(...) ---~ end ---~ end - if self.Parent.protect then - local t=pcall(self.func,...) - if t then - return t - end - else - return self.func(...) - end - end, - Remove=function(self) - for i=1,#self.Link do - if self.Link[i][2]~=nil then - if self.Link[i][2]==self.ID then - table.remove(self.Link,i) - self.remove=function() end - self.Link=nil - self.ID=nil - return true - end - end - end - end - } - if name then - self.connections[name]=temp - end - return temp - end - c.Connect=c.connect - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:tofile(path) - end - return c -end -multi.OnObjectCreated=multi:newConnection() -multi.OnObjectDestroyed=multi:newConnection() -function multi:newJob(func,name) - if not(self.Type=='mainprocess' or self.Type=='process') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='process' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Parent=self - c.Type='job' - c.trigfunc=func or function() end - function c:Act() - self:trigfunc(self) - end - table.insert(self.Jobs,{c,name}) - if self.JobRunner==nil then - self.JobRunner=self:newAlarm(self.jobUS) - self.JobRunner:OnRing(function(self) - if #self.Parent.Jobs>0 then - if self.Parent.Jobs[1] then - self.Parent.Jobs[1][1]:Act() - table.remove(self.Parent.Jobs,1) - end - end - self:Reset(self.Parent.jobUS) - end) - end -end -function multi:newRange() - local selflink=self - local temp={ - getN = function(self) selflink:Do_Order() self.n=self.n+self.c if self.n>self.b then self.Link.held=false self.Link:Resume() return nil end return self.n end, - } - setmetatable(temp,{ - __call=function(self,a,b,c) - self.c=c or 1 - self.n=a-self.c - self.a=a - self.b=b - self.Link=selflink--.Parent.Mainloop[selflink.CID] or - self.Link:Pause() - self.Link.held=true - return function() return self:getN() end - end - }) - self:create(temp) - return temp -end -multi.NewRange=multi.newRange -function multi:newCondition(func) - local c={['condition']=func,Type="condition"} - self:create(c) - return c -end -multi.NewCondition=multi.newCondition -function multi:mainloop() - if not multi.isRunning then - multi.isRunning=true - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - self:Do_Order() - end - else - return "Already Running!" - end -end -function multi:protectedMainloop() - multi:protect() - if not multi.isRunning then - multi.isRunning=true - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - self:Do_Order() - end - else - return "Already Running!" - end -end -function multi:unprotectedMainloop() - multi:unProtect() - if not multi.isRunning then - multi.isRunning=true - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - else - return "Already Running!" - end -end -function multi:prioritizedMainloop1() - multi:enablePriority() - if not multi.isRunning then - multi.isRunning=true - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PList[PS.PStep])%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>7 then - PS.PStep=1 - end - end - else - return "Already Running!" - end -end -function multi:prioritizedMainloop2() - multi:enablePriority2() - if not multi.isRunning then - multi.isRunning=true - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PStep)%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>self.Priority_Idle then - PS.PStep=1 - end - end - else - return "Already Running!" - end -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - rawset(self,'Start',self.clock()) -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - function self:uManager(dt) - self:Do_Order() - end - self:Do_Order() - end -end ---Core Actors -function multi:newCustomObject(objRef,t) - local c={} - if t=='process' then - c=self:newBase() - if type(objRef)=='table' then - table.merge(c,objRef) - end - if not c.Act then - function c:Act() - -- Empty function - end - end - else - c=objRef or {} - end - if not c.Type then - c.Type='coustomObject' - end - self:create(c) - return c -end -function multi:newEvent(task) - local c=self:newBase() - c.Type='event' - c.Task=task or function() end - function c:Act() - if self.Task(self) then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:SetTask(func) - self.Task=func - end - function c:OnEvent(func) - table.insert(self.func,func) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.Task) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newUpdater(skip) - local c=self:newBase() - c.Type='updater' - c.pos=1 - c.skip=skip or 1 - function c:Act() - if self.pos>=self.skip then - self.pos=0 - for i=1,#self.func do - self.func[i](self) - end - end - self.pos=self.pos+1 - end - function c:setSkip(n) - self.skip=n - end - c.OnUpdate=self.OnMainConnect - self:create(c) - return c -end -function multi:newAlarm(set) - local c=self:newBase() - c.Type='alarm' - c.Priority=self.Priority_Low - c.timer=self:newTimer() - c.set=set or 0 - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.set) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.timer:Get()>=self.set then - self:Pause() - self.Active=false - for i=1,#self.func do - self.func[i](self) - end - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer:Resume() - end - function c:Reset(n) - if n then self.set=n end - self:Resume() - self.timer:Reset() - end - function c:OnRing(func) - table.insert(self.func,func) - end - function c:Pause() - self.timer:Pause() - self.Parent.Pause(self) - end - self:create(c) - return c -end -function multi:newLoop(func) - local c=self:newBase() - c.Type='loop' - c.Start=self.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - for i=1,#self.func do - self.func[i](self,self.Parent.clock()-self.Start) - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - self:create(c) - return c -end -function multi:newFunction(func) - local c={} - c.func=func - mt={ - __index=multi, - __call=function(self,...) if self.Active then return self:func(...) end local t={...} return "PAUSED" end - } - c.Parent=self - function c:Pause() - self.Active=false - end - function c:Resume() - self.Active=true - end - setmetatable(c,mt) - self:create(c) - return c -end -function multi:newStep(start,reset,count,skip) - local c=self:newBase() - think=1 - c.Type='step' - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self,self.pos) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - self:create(c) - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newTLoop(func,set) - local c=self:newBase() - c.Type='tloop' - c.set=set or 0 - c.timer=self:newTimer() - c.life=0 - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.timer:Get()>=self.set then - self.life=self.life+1 - for i=1,#self.func do - self.func[i](self,self.life) - end - self.timer:Reset() - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer:Resume() - end - function c:Pause() - self.timer:Pause() - self.Parent.Pause(self) - end - function c:OnLoop(func) - table.insert(self.func,func) - end - self:create(c) - return c -end -function multi:newTrigger(func) - local c={} - c.Type='trigger' - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(...) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.trigfunc) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newTStep(start,reset,count,set) - local c=self:newBase() - think=1 - c.Type='tstep' - c.Priority=self.Priority_Low - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=self.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=self.start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=self.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self,self.pos) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=self.clock() - self:Resume() - end - self:create(c) - return c -end -function multi:newWatcher(namespace,name) - local function WatcherObj(ns,n) - if self.Type=='queue' then - print("Cannot create a watcher on a queue! Creating on 'multi' instead!") - self=multi - end - local c=self:newBase() - c.Type='watcher' - c.ns=ns - c.n=n - c.cv=ns[n] - function c:OnValueChanged(func) - table.insert(self.func,func) - end - function c:Act() - if self.cv~=self.ns[self.n] then - for i=1,#self.func do - self.func[i](self,self.cv,self.ns[self.n]) - end - self.cv=self.ns[self.n] - end - end - self:create(c) - return c - end - if type(namespace)~='table' and type(namespace)=='string' then - return WatcherObj(_G,namespace) - elseif type(namespace)=='table' and (type(name)=='string' or 'number') then - return WatcherObj(namespace,name) - else - print('Warning, invalid arguments! Nothing returned!') - end -end --- Threading stuff -thread={} -multi.GlobalVariables={} -if os.getOS()=="windows" then - thread.__CORES=tonumber(os.getenv("NUMBER_OF_PROCESSORS")) -else - thread.__CORES=tonumber(io.popen("nproc --all"):read("*n")) -end -function thread.sleep(n) - coroutine.yield({"_sleep_",n or 0}) -end -function thread.hold(n) - coroutine.yield({"_hold_",n or function() return true end}) -end -function thread.skip(n) - coroutine.yield({"_skip_",n or 0}) -end -function thread.kill() - coroutine.yield({"_kill_",":)"}) -end -function thread.yeild() - coroutine.yield({"_sleep_",0}) -end -function thread.getCores() - return thread.__CORES -end -function thread.set(name,val) - multi.GlobalVariables[name]=val - return true -end -function thread.get(name) - return multi.GlobalVariables[name] -end -function thread.waitFor(name) - thread.hold(function() return thread.get(name)~=nil end) - return thread.get(name) -end -function thread.testFor(name,val,sym) - thread.hold(function() return thread.get(name)~=nil end) - return thread.get(name) -end -function multi:newTBase(ins) - local c = {} - c.Active=true - c.func={} - c.ender={} - c.Id=0 - c.PId=0 - c.Parent=self - c.held=false - return c -end -function multi:newThread(name,func) - local c={} - c.ref={} - c.Name=name - c.thread=coroutine.create(func) - c.sleep=1 - c.Type="thread" - c.firstRunDone=false - c.timer=multi.scheduler:newTimer() - c.ref.Globals=self:linkDomain("Globals") - function c.ref:send(name,val) - ret=coroutine.yield({Name=name,Value=val}) - self:syncGlobals(ret) - end - function c.ref:get(name) - return self.Globals[name] - end - function c.ref:kill() - err=coroutine.yield({"_kill_"}) - if err then - error("Failed to kill a thread! Exiting...") - end - end - function c.ref:sleep(n) - if type(n)=="function" then - ret=coroutine.yield({"_hold_",n}) - self:syncGlobals(ret) - elseif type(n)=="number" then - n = tonumber(n) or 0 - ret=coroutine.yield({"_sleep_",n}) - self:syncGlobals(ret) - else - error("Invalid Type for sleep!") - end - end - function c.ref:syncGlobals(v) - self.Globals=v - end - table.insert(self:linkDomain("Threads"),c) - if not multi.scheduler:isActive() then - multi.scheduler:Resume() - end -end -multi:setDomainName("Threads") -multi:setDomainName("Globals") -multi.scheduler=multi:newLoop() -multi.scheduler.Type="scheduler" -function multi.scheduler:setStep(n) - self.skip=tonumber(n) or 24 -end -multi.scheduler.skip=0 -multi.scheduler.counter=0 -multi.scheduler.Threads=multi:linkDomain("Threads") -multi.scheduler.Globals=multi:linkDomain("Globals") -multi.scheduler:OnLoop(function(self) - self.counter=self.counter+1 - for i=#self.Threads,1,-1 do - ret={} - if coroutine.status(self.Threads[i].thread)=="dead" then - table.remove(self.Threads,i) - else - if self.Threads[i].timer:Get()>=self.Threads[i].sleep then - if self.Threads[i].firstRunDone==false then - self.Threads[i].firstRunDone=true - self.Threads[i].timer:Start() - _,ret=coroutine.resume(self.Threads[i].thread,self.Threads[i].ref) - else - _,ret=coroutine.resume(self.Threads[i].thread,self.Globals) - end - if _==false then - self.Parent.OnError:Fire(self.Threads[i],ret) - print("Error in thread: <"..self.Threads[i].Name.."> "..ret) - end - if ret==true or ret==false then - print("Thread Ended!!!") - ret={} - end - end - if ret then - if ret[1]=="_kill_" then - table.remove(self.Threads,i) - elseif ret[1]=="_sleep_" then - self.Threads[i].timer:Reset() - self.Threads[i].sleep=ret[2] - elseif ret[1]=="_skip_" then - self.Threads[i].timer:Reset() - self.Threads[i].sleep=math.huge - local event=multi:newEvent(function(evnt) return multi.scheduler.counter>=evnt.counter end) - event.link=self.Threads[i] - event.counter=self.counter+ret[2] - event:OnEvent(function(evnt) - evnt.link.sleep=0 - end) - elseif ret[1]=="_hold_" then - self.Threads[i].timer:Reset() - self.Threads[i].sleep=math.huge - local event=multi:newEvent(ret[2]) - event.link=self.Threads[i] - event:OnEvent(function(evnt) - evnt.link.sleep=0 - end) - elseif ret.Name then - self.Globals[ret.Name]=ret.Value - end - end - end - end -end) -multi.scheduler:Pause() -multi.OnError=multi:newConnection() -function multi:newThreadedAlarm(name,set) - local c=self:newTBase() - c.Type='alarmThread' - c.timer=self:newTimer() - c.set=set or 0 - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.set) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - self.timer:Resume() - end - function c:Reset(n) - if n then self.set=n end - self.rest=false - self.timer:Reset(n) - end - function c:OnRing(func) - table.insert(self.func,func) - end - function c:Pause() - self.timer:Pause() - self.rest=true - end - c.rest=false - c.updaterate=multi.Priority_Low -- skips - c.restRate=0 -- secs - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) -- rest a bit more when a thread is paused - else - if c.timer:Get()>=c.set then - c:Pause() - for i=1,#c.func do - c.func[i](c) - end - end - thread.skip(c.updaterate) -- lets rest a bit - end - end - end) - self:create(c) - return c -end -function multi:newThreadedUpdater(name,skip) - local c=self:newTBase() - c.Type='updaterThread' - c.pos=1 - c.skip=skip or 1 - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - c.OnUpdate=self.OnMainConnect - c.rest=false - c.updaterate=0 - c.restRate=.75 - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) -- rest a bit more when a thread is paused - else - for i=1,#c.func do - c.func[i](c) - end - c.pos=c.pos+1 - thread.skip(c.skip) - end - end - end) - self:create(c) - return c -end -function multi:newThreadedTStep(name,start,reset,count,set) - local c=self:newTBase() - local think=1 - c.Type='tstepThread' - c.Priority=self.Priority_Low - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=os.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=self.start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=os.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - c.updaterate=0--multi.Priority_Low -- skips - c.restRate=0 - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) -- rest a bit more when a thread is paused - else - if os.clock()-c.timer>=c.set then - c:Reset() - if c.pos==c.start then - for fe=1,#c.funcS do - c.funcS[fe](c) - end - end - for i=1,#c.func do - c.func[i](c.pos,c) - end - c.pos=c.pos+c.count - if c.pos-c.count==c.endAt then - c:Pause() - for fe=1,#c.funcE do - c.funcE[fe](c) - end - c.pos=c.start - end - end - thread.skip(c.updaterate) -- lets rest a bit - end - end - end) - self:create(c) - return c -end -function multi:newThreadedTLoop(name,func,n) - local c=self:newTBase() - c.Type='tloopThread' - c.restN=n or 1 - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - function c:OnLoop(func) - table.insert(self.func,func) - end - c.rest=false - c.updaterate=0 - c.restRate=.75 - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) -- rest a bit more when a thread is paused - else - for i=1,#c.func do - c.func[i](c) - end - thread.sleep(c.restN) -- lets rest a bit - end - end - end) - self:create(c) - return c -end -function multi:newThreadedStep(name,start,reset,count,skip) - local c=self:newTBase() - local think=1 - c.Type='stepThread' - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.rest=true - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - c.updaterate=0 - c.restRate=.1 - multi:newThread(name,function(ref) - while true do - if c.rest then - ref:sleep(c.restRate) -- rest a bit more when a thread is paused - else - if c~=nil then - if c.spos==0 then - if c.pos==c.start then - for fe=1,#c.funcS do - c.funcS[fe](c) - end - end - for i=1,#c.func do - c.func[i](c.pos,c) - end - c.pos=c.pos+c.count - if c.pos-c.count==c.endAt then - c:Pause() - for fe=1,#c.funcE do - c.funcE[fe](c) - end - c.pos=c.start - end - end - end - c.spos=c.spos+1 - if c.spos>=c.skip then - c.spos=0 - end - ref:sleep(c.updaterate) -- lets rest a bit - end - end - end) - self:create(c) - return c -end -function multi:newThreadedProcess(name) - local c = {} - setmetatable(c, multi) - function c:newBase(ins) - local ct = {} - setmetatable(ct, self.Parent) - ct.Active=true - ct.func={} - ct.ender={} - ct.Id=0 - ct.PId=0 - ct.Act=function() end - ct.Parent=self - ct.held=false - ct.ref=self.ref - table.insert(self.Mainloop,ct) - return ct - end - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type='process' - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.Active=true - c.Id=-1 - c.Rest=0 - c.updaterate=.01 - c.restRate=.1 - c.Jobs={} - c.queue={} - c.jobUS=2 - c.rest=false - function c:getController() - return nil - end - function c:Start() - self.rest=false - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - function c:Remove() - self.ref:kill() - end - function c:kill() - err=coroutine.yield({"_kill_"}) - if err then - error("Failed to kill a thread! Exiting...") - end - end - function c:sleep(n) - if type(n)=="function" then - ret=coroutine.yield({"_hold_",n}) - elseif type(n)=="number" then - n = tonumber(n) or 0 - ret=coroutine.yield({"_sleep_",n}) - else - error("Invalid Type for sleep!") - end - end - c.hold=c.sleep - multi:newThread(name,function(ref) - while true do - if c.rest then - ref:Sleep(c.restRate) -- rest a bit more when a thread is paused - else - c:uManager() - ref:sleep(c.updaterate) -- lets rest a bit - end - end - end) - return c -end -function multi:newThreadedLoop(name,func) - local c=self:newTBase() - c.Type='loopThread' - c.Start=os.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - function c:OnLoop(func) - table.insert(self.func,func) - end - c.rest=false - c.updaterate=0 - c.restRate=.75 - multi:newThread(name,function(ref) - while true do - if c.rest then - thread.sleep(c.restRate) -- rest a bit more when a thread is paused - else - for i=1,#c.func do - c.func[i](os.clock()-self.Start,c) - end - thread.sleep(c.updaterate) -- lets rest a bit - end - end - end) - self:create(c) - return c -end -function multi:newThreadedEvent(name,task) - local c=self:newTBase() - c.Type='eventThread' - c.Task=task or function() end - function c:OnEvent(func) - table.insert(self.func,func) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.Task) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Resume() - self.rest=false - end - function c:Pause() - self.rest=true - end - c.rest=false - c.updaterate=0 - c.restRate=1 - multi:newThread(name,function(ref) - while true do - if c.rest then - ref:sleep(c.restRate) -- rest a bit more when a thread is paused - else - if c.Task(self) then - for _E=1,#c.func do - c.func[_E](c) - end - c:Pause() - end - ref:sleep(c.updaterate) -- lets rest a bit - end - end - end) - self:create(c) - return c -end diff --git a/mulit/multi/integration/lanesManager.lua b/mulit/multi/integration/lanesManager.lua deleted file mode 100644 index a490ce8..0000000 --- a/mulit/multi/integration/lanesManager.lua +++ /dev/null @@ -1,133 +0,0 @@ ---[[ -MIT License - -Copyright (c) 2017 Ryan Ward - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] -function os.getOS() - if package.config:sub(1,1)=='\\' then - return 'windows' - else - return 'unix' - end -end --- Step 1 get lanes -lanes=require("lanes").configure() ---~ package.path="lua/?/init.lua;lua/?.lua;"..package.path -require("multi") -- get it all and have it on all lanes -function multi:canSystemThread() - return true -end -local multi=multi --- Step 2 set up the linda objects -local __GlobalLinda = lanes.linda() -- handles global stuff -local __SleepingLinda = lanes.linda() -- handles sleeping stuff --- For convience a GLOBAL table will be constructed to handle requests -local GLOBAL={} -setmetatable(GLOBAL,{ - __index=function(t,k) - return __GlobalLinda:get(k) - end, - __newindex=function(t,k,v) - __GlobalLinda:set(k,v) - end, -}) --- Step 3 rewrite the thread methods to use lindas -local THREAD={} -function THREAD.set(name,val) - __GlobalLinda:set(name,val) -end -function THREAD.get(name) - __GlobalLinda:get(name) -end -local function randomString(n) - local str = '' - local strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'} - for i=1,n do - str = str..''..strings[math.random(1,#strings)] - end - return str -end -function THREAD.waitFor(name) - local function wait() - math.randomseed(os.time()) - __SleepingLinda:receive(.001,randomString(12)) - end - repeat wait() until __GlobalLinda:get(name) - return __GlobalLinda:get(name) -end -function THREAD.testFor(name,val,sym) - -- -end -function THREAD.getCores() - return THREAD.__CORES -end -if os.getOS()=="windows" then - THREAD.__CORES=tonumber(os.getenv("NUMBER_OF_PROCESSORS")) -else - THREAD.__CORES=tonumber(io.popen("nproc --all"):read("*n")) -end -function THREAD.kill() -- trigger the lane destruction - -- coroutine.yield({"_kill_",":)"}) -end ---[[ Step 4 We need to get sleeping working to handle timing... We want idle wait, not busy wait -Idle wait keeps the CPU running better where busy wait wastes CPU cycles... Lanes does not have a sleep method -however, a linda recieve will in fact be a idle wait! So we use that and wrap it in a nice package]] -function THREAD.sleep(n) - math.randomseed(os.time()) - __SleepingLinda:receive(n,randomString(12)) -end -function THREAD.hold(n) - local function wait() - math.randomseed(os.time()) - __SleepingLinda:receive(.001,randomString(12)) - end - repeat wait() until n() -end --- Step 5 Basic Threads! -function multi:newSystemThread(name,func) - local c={} - local __self=c - c.name=name - c.Type="sthread" - c.thread=lanes.gen("*", func)() - function c:kill() - --self.status:Destroy() - self.thread:cancel() - print("Thread: '"..self.name.."' has been stopped!") - end - c.status=multi:newUpdater(multi.Priority_IDLE) - c.status.link=c - c.status:OnUpdate(function(self) - local v,err,t=self.link.thread:join(.001) - if err then - multi.OnError:Fire(self.link,err) - print("Error in systemThread: '"..self.link.name.."' <"..err..">") - self:Destroy() - end - end) - return c -end -print("Integrated Lanes!") -multi.integration={} -- for module creators -multi.integration.GLOBAL=GLOBAL -multi.integration.THREAD=THREAD -require("multi.integration.shared") -return {init=function() return GLOBAL,THREAD end} diff --git a/mulit/multi/integration/loveManager.lua b/mulit/multi/integration/loveManager.lua deleted file mode 100644 index 56260c7..0000000 --- a/mulit/multi/integration/loveManager.lua +++ /dev/null @@ -1,359 +0,0 @@ -require("multi.compat.love2d") -function multi:canSystemThread() - return true -end -multi.integration={} -multi.integration.love2d={} -multi.integration.love2d.ThreadBase=[[ -tab={...} -__THREADNAME__=tab[2] -__THREADID__=tab[1] -require("love.filesystem") -require("love.system") -require("love.timer") -require("multi") -GLOBAL={} -setmetatable(GLOBAL,{ - __index=function(t,k) - __sync__() - return __proxy__[k] - end, - __newindex=function(t,k,v) - __sync__() - __proxy__[k]=v - if type(v)=="userdata" then - __MainChan__:push(v) - else - __MainChan__:push("SYNC "..type(v).." "..k.." "..resolveData(v)) - end - end, -}) -function __sync__() - local data=__mythread__:pop() - while data do - love.timer.sleep(.001) - if type(data)=="string" then - local cmd,tp,name,d=data:match("(%S-) (%S-) (%S-) (.+)") - if name=="__DIEPLZ"..__THREADID__.."__" then - error("Thread: "..__THREADID__.." has been stopped!") - end - if cmd=="SYNC" then - __proxy__[name]=resolveType(tp,d) - end - else - __proxy__[name]=data - end - data=__mythread__:pop() - end -end -function ToStr(val, name, skipnewlines, depth) - skipnewlines = skipnewlines or false - depth = depth or 0 - local tmp = string.rep(" ", depth) - if name then - if type(name) == "string" then - tmp = tmp .. "[\""..name.."\"] = " - else - tmp = tmp .. "["..(name or "").."] = " - end - end - if type(val) == "table" then - tmp = tmp .. "{" .. (not skipnewlines and " " or "") - for k, v in pairs(val) do - tmp = tmp .. ToStr(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and " " or "") - end - tmp = tmp .. string.rep(" ", depth) .. "}" - elseif type(val) == "number" then - tmp = tmp .. tostring(val) - elseif type(val) == "string" then - tmp = tmp .. string.format("%q", val) - elseif type(val) == "boolean" then - tmp = tmp .. (val and "true" or "false") - elseif type(val) == "function" then - tmp = tmp .. "loadDump([===["..dump(val).."]===])" - else - tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\"" - end - return tmp -end -function resolveType(tp,d) - if tp=="number" then - return tonumber(d) - elseif tp=="bool" then - return (d=="true") - elseif tp=="function" then - return loadDump("[==["..d.."]==]") - elseif tp=="table" then - return loadstring("return "..d)() - elseif tp=="nil" then - return nil - else - return d - end -end -function resolveData(v) - local data="" - if type(v)=="table" then - return ToStr(v) - elseif type(v)=="function" then - return dump(v) - elseif type(v)=="string" or type(v)=="number" or type(v)=="bool" or type(v)=="nil" then - return tostring(v) - end - return data -end -sThread={} -local function randomString(n) - local c=os.clock() - local a=0 - while os.clock()" - c.thread=love.thread.newThread(multi.integration.love2d.ThreadBase:gsub("INSERT_USER_CODE",dump(func))) - c.thread:start(c.ID,c.name) - function c:kill() - multi.integration.GLOBAL["__DIEPLZ"..self.ID.."__"]="__DIEPLZ"..self.ID.."__" - end - return c -end -function love.threaderror( thread, errorstr ) - multi.OnError:Fire(thread,errorstr) - print("Error in systemThread: "..tostring(thread)..": "..errorstr) -end -local THREAD={} -function THREAD.set(name,val) - GLOBAL[name]=val -end -function THREAD.get(name) - return GLOBAL[name] -end -function THREAD.waitFor(name) - multi.OBJ_REF:Pause() - repeat multi:lManager() until GLOBAL[name] - multi.OBJ_REF:Resume() - return GLOBAL[name] -end -function THREAD.getCores() - return love.system.getProcessorCount() -end -function THREAD.sleep(n) - love.timer.sleep(n) -end -function THREAD.hold(n) - multi.OBJ_REF:Pause() - repeat multi:lManager() until n() - multi.OBJ_REF:Resume() -end -__channels__={} -multi.integration.GLOBAL=GLOBAL -multi.integration.THREAD=THREAD -updater=multi:newUpdater() -updater:OnUpdate(function(self) - local data=multi.integration.love2d.mainChannel:pop() - while data do - --print("MAIN:",data) - if type(data)=="string" then - local cmd,tp,name,d=data:match("(%S-) (%S-) (%S-) (.+)") - if cmd=="SYNC" then - __proxy__[name]=resolveType(tp,d) - for i=1,#__channels__ do - -- send data to other threads - if type(v)=="userdata" then - __channels__[i]:push(v) - else - __channels__[i]:push("SYNC "..tp.." "..name.." "..d) - end - end - elseif cmd=="NEWTHREAD" then - __channels__[#__channels__+1]=love.thread.getChannel(tp) - for k,v in pairs(__proxy__) do -- sync the global with each new thread - if type(v)=="userdata" then - __channels__[#__channels__]:push(v) - else - __channels__[#__channels__]:push("SYNC "..type(v).." "..k.." "..resolveData(v)) - end - end - end - else - __proxy__[name]=data - end - data=multi.integration.love2d.mainChannel:pop() - end -end) -require("multi.integration.shared") -print("Integrated Love2d!") -return { - init=function(t) - if t then - if t.threadNamespace then - multi.integration.THREADNAME=t.threadNamespace - multi.integration.love2d.ThreadBase:gsub("sThread",t.threadNamespace) - end - if t.globalNamespace then - multi.integration.GLOBALNAME=t.globalNamespace - multi.integration.love2d.ThreadBase:gsub("GLOBAL",t.globalNamespace) - end - end - return GLOBAL,THREAD - end -} diff --git a/mulit/multi/integration/shared.lua b/mulit/multi/integration/shared.lua deleted file mode 100644 index 63ff000..0000000 --- a/mulit/multi/integration/shared.lua +++ /dev/null @@ -1,359 +0,0 @@ ---[[ -MIT License - -Copyright (c) 2017 Ryan Ward - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -]] -function multi.randomString(n) - local str = '' - local strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'} - for i=1,n do - str = str..''..strings[math.random(1,#strings)] - end - return str -end -function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a channel on both ends - local c={} -- where we will store our object - c.name=name -- set the name this is important for the love2d side - if love then -- check love - if love.thread then -- make sure we can use the threading module - function c:init() -- create an init function so we can mimic on bith love2d and lanes - self.chan=love.thread.getChannel(self.name) -- create channel by the name self.name - function self:push(v) -- push to the channel - self.chan:push({type(v),resolveData(v)}) - end - function self:pop() -- pop from the channel - local tab=self.chan:pop() - --print(tab) - if not tab then return end - return resolveType(tab[1],tab[2]) - end - function self:peek() - local tab=self.chan:peek() - --print(tab) - if not tab then return end - return resolveType(tab[1],tab[2]) - end - GLOBAL[self.name]=self -- send the object to the thread through the global interface - return self -- return the object - end - return c - else - error("Make sure you required the love.thread module!") -- tell the user if he/she didn't require said module - end - else - c.linda=lanes.linda() -- lanes is a bit eaiser, create the linda on the main thread - function c:push(v) -- push to the queue - self.linda:send("Q",v) - end - function c:pop() -- pop the queue - return ({self.linda:receive(0,"Q")})[2] - end - function c:peek() - return self.linda:get("Q") - end - function c:init() -- mimic the feature that love2d requires, so code can be consistent - return self - end - multi.integration.GLOBAL[name]=c -- send the object to the thread through the global interface - end - return c -end -function multi:systemThreadedBenchmark(n,p) - n=n or 1 - local cores=multi.integration.THREAD.getCores() - local queue=multi:newSystemThreadedQueue("QUEUE") - multi.integration.GLOBAL["__SYSTEMBENCHMARK__"]=n - local sThread=multi.integration.THREAD - local GLOBAL=multi.integration.GLOBAL - for i=1,cores do - multi:newSystemThread("STHREAD_BENCH",function() - require("multi") - if multi:getPlatform()=="love2d" then - GLOBAL=_G.GLOBAL - sThread=_G.sThread - end -- we cannot have upvalues... in love2d globals not locals must be used - queue=sThread.waitFor("QUEUE"):init() -- always wait for when looking for a variable at the start of the thread! - multi:benchMark(sThread.waitFor("__SYSTEMBENCHMARK__")):OnBench(function(self,count) - queue:push(count) - multi:Stop() - end) - multi:mainloop() - end) - end - local c={} - c.tt=function() end - c.p=p - function c:OnBench(func) - self.tt=func - end - multi:newThread("THREAD_BENCH",function() - thread.sleep(n+.1) - GLOBAL["QUEUE"]=nil -- time to clean up - local num=0 - data=queue:pop() - while data do - num=num+data - data=queue:pop() - end - if p then - print(tostring(p)..num) - end - c.tt(c,num) - end) - return c -end -function multi:newSystemThreadedTable(name,n) - local c={} -- where we will store our object - c.name=name -- set the name this is important for the love2d side - c.cores=n - c.hasT={} - if love then -- check love - if love.thread then -- make sure we can use the threading module - function c:init() -- create an init function so we can mimic on bith love2d and lanes - self.tab={} - self.chan=love.thread.getChannel(self.name) -- create channel by the name self.name - function self:waitFor(name) -- pop from the channel - repeat self:sync() until self[name] - return self[name] - end - function self:sync() - local data=self.chan:peek() - if data then - local cmd,tp,name,d=data:match("(%S-) (%S-) (%S-) (.+)") - if not self.hasT[name] then - if type(data)=="string" then - if cmd=="SYNC" then - self.tab[name]=resolveType(tp,d) -- this is defined in the loveManager.lua file - self.hasT[name]=true - end - else - self.tab[name]=data - end - self.chan:pop() - end - end - end - function self:reset(name) - self.hasT[core]=nil - end - setmetatable(self,{ - __index=function(t,k) - self:sync() - return self.tab[k] - end, - __newindex=function(t,k,v) - self:sync() - self.tab[k]=v - if type(v)=="userdata" then - self.chan:push(v) - else - for i=1,self.cores do - self.chan:push("SYNC "..type(v).." "..k.." "..resolveData(v)) -- this is defined in the loveManager.lua file - end - end - end, - }) - GLOBAL[self.name]=self -- send the object to the thread through the global interface - return self -- return the object - end - return c - else - error("Make sure you required the love.thread module!") -- tell the user if he/she didn't require said module - end - else - c.linda=lanes.linda() -- lanes is a bit eaiser, create the linda on the main thread - function c:waitFor(name) - while self[name]==nil do - -- Waiting - end - return self[name] - end - function c:sync() - return -- just so we match the love2d side - end - function c:init() -- set the metatable - setmetatable(self,{ - __index=function(t,k) - return self.linda:get(k) - end, - __newindex=function(t,k,v) - self.linda:set(k,v) - end, - }) - return self - end - multi.integration.GLOBAL[name]=c -- send the object to the thread through the global interface - end - return c -end -function multi:newSystemThreadedJobQueue(numOfCores) - local c={} - c.jobnum=1 - c.cores=numOfCores or multi.integration.THREAD.getCores() - c.queueIN=multi:newSystemThreadedQueue("THREADED_JQ"):init() - c.queueOUT=multi:newSystemThreadedQueue("THREADED_JQO"):init() - c.queueALL=multi:newSystemThreadedQueue("THREADED_QALL"):init() - c.REG=multi:newSystemThreadedQueue("THREADED_JQ_F_REG"):init() - -- registerJob(name,func) - -- pushJob(...) - function c:registerJob(name,func) - for i=1,self.cores do - self.REG:push({name,func}) - end - end - function c:pushJob(name,...) - self.queueOUT:push({self.jobnum,name,...}) - self.jobnum=self.jobnum+1 - end - local GLOBAL=multi.integration.GLOBAL -- set up locals incase we are using lanes - local sThread=multi.integration.THREAD -- set up locals incase we are using lanes - function c:doToAll(func) - local TaskName=multi.randomString(16) - for i=1,self.cores do - self.queueALL:push({TaskName,func}) - end - end - function c:start() - self:doToAll(function() - _G["__started__"]=true - SFunc() - end) - end - GLOBAL["__JQ_COUNT__"]=c.cores - for i=1,c.cores do - multi:newSystemThread("System Threaded Job Queue Worker Thread #"..i,function() - require("multi") - __sleep__=.001 - if love then -- lets make sure we don't reference upvalues if using love2d - GLOBAL=_G.GLOBAL - sThread=_G.sThread - __sleep__=.1 - end - JQI=sThread.waitFor("THREADED_JQO"):init() -- Grab it - JQO=sThread.waitFor("THREADED_JQ"):init() -- Grab it - REG=sThread.waitFor("THREADED_JQ_F_REG"):init() -- Grab it - QALL=sThread.waitFor("THREADED_QALL"):init() -- Grab it - sThread.sleep(.1) -- lets wait for things to work out - GLOBAL["THREADED_JQ"]=nil -- remove it - GLOBAL["THREADED_JQO"]=nil -- remove it - GLOBAL["THREADED_JQ_F_REG"]=nil -- remove it - QALLT={} - FUNCS={} - SFunc=multi:newFunction(function(self) - MainLoop:Pause() - self:hold(.1) - MainLoop:Resume() - self:Pause() - end) - multi:newLoop(function() - local rd=REG:peek() - if rd then - if not FUNCS[rd[1]] then - FUNCS[rd[1]]=rd[2] - rd=nil -- lets clean up - REG:pop() - end - end - local d=QALL:peek() - if d then - if not QALLT[d[1]] then - QALLT[d[1]]=true - d[2]() - d=nil -- lets clean up - QALL:pop() - end - end - end) - setmetatable(_G,{ - __index=function(t,k) - return FUNCS[k] - end - }) - MainLoop=multi:newLoop(function(self) - if __started__ then - local job=JQI:pop() - if job then - local d=QALL:peek() - if d then - if not QALLT[d[1]] then - QALLT[d[1]]=true - d[2]() - d=nil -- lets clean up - QALL:pop() - end - end - local ID=table.remove(job,1) -- return and remove - local name=table.remove(job,1) -- return and remove - if FUNCS[name] then - JQO:push({ID,FUNCS[name](unpack(job))}) - else - self:hold(function() return FUNCS[name] end) - JQO:push({ID,FUNCS[name](unpack(job))}) - end - end - end - end) - if not love then - multi:mainloop() - end - end) - end - c.OnJobCompleted=multi:newConnection() - c.updater=multi:newLoop(function(self) - local data=self.link.queueIN:pop() - while data do - if data then - self.link.OnJobCompleted:Fire(unpack(data)) - end - data=self.link.queueIN:pop() - end - end) - c.updater.link=c - return c -end -function multi:newSystemThreadedExecute(cmd) - local c={} - local GLOBAL=multi.integration.GLOBAL -- set up locals incase we are using lanes - local sThread=multi.integration.THREAD -- set up locals incase we are using lanes - local name="Execute_Thread"..multi.randomString(16) - c.name=name - GLOBAL[name.."CMD"]=cmd - multi:newSystemThread(name,function() - if love then -- lets make sure we don't reference upvalues if using love2d - GLOBAL=_G.GLOBAL - sThread=_G.sThread - name=__THREADNAME__ -- global data same as the name we used in this functions creation - end -- Lanes should take the local upvalues ^^^ - cmd=sThread.waitFor(name.."CMD") - local ret=os.execute(cmd) - GLOBAL[name.."R"]=ret - end) - c.OnCMDFinished=multi:newConnection() - c.looper=multi:newLoop(function(self) - local ret=GLOBAL[self.link.name.."R"] - if ret then - self.link.OnCMDFinished:Fire(ret) - self:Destroy() - end - end) - c.looper.link=c - return c -end diff --git a/mulit/oldversions/BasicCommands.lua b/mulit/oldversions/BasicCommands.lua deleted file mode 100644 index eec5d46..0000000 --- a/mulit/oldversions/BasicCommands.lua +++ /dev/null @@ -1,511 +0,0 @@ ---Needs:SystemType.bat -function RandomString(num) -string = "" -strings = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","1","2","3","4","5","6","7","8","9","0","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"} -for i=1,num do -h = math.random(1,#strings) -string = string..""..strings[h] -end -return string -end ----------------------------------------------------------------------------------------------------- -function GetSystemType() -return BatCmd([[ -for /f "skip=1 delims=" %%x in ('wmic cpu get addresswidth') do if not defined AddressWidth set AddressWidth=%%x - -if %AddressWidth%==64 ( - exit /b 64 -) else ( - exit /b 32 -) -]]) -end ----------------------------------------------------------------------------------------------------- -local clock = os.clock -function sleep(n) -- seconds -if not n then n=0 end -local t0 = clock() -while clock() - t0 <= n do end -end ----------------------------------------------------------------------------------------------------- -function SetCounter() -return os.clock() -end ----------------------------------------------------------------------------------------------------- -function GetCounter(count) -if count~=nil then -return os.clock()-count -else -return 0 -end -end ----------------------------------------------------------------------------------------------------- --- sleep and wait script for n seconds -function wait(n) -sleep(n) -end ----------------------------------------------------------------------------------------------------- --- pause into any key pressed -function pause(msg) -if msg ~= nil then -print(msg) -end -io.read() -end ----------------------------------------------------------------------------------------------------- --- gets input -function getInput(msg) -if msg ~= nil then -io.write(msg) -end -return io.read() -end ----------------------------------------------------------------------------------------------------- --- Print contents of `tbl`, with indentation. --- `indent` sets the initial level of indentation. -function print(...) -arg={...} -if arg[1]==nil then -return nil -end -for i,v in ipairs(arg) do -function tprint(tbl, indent) -if not indent then indent = 0 end -for k, v in pairs(tbl) do -formatting = string.rep(" ", indent) .. k .. ": " -if type(v) == "table" then -print(formatting) -tprint(v, indent+1) -else -print(formatting .. tostring(v)) -end -end -end -if type(v)=="string" then -io.write(v..[[ - -]]) -elseif type(v)=="table" then -function test(v) -return v:tostring() -end -if v.tostring ~=nil then -print(test(v)) -else -tprint(v) -end -elseif type(v)=="number" then -io.write(tostring(v..[[ - -]])) -elseif type(v)=="boolean" then -if v then -io.write("true"..[[ - -]]) -else -io.write("false"..[[ - -]]) -end -end -end -end -math.randomseed(clock()) ----------------------------------------------------------------------------------------------------- --- gets the length of a table or a string or the number of digits in a number including the decimal -function len(T) -if type(T)=="table" then -local count = 0 -for _ in pairs(T) do count = count + 1 end -return count -elseif type(T)=="string" then -return string.len(T) -elseif type(T)=="number" then -return string.len(tostring(T)) -end -end ----------------------------------------------------------------------------------------------------- -function dump(t,indent) - local names = {} - if not indent then indent = "" end - for n,g in pairs(t) do - table.insert(names,n) - end - table.sort(names) - for i,n in pairs(names) do - local v = t[n] - if type(v) == "table" then - if(v==t) then -- prevent endless loop if table contains reference to itself - print(indent..tostring(n)..": <-") - else - print(indent..tostring(n)..":") - dump(v,indent.." ") - end - else - if type(v) == "function" then - print(indent..tostring(n).."()") - else - print(indent..tostring(n)..": "..tostring(v)) - end - end - end -end ----------------------------------------------------------------------------------------------------- -function BuildFromTree(tbl, indent,folder) -if not indent then indent = 0 end -if not folder then folder = "" end -for k, v in pairs(tbl) do -formatting = string.rep(" ", indent) .. k .. ":" -if type(v) == "table" then ---print(formatting) -mkdir(folder..string.sub(formatting,1,-2)) -BuildFromTree(v,0,folder..string.sub(formatting,1,-2).."\\") -print(v,0,folder..string.sub(formatting,1,-2).."\\") -else -a=string.find(tostring(v),":",1,true) -file=string.sub(tostring(v),1,a-1) -data=string.sub(tostring(v),a+1) -mkfile(folder..file,data,"w") -print(folder..tostring(v)) -end -end -end ----------------------------------------------------------------------------------------------------- -function CopyFile(path,topath) -print("Copy "..path.." "..topath) -os.execute("Copy "..path.." "..topath) -end ----------------------------------------------------------------------------------------------------- -function DeleteFile(path) -os.remove(path) -end ----------------------------------------------------------------------------------------------------- -function mkdir(dirname) -os.execute("mkdir \"" .. dirname.."\"") -end ----------------------------------------------------------------------------------------------------- -function mkfile(filename,data,tp) -if not(tp) then tp="w" end -if not(data) then data="" end -file = io.open(filename, tp) -file:write(data) -file:close() -end ----------------------------------------------------------------------------------------------------- -function MoveFile(path,topath) -CopyFile(path,topath) -DeleteFile(path) -end ----------------------------------------------------------------------------------------------------- -function List_Files(dir) -if not(dir) then dir="" end -local f = io.popen("dir \""..dir.."\"") -if f then - return f:read("*a") -else - print("failed to read") -end -end ----------------------------------------------------------------------------------------------------- -function StringLineToTable(s) -local t = {} -- table to store the indices -local i = 0 -while true do -i = string.find(s, "\n", i+1) -- find 'next' newline -if i == nil then return t end -table.insert(t, i) -end -end ----------------------------------------------------------------------------------------------------- -function GetDirectory(dir,flop) -s=List_Files(dir) -drive=string.sub(string.match(s,"drive.."),-1) -local t = {} -- table to store the indices -local i = 0 -while true do -i = string.find(s, "\n", i+1) -- find 'next' newline -if i == nil then -a,b=string.find(s,drive..":\\",1,true) -main = string.gsub(string.sub(s,a,t[4]), "\n", "") -if flop then -main=main:gsub("%\\", "/") -end -return main -end -table.insert(t, i) -end -end ----------------------------------------------------------------------------------------------------- -function lines(str) - local t = {} - local function helper(line) table.insert(t, line) return "" end - helper((str:gsub("(.-)\r?\n", helper))) - return t -end ----------------------------------------------------------------------------------------------------- -function File_Exist(path) -g=io.open(path or '','r') -if path =="" then -p="empty path" -return nil -end -if g~=nil and true or false then -p=(g~=nil and true or false) -end ---p=(g~=nil and true or false..(path=='' and 'empty path entered!' or (path or 'arg "path" wasn\'t define to function call!'))) -if g~=nil then -io.close(g) -else -return false -end -return p -end ----------------------------------------------------------------------------------------------------- -function file_check(file_name) -if not file_name then print("No path inputed") return false end -local file_found=io.open(file_name, "r") -if file_found==nil then -file_found=false -else -file_found=true -end -return file_found -end ----------------------------------------------------------------------------------------------------- -function Dir_Exist(strFolderName) - local fileHandle, strError = io.open(strFolderName.."\\*.*","r") - if fileHandle ~= nil then - io.close(fileHandle) - return true - else - if string.match(strError,"No such file or directory") then - return false - else - return true - end - end -end ----------------------------------------------------------------------------------------------------- -function ListItems(dir) -if Dir_Exist(dir) then -temp=List_Files(dir) -- current directory if blank -if GetDirectory(dir)=="C:\\\n" then -a,b=string.find(temp,"C:\\",1,true) -a=a+2 -else -a,b=string.find(temp,"..",1,true) -end -temp=string.sub(temp,a+2) -list=StringLineToTable(temp) -temp=string.sub(temp,1,list[#list-2]) -slist=lines(temp) -table.remove(slist,1) -table.remove(slist,#slist) -temp={} -temp2={} -for i=1,#slist do -table.insert(temp,string.sub(slist[i],40,-1)) -end -return temp -else -print("Directory does not exist") -return nil -end -end ----------------------------------------------------------------------------------------------------- -function GetDirectories(dir) -temp2={} -dirs=ListItems(dir) -for i=1,#dirs do -if Dir_Exist(string.gsub(GetDirectory(dir).."\\"..dirs[i], "\n", "")) then -table.insert(temp2,dirs[i]) -end -end -return temp2 -end ----------------------------------------------------------------------------------------------------- -function GetFiles(dir) -temp2={} -dirs=ListItems(dir) -for i=1,#dirs do -if Dir_Exist(string.gsub(GetDirectory(dir).."\\"..dirs[i], "\n", "")) then -else -table.insert(temp2,dirs[i]) -end -end -return temp2 -end ----------------------------------------------------------------------------------------------------- -function GetName(name) -if name then temp=name else temp=arg[0] end -if string.find(temp,"\\",1,true) then -temp=string.reverse(temp) -a,b=string.find(temp,"\\",1,true) -return string.reverse(string.sub(temp,1,b-1)) -end -return arg[0] -end ----------------------------------------------------------------------------------------------------- -BuildFromTreeE = function(tbl, indent,folder) -if not indent then indent = 0 end -if not folder then folder = "" end -for k, v in pairs(tbl) do -formatting = string.rep(" ", indent) .. k .. ":" -if type(v) == "table" then ---print(formatting) -mkdir(folder..string.sub(formatting,1,-2)) -BuildFromTreeE(v,0,folder..string.sub(formatting,1,-2).."\\") -print(v,0,folder..string.sub(formatting,1,-2).."\\") -else -a=string.find(tostring(v),":",1,true) -file=string.sub(tostring(v),1,a-1) -data=string.sub(tostring(v),a+1) -mkfile(folder..file,SuperEncode(data),"w") -print(folder..tostring(v)) -end -end -end ------------------------------------------------------------------------------------------------------- -readFile = function(file) - local f = io.open(file, "rb") - local content = f:read("*all") - f:close() - return content -end ------------------------------------------------------------------------------------------------------- -readFileE = function(file) - local f = io.open(file, "rb") - local content = f:read("*all") - f:close() - return SuperDecode(content) -end ------------------------------------------------------------------------------------------------------- -mkfileE = function(filename,data,tp) -if not(tp) then tp="w" end -if not(data) then data="" end -file = io.open(filename, tp) -file:write(SuperEncode(data)) -file:close() -end ------------------------------------------------------------------------------------------------------- -math.randomseed(clock()) ------------------------------------------------------------------------------------------------------- -function extension(file) -file=GetName(GetDirectory(file).."/"..file) -a,b=string.find(file,".",0,true) -return string.sub(file,b) -end -function InstallLua() -os.execute("Data\\LuaForWindows.exe") -end ------------------------------------------------------------------------------------------------------- -function autoCmd(cmd,a,b) -if b==nil then b=true end -if File_Exist("tempfile.ahk") and not(File_Exist("tempfile2.ahk")) then fname="tempfile2.ahk" elseif File_Exist("tempfile2.ahk") and not(File_Exist("tempfile.ahk")) then fname="tempfile.ahk" else fname=RandomString(10)..".ahk" end -mkfile(fname,[[ -#SingleInstance off -ReturnLua(val) -{ - FileAppend,%val%", %A_WorkingDir%\File.dat - Exitapp, 0 -} - -]]..cmd) -g=os.execute([[Data\Win32a\AutoHotkey.exe ]]..fname) -if b==true then -if not string.find(cmd,"ReturnLua(",1,true) then print("To Return use ReturnLua(value) (Note: values are returned as strings for booleans use '/bT' or '/bF' true/false, also \"\" are needed for string no other way works for now use \\\" to get quotes also for absolute render(does loadstring to the data don't assign a val name in the script do it to this function) call this function autoCmd(cmd,true) )") return false end ---repeat wait() until File_Exist("File.dat") or g==nil -if not(File_Exist("File.dat")) then -print("An Error has occurred") -return false -end -file = io.open("File.dat", "r") -size = file:read() -- capture file in a string -file:close() -Clean() -if size==nil then -return nil -end -if a then -loadstring("temp="..string.sub(size,1,-2))() -return temp -end -if string.sub(size,1,-2)=="/bT" then -return true -elseif string.sub(size,1,-2)=="/bF" then -return false -end -return string.sub(size,1,-2) -else -return g -end -end ------------------------------------------------------------------------------------------------------- -function BatCmd(cmd) -mkfile("temp.bat",cmd) -return os.execute([[temp.bat]]) -end ------------------------------------------------------------------------------------------------------- -inifile = {} - -local lines -local write - -if love then - lines = love.filesystem.lines - write = love.filesystem.write -else - lines = function(name) return assert(io.open(name)):lines() end - write = function(name, contents) return assert(io.open(name, "w")):write(contents) end -end - -function inifile.parse(name) - local t = {} - local section - for line in lines(name) do - local s = line:match("^%[([^%]]+)%]$") - if s then - section = s - t[section] = t[section] or {} - end - local key, value = line:match("^(%w+)%s-=%s-(.+)$") - if key and value then - if tonumber(value) then value = tonumber(value) end - if value == "true" then value = true end - if value == "false" then value = false end - t[section][key] = value - end - end - return t -end - -function inifile.save(name, t) - local contents = "" - for section, s in pairs(t) do - contents = contents .. ("[%s]\n"):format(section) - for key, value in pairs(s) do - contents = contents .. ("%s=%s\n"):format(key, tostring(value)) - end - contents = contents .. "\n" - end - write(name, contents) -end ---------------- -function DB(txt) -print(txt) -end ------------------------------------------------------------------------------------------------------- -function CreateShortcut(Target, Name , Work, Args, Desc, Icon, Short, IconN, Run) -if not(Target) or not(Name) then print("Error Target folder or file is needed and the name of the shortcut is needed") return false end -if string.sub(Name,-4)~=".lnk" then Name=Name..".lnk" end -if not(Work) then Work="," end -if not(Args) then Args="," end -if not(Desc) then Desc="," end -if not(Icon) then Icon="," end -if not(Short) then Short="," end -if not(IconN) then IconN="," end -if not(Run) then Run="" end -autoCmd([[FileCreateShortcut, ]]..Target..[[, ]]..Name..[[ ]]..Work..[[ ]]..Args..[[ ]]..Desc..[[ ]]..Icon..[[ ]]..Short..[[ ]]..IconN..[[ ]]..Run) -print("--shortcut created at "..Target.." with the name "..Name) -end diff --git a/mulit/oldversions/EventManager(0.0.1).lua b/mulit/oldversions/EventManager(0.0.1).lua deleted file mode 100644 index f815d54..0000000 --- a/mulit/oldversions/EventManager(0.0.1).lua +++ /dev/null @@ -1,53 +0,0 @@ -IsEvent=true -event={ -Active=true, -CT=false, -tag={}, -Events={}, -EventTracker={}, -Steps={}, -setAlarm=function(self,tag,set) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:addTracker("_Alarm_"..tag,SetCounter()) end, -setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end event:new("Event_"..fname,condition,also) end, -removeAlarm=function(self,tag) event:destroy("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end, -updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end, -addTracker=function(self,varname,var) event.EventTracker[varname]=var end, -getTracker=function(self,var) return event.EventTracker[var] end, -removeTracker=function(self,var) event.EventTracker[var]=nil end, -trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end, -updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end, -alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end, -new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end, -eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end, -destroy=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end, -Stop=function() event.Active=false end, -OnCreate=function() end, -OnUpdate=function() end, -OnClose=function() end, -getActive=function() return event.tag end, -Manager=function() event.OnCreate() while event.Active==true do for d=1,#event.Events do if event.Active==true then loadstring(event.Events[d])() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end event.OnClose() end, -CManager=function() for d=1,#event.Events do if event.Active==true then loadstring(event.Events[d])() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, -UManager=function() if event.CT==false then event.CT=true event.OnCreate() end for d=1,#event.Events do if event.Active==true then loadstring(event.Events[d])() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, -createStep=function(self,tag,reset,endc) -if not(endc) then endc=false end -if not(reset) then reset=0 end -temp={Name=tag,pos=1,endAt=reset,active=true,endc=endc, -Step=function(self) if self~=nil then _G.__CStep__=self if self.active==true then loadstring("Step_"..tag.."("..self.pos..",__CStep__)")() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then loadstring("Step_"..self.Name.."_End(__CStep__)")() end end end, -Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, -Reset=function(self) self.pos=1 end, -Set=function(self,amt) self.pos=amt end, -Pause=function(self) self.active=false end, -Resume=function(self) self.active=true end, -Stop=function(self) self:Reset() self:Pause() end, -Start=function(self) self:Resume() end, -End=function(self) self.pos=self.EndAt self.endc=true end, -} -table.insert(event.Steps,temp) return temp end, -stepExist=function(self,tag) -for a_s=1,#event.Steps do -if event.Steps[a_s].Name==tag then -return true -end -end -return false -end, -} diff --git a/mulit/oldversions/EventManager(0.9.0).lua b/mulit/oldversions/EventManager(0.9.0).lua deleted file mode 100644 index 3b31066..0000000 --- a/mulit/oldversions/EventManager(0.9.0).lua +++ /dev/null @@ -1,55 +0,0 @@ -IsEvent=true -event={ -Active=true, -CT=false, -tag={}, -Events={}, -EventTracker={}, -Steps={}, ---addAlarm=function(self,tag) end, -setAlarm=function(self,tag,set) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:addTracker("_Alarm_"..tag,SetCounter()) assert(loadstring("if Alarm_"..tag.."==nil then function Alarm_"..tag.."() print('No function \"Alarm_"..tag.."()\" exists make sure you created it') end end"))() end, -setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end a=string.find(fname,"(",1,true) tempstr=string.sub(fname,1,a-1) event:new("Event_"..fname,condition,also) assert(loadstring("if Event_"..tempstr.."==nil then function Event_"..tempstr.."() print('No function \"Event_"..tempstr.."()\" exists make sure you created it') end end"))() end, -removeAlarm=function(self,tag) event:destroy("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end, -updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end, -addTracker=function(self,varname,var) event.EventTracker[varname]=var end, -getTracker=function(self,var) return event.EventTracker[var] end, -removeTracker=function(self,var) event.EventTracker[var]=nil end, -trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end, -updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end, -alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end, -new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end, -eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end, -destroy=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end, -Stop=function() event.Active=false end, -OnCreate=function() end, -OnUpdate=function() end, -OnClose=function() end, -getActive=function() return event.tag end, -Manager=function() event.OnCreate() while event.Active==true do for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end event.OnClose() end, -CManager=function() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, -UManager=function() if event.CT==false then event.CT=true event.OnCreate() end for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, -RManager=function() event.OnCreate() while event.Active==true do event.OnUpdate() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end end event.OnClose() end, -createStep=function(self,tag,reset,endc) -if not(endc) then endc=false end -if not(reset) then reset=0 end -temp={Name=tag,pos=1,endAt=reset,active=true,endc=endc, -Step=function(self) if self~=nil then _G.__CStep__=self if self.active==true then assert(loadstring("Step_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CStep__)"))() end end end, -Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, -Reset=function(self) self.pos=1 end, -Set=function(self,amt) self.pos=amt end, -Pause=function(self) self.active=false end, -Resume=function(self) self.active=true end, -Stop=function(self) self:Reset() self:Pause() end, -Start=function(self) self:Resume() end, -End=function(self) self.pos=self.EndAt self.endc=true end, -} -table.insert(event.Steps,temp) return temp end, -stepExist=function(self,tag) -for a_s=1,#event.Steps do -if event.Steps[a_s].Name==tag then -return true -end -end -return false -end, -} diff --git a/mulit/oldversions/EventManager(1.0.0).lua b/mulit/oldversions/EventManager(1.0.0).lua deleted file mode 100644 index 3b31066..0000000 --- a/mulit/oldversions/EventManager(1.0.0).lua +++ /dev/null @@ -1,55 +0,0 @@ -IsEvent=true -event={ -Active=true, -CT=false, -tag={}, -Events={}, -EventTracker={}, -Steps={}, ---addAlarm=function(self,tag) end, -setAlarm=function(self,tag,set) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:addTracker("_Alarm_"..tag,SetCounter()) assert(loadstring("if Alarm_"..tag.."==nil then function Alarm_"..tag.."() print('No function \"Alarm_"..tag.."()\" exists make sure you created it') end end"))() end, -setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end a=string.find(fname,"(",1,true) tempstr=string.sub(fname,1,a-1) event:new("Event_"..fname,condition,also) assert(loadstring("if Event_"..tempstr.."==nil then function Event_"..tempstr.."() print('No function \"Event_"..tempstr.."()\" exists make sure you created it') end end"))() end, -removeAlarm=function(self,tag) event:destroy("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end, -updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end, -addTracker=function(self,varname,var) event.EventTracker[varname]=var end, -getTracker=function(self,var) return event.EventTracker[var] end, -removeTracker=function(self,var) event.EventTracker[var]=nil end, -trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end, -updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end, -alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end, -new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end, -eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end, -destroy=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end, -Stop=function() event.Active=false end, -OnCreate=function() end, -OnUpdate=function() end, -OnClose=function() end, -getActive=function() return event.tag end, -Manager=function() event.OnCreate() while event.Active==true do for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end event.OnClose() end, -CManager=function() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, -UManager=function() if event.CT==false then event.CT=true event.OnCreate() end for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, -RManager=function() event.OnCreate() while event.Active==true do event.OnUpdate() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end end event.OnClose() end, -createStep=function(self,tag,reset,endc) -if not(endc) then endc=false end -if not(reset) then reset=0 end -temp={Name=tag,pos=1,endAt=reset,active=true,endc=endc, -Step=function(self) if self~=nil then _G.__CStep__=self if self.active==true then assert(loadstring("Step_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CStep__)"))() end end end, -Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, -Reset=function(self) self.pos=1 end, -Set=function(self,amt) self.pos=amt end, -Pause=function(self) self.active=false end, -Resume=function(self) self.active=true end, -Stop=function(self) self:Reset() self:Pause() end, -Start=function(self) self:Resume() end, -End=function(self) self.pos=self.EndAt self.endc=true end, -} -table.insert(event.Steps,temp) return temp end, -stepExist=function(self,tag) -for a_s=1,#event.Steps do -if event.Steps[a_s].Name==tag then -return true -end -end -return false -end, -} diff --git a/mulit/oldversions/EventManager(1.1.0).lua b/mulit/oldversions/EventManager(1.1.0).lua deleted file mode 100644 index 9ad29ad..0000000 --- a/mulit/oldversions/EventManager(1.1.0).lua +++ /dev/null @@ -1,98 +0,0 @@ -require("Data/BasicCommands") -IsEvent=true -event={ - Active=true, - CT=false, - tag={}, - Events={}, - EventTracker={}, - Steps={}, - TSteps={}, - LoadOrder="/E/S/U",-- types = ESU,EUS,USE,UES,SEU,SUE - setLoadOrder=function(self,str) event.LoadOrder=string.upper(str) end, - DO_Order=function() LoadOrder=event.LoadOrder LoadOrder=LoadOrder:gsub("/E", "event.RUN_EVENTS(); ") LoadOrder=LoadOrder:gsub("/S", "event.RUN_STEPS(); ") LoadOrder=LoadOrder:gsub("/U", "event.RUN_UPDATES(); ") assert(loadstring(LoadOrder))() end, - RUN_EVENTS=function() for d=1,#event.Events do assert(loadstring(event.Events[d]))() end end, - RUN_STEPS=function() for s_g=1,#event.Steps do event.Steps[s_g]:Step() end end, - RUN_UPDATES=function() event.OnUpdate() end, - setAlarm=function(self,tag,set) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:addTracker("_Alarm_"..tag,SetCounter()) assert(loadstring("if Alarm_"..tag.."==nil then function Alarm_"..tag.."() print('No function \"Alarm_"..tag.."()\" exists make sure you created it') end end"))() end, - setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end a=string.find(fname,"(",1,true) tempstr=string.sub(fname,1,a-1) event:new("Event_"..fname,condition,also) assert(loadstring("if Event_"..tempstr.."==nil then function Event_"..tempstr.."() print('No function \"Event_"..tempstr.."()\" exists make sure you created it') end end"))() end, - removeAlarm=function(self,tag) event:destroy("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end, - updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end, - addTracker=function(self,varname,var) event.EventTracker[varname]=var end, - getTracker=function(self,varname) return event.EventTracker[varname] end, - removeTracker=function(self,var) event.EventTracker[var]=nil end, - trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end, - updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end, - alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end, - new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end, - eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end, - destroy=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end, - Stop=function() event.Active=false end, - OnCreate=function() end, - OnUpdate=function() end, - OnClose=function() end, - getActive=function() return event.tag end, - Manager=function() event.OnCreate() while event.Active==true do event.DO_Order() end event.OnClose() end, - --Manager=function() event.OnCreate() while event.Active==true do for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end event.OnClose() end, - CManager=function() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, - UManager=function() if event.CT==false then event.CT=true event.OnCreate() end for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, - createStep=function(self,tag,reset,skip,endc) - if not(endc) then endc=false end - temp= - { - Name=tag, - pos=1, - endAt=reset or math.huge, - active=true, - endc=endc, - skip=skip or 0, - spos=0, - Step=function(self) if self~=nil then if self.spos==0 then _G.__CStep__=self if self.active==true then assert(loadstring("Step_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CStep__)"))() end end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, - FStep=function(self) if self~=nil then if self.spos==0 then _G.__CStep__=self assert(loadstring("Step_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CStep__)"))() end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, - Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, - Reset=function(self) self.pos=1 end, - Set=function(self,amt) self.pos=amt end, - Pause=function(self) self.active=false end, - Resume=function(self) self.active=true end, - Stop=function(self) self:Reset() self:Pause() end, - Start=function(self) self:Resume() end, - End=function(self) self.pos=self.EndAt self.endc=true end, - } - table.insert(event.Steps,temp) return temp end, - createTStep=function(self,tag,reset,timer,endc) - if not(endc) then endc=false end - timer=timer or 1 - temp= - { - Name=tag, - pos=1, - endAt=reset or math.huge, - active=true, - endc=endc, - skip= 0, - spos=0, - Step=function(self) if self~=nil then if self.spos==0 then _G.__CStep__=self if self.active==true then assert(loadstring("TStep_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("TStep_"..self.Name.."_End(__CStep__)"))() end end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, - FStep=function(self) if self~=nil then if self.spos==0 then _G.__CStep__=self assert(loadstring("TStep_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("TStep_"..self.Name.."_End(__CStep__)"))() end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, - Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, - Reset=function(self) self.pos=1 end, - Set=function(self,amt) self.pos=amt end, - Pause=function(self) self.active=false end, - Resume=function(self) self.active=true end, - Stop=function(self) self:Reset() self:Pause() end, - Start=function(self) self:Resume() end, - End=function(self) self.pos=self.EndAt self.endc=true end, - } - event:setAlarm("TStep_"..tag,timer) - event:addTracker("_TStep_"..tag,temp) - table.insert(event.TSteps,temp) - assert(loadstring("function Alarm_TStep_"..tag.."(alarm) event:getTracker(\"_\"..alarm):Step() event:setAlarm(alarm,"..timer..") end"))() - return temp end, - stepExist=function(self,tag) - for a_s=1,#event.Steps do - if event.Steps[a_s].Name==tag then - return true - end - end - return false - end, -} diff --git a/mulit/oldversions/EventManager(1.2.0).lua b/mulit/oldversions/EventManager(1.2.0).lua deleted file mode 100644 index 25d8f49..0000000 --- a/mulit/oldversions/EventManager(1.2.0).lua +++ /dev/null @@ -1,203 +0,0 @@ -function dump(t,indent) - local names = {} - if not indent then indent = "" end - for n,g in pairs(t) do - table.insert(names,n) - end - table.sort(names) - for i,n in pairs(names) do - local v = t[n] - if type(v) == "table" then - if(v==t) then -- prevent endless loop if table contains reference to itself - print(indent..tostring(n)..": <-") - else - print(indent..tostring(n)..":") - dump(v,indent.." ") - end - else - if type(v) == "function" then - print(indent..tostring(n).."()") - else - print(indent..tostring(n)..": "..tostring(v)) - end - end - end -end -function SetCounter() - return os.clock() -end ----------------------------------------------------------------------------------------------------- -function GetCounter(count) - if count~=nil then - return os.clock()-count - else - return 0 - end -end ----------------------------------------------------------------------------------------------------- -clock=os.clock -event={ - Active=true, - CT=false, - tag={}, - Events={}, - Alarms={}, - EventTracker={}, - Steps={}, - TSteps={}, - CTask="", - LoadOrder="/E/S/A/U", - UpdateObj= - { - LoadOrder="", - Resume=function(self) event.LoadOrder=self.LoadOrder end, - Pause=function(self) self.LoadOrder=event.LoadOrder event.LoadOrder=event.LoadOrder:gsub("/U", "") end, - }, - setLoadOrder=function(self,str) event.LoadOrder=string.upper(str) end, - DO_Order=function() LoadOrder=event.LoadOrder LoadOrder=LoadOrder:gsub("/A", "event.RUN_ALARMS(); ") LoadOrder=LoadOrder:gsub("/E", "event.RUN_EVENTS(); ") LoadOrder=LoadOrder:gsub("/S", "event.RUN_STEPS(); ") LoadOrder=LoadOrder:gsub("/U", "event.RUN_UPDATES(); ") assert(loadstring(LoadOrder))() end, - RUN_EVENTS=function() event.CTask="events" for d=1,#event.Events do assert(loadstring(event.Events[d]))() end end, - RUN_STEPS=function() event.CTask="steps" for s_g=1,#event.Steps do event.Steps[s_g]:Step() end end, - RUN_UPDATES=function() _G.__CAction__=event.UpdateObj event.CTask="updates" event.OnUpdate() end, - RUN_ALARMS=function() for i=1,#event.Alarms do event.Alarms[i]:Tick() end end, - --System Used Functions - Hold=function(self,task) -- as many conditions and times that you want can be used - local action=__CAction__ - action:Pause() - if type(task)=="number" then - local func=function() end - local alarm=event:newAlarm(task,func,true) - while alarm.active==true do - event.CManager() - end - alarm:Destroy() - action:Resume() - elseif type(task)=="string" then - assert(loadstring("while not("..task..") do event.CManager() end"))() - action:Resume() - end - end, - newAlarm=function(self,set,func,start) - if not(start) then timer=0 active=false else timer=clock() active=true end - if not(func) then func=(function() end) end - Alarm= - { - active=active, - timer=timer, - set=set or 0, - func=func, - Tick=function(self) _G.__CAction__=self if self.active==true then if clock()-self.timer>=self.set then self:Pause() self:Ring() end end end, - Pause=function(self) self.active=false end, - Set=function(self,amt) self.set=amt self.timer=clock() self:Resume() end, - OnRing=function(self,func) self.func=func end, - Ring=function(self) self:func(self) end, - Reset=function(self) self.timer=clock() self:Resume() end, - Resume=function(self) self.active=true end, - Destroy=function(self) for i=1,#event.Alarms do if tostring(event.Alarms[i])==tostring(self) then table.remove(event.Alarms,i) end end end, - } - table.insert(event.Alarms,Alarm) - return Alarm - end, - setAlarm=function(self,tag,set) - if event:eventExist("Alarm_"..tag.."(\""..tag.."\")")==false then - event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) - event:addTracker("_Alarm_"..tag,SetCounter()) - assert(loadstring("if Alarm_"..tag.."==nil then function Alarm_"..tag.."() print('No function \"Alarm_"..tag.."()\" exists make sure you created it') end end"))() - else - event:addTracker("_Alarm_"..tag,SetCounter()) - end - end, - setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end a=string.find(fname,"(",1,true) tempstr=string.sub(fname,1,a-1) event:new("Event_"..fname,condition,also) assert(loadstring("if Event_"..tempstr.."==nil then function Event_"..tempstr.."() print('No function \"Event_"..tempstr.."()\" exists make sure you created it') end end"))() end, - removeAlarm=function(self,tag) event:destroyEvent("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end, - updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end, - addTracker=function(self,varname,var) event.EventTracker[varname]=var end, - getTracker=function(self,varname) return event.EventTracker[varname] end, - listTrackers=function(self) return event.EventTracker end, - removeTracker=function(self,var) event.EventTracker[var]=nil end, - trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end, - updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end, - alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end, - new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end, - eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end, - destroyEvent=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end, - Stop=function() event.Active=false end, - OnCreate=function() end, - OnUpdate=function() end, - OnClose=function() end, - getActive=function() return event.tag end, - Manager=function() event.OnCreate() while event.Active==true do event.DO_Order() end event.OnClose() end, - CManager=function() if event.Active==true then event.DO_Order() end end, - UManager=function() if event.CT==false then event.CT=true event.OnCreate() end if event.Active==true then event.DO_Order() end end, - createStep=function(self,tag,reset,skip,endc) - if not(endc) then - endc=false - end - temp= - { - Name=tag, - pos=1, - endAt=reset or math.huge, - active=true, - endc=endc, - skip=skip or 0, - spos=0, - Step=function(self) if self~=nil then if self.spos==0 then _G.__CAction__=self if self.active==true then assert(loadstring("Step_"..tag.."("..self.pos..",__CAction__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CAction__)"))() end end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, - FStep=function(self) if self~=nil then if self.spos==0 then _G.__CAction__=self assert(loadstring("Step_"..tag.."("..self.pos..",__CAction__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CAction__)"))() end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, - Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, - Reset=function(self) self.pos=1 end, - Set=function(self,amt) self.pos=amt end, - Pause=function(self) self.active=false end, - Resume=function(self) self.active=true end, - Stop=function(self) self:Reset() self:Pause() end, - Start=function(self) self:Resume() end, - End=function(self) _G.__CAction__=self assert(loadstring("Step_"..self.Name.."_End(__CAction__)"))() self:Reset() end, - } - table.insert(event.Steps,temp) return temp - end, - createTStep=function(self,tag,reset,timer,endc) - if not(endc) then - endc=false - end - timer=timer or 1 - temp= - { - Name=tag, - pos=1, - endAt=reset or math.huge, - active=true, - endc=endc, - skip= 0, - spos=0, - Step=function(self) if self~=nil then if self.spos==0 then _G.__CAction__=self if self.active==true then assert(loadstring("TStep_"..tag.."("..self.pos..",__CAction__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("TStep_"..self.Name.."_End(__CAction__)"))() end end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, - FStep=function(self) if self~=nil then if self.spos==0 then _G.__CAction__=self assert(loadstring("TStep_"..tag.."("..self.pos..",__CAction__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("TStep_"..self.Name.."_End(__CAction__)"))() end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, - Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, - Reset=function(self) self.pos=1 end, - Set=function(self,amt) self.pos=amt end, - Pause=function(self) self.active=false end, - Resume=function(self) self.active=true end, - Stop=function(self) self:Reset() self:Pause() end, - Start=function(self) self:Resume() end, - End=function(self) self.pos=self.EndAt self.endc=true end, - } - event:setAlarm("TStep_"..tag,timer) - event:addTracker("_TStep_"..tag,temp) - table.insert(event.TSteps,temp) - assert(loadstring("function Alarm_TStep_"..tag.."(alarm) event:getTracker(\"_\"..alarm):Step() event:updateAlarm(alarm,"..timer..") end"))() - return temp - end, - stepExist=function(self,tag) - for a_s=1,#event.Steps do - if event.Steps[a_s].Name==tag then - return true - end - end - return false - end, - tstepExist=function(self,tag) - for a_s=1,#event.TSteps do - if event.TSteps[a_s].Name==tag then - return true - end - end - return false - end, -} diff --git a/mulit/oldversions/EventManager(1.3.0).lua b/mulit/oldversions/EventManager(1.3.0).lua deleted file mode 100644 index a51a84f..0000000 --- a/mulit/oldversions/EventManager(1.3.0).lua +++ /dev/null @@ -1,728 +0,0 @@ -function readonlytable(table) - return setmetatable({}, { - __index = table, - __newindex = function(table, key, value) - error("Attempt to modify read-only table") - end, - __metatable = false - }); -end -local EventRef= -readonlytable{ - Pause=function(self) - self.active=false - if not(event.isPaused(self)) then - table.insert(event.Paused,self) - for _j=1,#event.Mainloop do - if tostring(event.Mainloop[_j])==tostring(self) then - table.remove(event.Mainloop,_j) - end - end - end - end, - Resume=function(self) - self.active=true - if event.isPaused(self) then - table.insert(event.Mainloop,self) - for _j=1,#event.Paused do - if tostring(event.Paused[_j])==tostring(self) then - table.remove(event.Paused,_j) - end - end - end - end, - Stop=function(self) - self.active=nil - end, -} - -local StepRef= -readonlytable{ - Step=function(self) - if self~=nil then - if self.spos==0 then - _G.__CAction__=self - if self.active==true then - for i=1,#self.steps do - self.steps[i](self.pos,self) - end - self.pos=self.pos+self.count - end - end - if self.endAt+self.count<=self.pos and self.endAt>self.start then - self:Reset() - for i=1,#self.funcs do - self.funcs[i](self) - end - elseif self.pos<=0 then - self:Reset() - for i=1,#self.funcs do - self.funcs[i](self) - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end, - FStep=function(self) - if self~=nil then - if self.spos==0 then - _G.__CAction__=self - for i=1,#self.steps do - self.steps[i](self.pos,self) - end - self.pos=self.pos+self.count - end - if self.endAt+self.count<=self.pos and self.endAt>self.start then - self:Reset() - for i=1,#self.funcs do - self.funcs[i](self) - end - elseif self.pos==0 then - self:Reset() - for i=1,#self.funcs do - self.funcs[i](self) - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end, - Remove=function(self) - if self~=_G.__CAction__ then - for as=1,#event.Mainloop do - if tostring(event.Mainloop[as])==tostring(self) then - table.remove(event.Mainloop,as) - end - end - else - table.insert(event.garbage,self) - end - end, - Reset=function(self) - self.pos=self.start - end, - Set=function(self,amt) - self.pos=amt - end, - Pause=EventRef.Pause, - Resume=EventRef.Resume, - Stop=function(self) - self:Reset() - self.active=nil - for i=1,#self.funcs do - self.funcs[i](self) - end - end, - End=function(self) - for i=1,#self.funcs do - self.funcs[i](self) - end - self:Reset() - end, - Update=function(self,start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end, - OnEnd=function(self,func) - table.insert(self.funcs,func) - end, - OnStep=function(self,func) - table.insert(self.steps,func) - end, - FreeConnections=function(self) - self.funcs={} - self.steps={} - end, -} ---thread and run setup -if love then - function love.run() - if love.math then - love.math.setRandomSeed(os.time()) - end - if love.event then - love.event.pump() - end - if love.load then love.load(arg) end - if love.timer then love.timer.step() end - local dt = 0 - while true do - -- Process events. - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - event.uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - event.dManager() - love.graphics.setColor(255,255,255,255) - if event.draw then event.draw() end - love.graphics.present() - end - end - end -end -eThreads={ - send=function() end, - - - - -} -function RunTasks() - for i=1,#event.DoTasks do - event.DoTasks[i]() - end -end -event={ - VERSION="1.0.0 (Build Version: 5.7.3)", - Priority_Core=1, - Priority_High=2, - Priority_Above_Normal=4, - Priority_Normal=16, - Priority_Low=256, - Priority_Idle=65536, - Start=0, - Active=true, - CT=false, - Tasks={}, - DoTasks={}, - garbage={}, - Paused={}, - last={}, - func={}, - drawF={}, - pump=false, - pumpvar=0, - Mainloop={}, - PEnabled=true, - PCount=1, - Triggers={}, - oneTimeObj= - { - last={}, - Resume=function(self) end, - Pause=function(self) end, - }, - RemoveAll=function() - event.Mainloop={} - end, - GarbageObj= - { - Resume=function() end, - Pause=function() end - }, - isPaused=function(obj) - for _j=1,#event.Paused do - if tostring(event.Paused[_j])==tostring(obj) then - return true - end - end - return false - end, - DO_Order=function() - event.oneTime(RunTasks) - event.PCount=event.PCount+1 - for i=1,#event.Mainloop do - if event.Mainloop[i]~=nil then - local obj = event.Mainloop[i] - if event.PCount%obj.Priority==0 and event.PEnabled then - obj:Act() - elseif event.PEnabled==false then - obj:Act() - end - if event.PCount>event.Priority_Idle then - event.PCount=event.Priority_Core - end - end - end - event.MANAGE_GARBAGE() - end, - MANAGE_GARBAGE=function() - _G.__CAction__=event.GarbageObj - for _i=1,#event.garbage do - event.garbage[_i]:Remove() - table.remove(event.garbage,_i) - end - end, - oneTime=function(func) - event.oneTimeObj.last=_G.__CAction__ - _G.__CAction__=event.oneTimeObj - for _k=1,#event.Tasks do - if event.Tasks[_k]==func then - _G.__CAction__=event.oneTimeObj.last - return false - end - end - table.insert(event.Tasks,func) - func() - _G.__CAction__=event.oneTimeObj.last - return true - end, - oneETime=function(func) - for _k=1,#event.Tasks do - if event.Tasks[_k]==string.dump(func) then - return false - end - end - table.insert(event.Tasks,string.dump(func)) - func() - return true - end, - hold=function(task) -- as many conditions and times that you want can be used - local action=__CAction__ - action:Pause() - if type(task)=="number" then - local alarm=event.newAlarm(task,function() end,true) - while alarm.active==true do - if love then - event.lManager() - else - event.cManager() - end - end - alarm:Remove() - action:Resume() - elseif type(task)=="function" then - local env=event.newEvent(task,function(envt) envt:Pause() envt:Stop() end) - while env.active do - if love then - event.lManager() - else - event.cManager() - end - end - env:Remove() - action:Resume() - else - print("Error Data Type!!!") - end - end, - waitFor=function(obj) - local obj=obj - event.hold(function() return not(obj.active) end) - end, - getType=function(obj) - if obj.Type~=nil then - return obj.Type - end - end, - newEvent=function(test,task) - temp= - { - Priority=event.Priority_Normal, - _Priority=0, - Parent=event.Events, - Type="Event", - active=true, - test=test or (function() end), - task={task} or {}, - Act=function(self) - _G.__CAction__=self - if self:test(self)==true then - self:Pause() - self:Stop() - for i=1,#self.task do - self.task[i](self) - end - end - end, - Reset=function(self) self:Resume() end, - Stop=EventRef.Stop, - Pause=EventRef.Pause, - Resume=EventRef.Resume, - OnEvent=function(self,func) - table.insert(self.task,func) - end, - FreeConnections=function(self) - self.task={} - end, - Remove=function(self) - if self~=_G.__CAction__ then - for i=1,#event.Mainloop do - if tostring(event.Mainloop[i])==tostring(self) then - table.remove(event.Mainloop,i) - end - end - else - table.insert(event.garbage,self) - end - end, - } - table.insert(event.Mainloop,temp) - event.last=temp - return temp - end, - newAlarm=function(set,func,start) - if not(start) then - timer=0 - active=false - else - timer=os.clock() - active=true - end - if not(func) then - func=(function() end) - end - Alarm= - { - Priority=event.Priority_Normal, - _Priority=0, - Parent=event.Alarms, - Type="Alarm", - active=active, - timer=timer, - set=set or 0, - func={func}, - Act=function(self) - _G.__CAction__=self - if self.active==true then - if os.clock()-self.timer>=self.set then - self:Pause() - self:Stop() - self:Ring() - end - end - end, - FreeConnections=function(self) - self.func={} - end, - Stop=EventRef.Stop, - Pause=EventRef.Pause, - Set=function(self,amt) - self.set=amt - self.timer=os.clock() - self:Resume() - end, - OnRing=function(self,func) - table.insert(self.func,func) - end, - Ring=function(self) - for i=1,#self.func do - self.func[i](self) - end - end, - Reset=function(self) - self.timer=os.clock() - self:Resume() - end, - Resume=EventRef.Resume, - Remove=function(self) - if self~=_G.__CAction__ then - for i=1,#event.Mainloop do - if tostring(event.Mainloop[i])==tostring(self) then - table.remove(event.Mainloop,i) - end - end - else - table.insert(event.garbage,self) - end - end, - } - table.insert(event.Mainloop,Alarm) - event.last=temp - return Alarm - end, - newTask=function(func) - table.insert(event.DoTasks,func) - end, - createLoop=function() - temp= - { - Priority=event.Priority_Normal, - _Priority=0, - Parent=event.Loops, - Type="Loop", - active=true, - func={}, - OnLoop=function(self,func) - table.insert(self.func,func) - end, - Stop=EventRef.Stop, - Pause=EventRef.Pause, - Resume=EventRef.Resume, - Act=function(self) - _G.__CAction__=self - for i=1,#self.func do - self.func[i](os.clock()-event.Start,self) - end - end, - Remove=function(self) - if self~=_G.__CAction__ then - for i=1,#event.Mainloop do - if tostring(event.Mainloop[i])==tostring(self) then - table.remove(event.Mainloop,i) - end - end - else - table.insert(event.garbage,self) - end - end, - FreeConnections=function(self) - self.func={} - end, - } - table.insert(event.Mainloop,temp) - event.last=temp - return temp - end, - createStep=function(start,reset,count,skip) - think=1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - if not(endc) then - endc=false - end - temp= - { - Priority=event.Priority_Normal, - _Priority=0, - start=start or 1, - Parent=event.Steps, - Type="Step", - pos=start or 1, - endAt=reset or math.huge, - active=true, - skip=skip or 0, - spos=0, - count=count or 1*think, - funcs={}, - steps={}, - Act=StepRef.Step, - FAct=StepRef.FStep, - Remove=StepRef.Remove, - Reset=StepRef.Reset, - Set=StepRef.Set, - Pause=StepRef.Pause, - Resume=StepRef.Resume, - Stop=StepRef.Stop, - End=StepRef.End, - Update=StepRef.Update, - OnEnd=StepRef.OnEnd, - OnStep=StepRef.OnStep, - FreeConnections=StepRef.FreeConnections - } - table.insert(event.Mainloop,temp) - event.last=temp - return temp - end, - createTStep=function(start,reset,timer,count) - think=1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - if not(endc) then - endc=false - end - timer=timer or 1 - local _alarm=event.newAlarm(timer,function(alarm) alarm.Link:Act() alarm:Reset() end,true) - temp= - { - Priority=event.Priority_Normal, - _Priority=0, - start=start or 1, - Parent=event.TSteps, - Type="TStep", - pos=start or 1, - endAt=reset or math.huge, - active=true, - skip= 0, - spos=0, - count=count or 1*think, - funcs={}, - steps={}, - alarm=_alarm, - Act=StepRef.Step, - FAct=StepRef.FStep, - Remove=function(self) - if self~=_G.__CAction__ then - for as=1,#event.Mainloop do - if tostring(event.Mainloop[as])==tostring(self) then - table.remove(event.Mainloop,as) - end - end - self.alarm:Remove() - else - table.insert(event.garbage,self) - end - end, - Reset=StepRef.Reset, - Set=StepRef.Set, - Pause=StepRef.Pause, - Resume=StepRef.Resume, - Stop=StepRef.Stop, - End=StepRef.End, - Update=function(self,start,reset,timer,count) - if start~=nil and reset~=nil then - if start>reset then - if not(count<0) then - print("less") - count=-count - end - end - end - self.start=start or self.start - self.endAt=reset or self.endAt - if timer~=nil then - self.alarm:Set(timer) - end - self.count=count or self.count - self.pos=self.start - self:Resume() - end, - OnEnd=StepRef.OnEnd, - OnStep=StepRef.OnStep, - FreeConnections=StepRef.FreeConnections - } - _alarm.Link=temp - event.last=temp - return temp - end, - createTrigger=function(func) - temp={ - active=true, - trigfunc=func, - Remove=function(self) - for i=1,#event.Triggers do - if event.Triggers[i]==self then - table.remove(event.Triggers,i) - end - end - end, - Pause=function(self) self.active=false end, - Resume=function(self) self.active=true end, - Fire=function(self,...) - if self.active==true then - local tempA=__CAction__ - __CAction__=self - self:trigfunc(...) - __CAction__=tempA - end - end, - } - table.insert(event.Triggers,temp) - return temp - end, - stop=function() - event.Active=false - end, - onStart=function() end, - onUpdate=function(func) - local temp=event.createLoop() - temp:OnLoop(func) - temp.Priority=1 - end, - onDraw=function(func) - table.insert(event.drawF,func) - end, - onClose=function() end, - manager=function() - if not(love) then - event.onStart() - event.Start=os.clock() - while event.Active==true do - event.DO_Order() - end - event.onClose() - return os.clock()-event.Start - else - return false - end - end, - cManager=function() - if event.Active==true then - event.DO_Order() - end - end, - uManager=function(dt) - if event.CT==false then - if dt then - event.pump=true - end - event.CT=true - event.onStart() - event.Start=os.clock() - end - event.pumpvar=dt - if event.Active==true then - event.DO_Order() - end - end, - dManager=function() - for ii=1,#event.drawF do - event.drawF[ii]() - end - end, - lManager=function() - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - event.uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - event.dManager() - love.graphics.present() - end - end, - benchMark=function(sec,p) - p=p or event.Priority_Normal - local temp=event.createStep(10) - temp.CC=0 - temp:OnStep(function(pos,step) step.CC=step.CC+1 end) - local Loud=event.newAlarm(sec,nil,true) - Loud.Link=temp - Loud:OnRing(function(alarm) print((alarm.Link.CC).." steps in "..alarm.set.." second(s)") end) - temp.Priority=p - Loud.Priority=p - return Loud - end, -} diff --git a/mulit/oldversions/EventManager(5.7.3).lua b/mulit/oldversions/EventManager(5.7.3).lua deleted file mode 100644 index a51a84f..0000000 --- a/mulit/oldversions/EventManager(5.7.3).lua +++ /dev/null @@ -1,728 +0,0 @@ -function readonlytable(table) - return setmetatable({}, { - __index = table, - __newindex = function(table, key, value) - error("Attempt to modify read-only table") - end, - __metatable = false - }); -end -local EventRef= -readonlytable{ - Pause=function(self) - self.active=false - if not(event.isPaused(self)) then - table.insert(event.Paused,self) - for _j=1,#event.Mainloop do - if tostring(event.Mainloop[_j])==tostring(self) then - table.remove(event.Mainloop,_j) - end - end - end - end, - Resume=function(self) - self.active=true - if event.isPaused(self) then - table.insert(event.Mainloop,self) - for _j=1,#event.Paused do - if tostring(event.Paused[_j])==tostring(self) then - table.remove(event.Paused,_j) - end - end - end - end, - Stop=function(self) - self.active=nil - end, -} - -local StepRef= -readonlytable{ - Step=function(self) - if self~=nil then - if self.spos==0 then - _G.__CAction__=self - if self.active==true then - for i=1,#self.steps do - self.steps[i](self.pos,self) - end - self.pos=self.pos+self.count - end - end - if self.endAt+self.count<=self.pos and self.endAt>self.start then - self:Reset() - for i=1,#self.funcs do - self.funcs[i](self) - end - elseif self.pos<=0 then - self:Reset() - for i=1,#self.funcs do - self.funcs[i](self) - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end, - FStep=function(self) - if self~=nil then - if self.spos==0 then - _G.__CAction__=self - for i=1,#self.steps do - self.steps[i](self.pos,self) - end - self.pos=self.pos+self.count - end - if self.endAt+self.count<=self.pos and self.endAt>self.start then - self:Reset() - for i=1,#self.funcs do - self.funcs[i](self) - end - elseif self.pos==0 then - self:Reset() - for i=1,#self.funcs do - self.funcs[i](self) - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end, - Remove=function(self) - if self~=_G.__CAction__ then - for as=1,#event.Mainloop do - if tostring(event.Mainloop[as])==tostring(self) then - table.remove(event.Mainloop,as) - end - end - else - table.insert(event.garbage,self) - end - end, - Reset=function(self) - self.pos=self.start - end, - Set=function(self,amt) - self.pos=amt - end, - Pause=EventRef.Pause, - Resume=EventRef.Resume, - Stop=function(self) - self:Reset() - self.active=nil - for i=1,#self.funcs do - self.funcs[i](self) - end - end, - End=function(self) - for i=1,#self.funcs do - self.funcs[i](self) - end - self:Reset() - end, - Update=function(self,start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end, - OnEnd=function(self,func) - table.insert(self.funcs,func) - end, - OnStep=function(self,func) - table.insert(self.steps,func) - end, - FreeConnections=function(self) - self.funcs={} - self.steps={} - end, -} ---thread and run setup -if love then - function love.run() - if love.math then - love.math.setRandomSeed(os.time()) - end - if love.event then - love.event.pump() - end - if love.load then love.load(arg) end - if love.timer then love.timer.step() end - local dt = 0 - while true do - -- Process events. - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - event.uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - event.dManager() - love.graphics.setColor(255,255,255,255) - if event.draw then event.draw() end - love.graphics.present() - end - end - end -end -eThreads={ - send=function() end, - - - - -} -function RunTasks() - for i=1,#event.DoTasks do - event.DoTasks[i]() - end -end -event={ - VERSION="1.0.0 (Build Version: 5.7.3)", - Priority_Core=1, - Priority_High=2, - Priority_Above_Normal=4, - Priority_Normal=16, - Priority_Low=256, - Priority_Idle=65536, - Start=0, - Active=true, - CT=false, - Tasks={}, - DoTasks={}, - garbage={}, - Paused={}, - last={}, - func={}, - drawF={}, - pump=false, - pumpvar=0, - Mainloop={}, - PEnabled=true, - PCount=1, - Triggers={}, - oneTimeObj= - { - last={}, - Resume=function(self) end, - Pause=function(self) end, - }, - RemoveAll=function() - event.Mainloop={} - end, - GarbageObj= - { - Resume=function() end, - Pause=function() end - }, - isPaused=function(obj) - for _j=1,#event.Paused do - if tostring(event.Paused[_j])==tostring(obj) then - return true - end - end - return false - end, - DO_Order=function() - event.oneTime(RunTasks) - event.PCount=event.PCount+1 - for i=1,#event.Mainloop do - if event.Mainloop[i]~=nil then - local obj = event.Mainloop[i] - if event.PCount%obj.Priority==0 and event.PEnabled then - obj:Act() - elseif event.PEnabled==false then - obj:Act() - end - if event.PCount>event.Priority_Idle then - event.PCount=event.Priority_Core - end - end - end - event.MANAGE_GARBAGE() - end, - MANAGE_GARBAGE=function() - _G.__CAction__=event.GarbageObj - for _i=1,#event.garbage do - event.garbage[_i]:Remove() - table.remove(event.garbage,_i) - end - end, - oneTime=function(func) - event.oneTimeObj.last=_G.__CAction__ - _G.__CAction__=event.oneTimeObj - for _k=1,#event.Tasks do - if event.Tasks[_k]==func then - _G.__CAction__=event.oneTimeObj.last - return false - end - end - table.insert(event.Tasks,func) - func() - _G.__CAction__=event.oneTimeObj.last - return true - end, - oneETime=function(func) - for _k=1,#event.Tasks do - if event.Tasks[_k]==string.dump(func) then - return false - end - end - table.insert(event.Tasks,string.dump(func)) - func() - return true - end, - hold=function(task) -- as many conditions and times that you want can be used - local action=__CAction__ - action:Pause() - if type(task)=="number" then - local alarm=event.newAlarm(task,function() end,true) - while alarm.active==true do - if love then - event.lManager() - else - event.cManager() - end - end - alarm:Remove() - action:Resume() - elseif type(task)=="function" then - local env=event.newEvent(task,function(envt) envt:Pause() envt:Stop() end) - while env.active do - if love then - event.lManager() - else - event.cManager() - end - end - env:Remove() - action:Resume() - else - print("Error Data Type!!!") - end - end, - waitFor=function(obj) - local obj=obj - event.hold(function() return not(obj.active) end) - end, - getType=function(obj) - if obj.Type~=nil then - return obj.Type - end - end, - newEvent=function(test,task) - temp= - { - Priority=event.Priority_Normal, - _Priority=0, - Parent=event.Events, - Type="Event", - active=true, - test=test or (function() end), - task={task} or {}, - Act=function(self) - _G.__CAction__=self - if self:test(self)==true then - self:Pause() - self:Stop() - for i=1,#self.task do - self.task[i](self) - end - end - end, - Reset=function(self) self:Resume() end, - Stop=EventRef.Stop, - Pause=EventRef.Pause, - Resume=EventRef.Resume, - OnEvent=function(self,func) - table.insert(self.task,func) - end, - FreeConnections=function(self) - self.task={} - end, - Remove=function(self) - if self~=_G.__CAction__ then - for i=1,#event.Mainloop do - if tostring(event.Mainloop[i])==tostring(self) then - table.remove(event.Mainloop,i) - end - end - else - table.insert(event.garbage,self) - end - end, - } - table.insert(event.Mainloop,temp) - event.last=temp - return temp - end, - newAlarm=function(set,func,start) - if not(start) then - timer=0 - active=false - else - timer=os.clock() - active=true - end - if not(func) then - func=(function() end) - end - Alarm= - { - Priority=event.Priority_Normal, - _Priority=0, - Parent=event.Alarms, - Type="Alarm", - active=active, - timer=timer, - set=set or 0, - func={func}, - Act=function(self) - _G.__CAction__=self - if self.active==true then - if os.clock()-self.timer>=self.set then - self:Pause() - self:Stop() - self:Ring() - end - end - end, - FreeConnections=function(self) - self.func={} - end, - Stop=EventRef.Stop, - Pause=EventRef.Pause, - Set=function(self,amt) - self.set=amt - self.timer=os.clock() - self:Resume() - end, - OnRing=function(self,func) - table.insert(self.func,func) - end, - Ring=function(self) - for i=1,#self.func do - self.func[i](self) - end - end, - Reset=function(self) - self.timer=os.clock() - self:Resume() - end, - Resume=EventRef.Resume, - Remove=function(self) - if self~=_G.__CAction__ then - for i=1,#event.Mainloop do - if tostring(event.Mainloop[i])==tostring(self) then - table.remove(event.Mainloop,i) - end - end - else - table.insert(event.garbage,self) - end - end, - } - table.insert(event.Mainloop,Alarm) - event.last=temp - return Alarm - end, - newTask=function(func) - table.insert(event.DoTasks,func) - end, - createLoop=function() - temp= - { - Priority=event.Priority_Normal, - _Priority=0, - Parent=event.Loops, - Type="Loop", - active=true, - func={}, - OnLoop=function(self,func) - table.insert(self.func,func) - end, - Stop=EventRef.Stop, - Pause=EventRef.Pause, - Resume=EventRef.Resume, - Act=function(self) - _G.__CAction__=self - for i=1,#self.func do - self.func[i](os.clock()-event.Start,self) - end - end, - Remove=function(self) - if self~=_G.__CAction__ then - for i=1,#event.Mainloop do - if tostring(event.Mainloop[i])==tostring(self) then - table.remove(event.Mainloop,i) - end - end - else - table.insert(event.garbage,self) - end - end, - FreeConnections=function(self) - self.func={} - end, - } - table.insert(event.Mainloop,temp) - event.last=temp - return temp - end, - createStep=function(start,reset,count,skip) - think=1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - if not(endc) then - endc=false - end - temp= - { - Priority=event.Priority_Normal, - _Priority=0, - start=start or 1, - Parent=event.Steps, - Type="Step", - pos=start or 1, - endAt=reset or math.huge, - active=true, - skip=skip or 0, - spos=0, - count=count or 1*think, - funcs={}, - steps={}, - Act=StepRef.Step, - FAct=StepRef.FStep, - Remove=StepRef.Remove, - Reset=StepRef.Reset, - Set=StepRef.Set, - Pause=StepRef.Pause, - Resume=StepRef.Resume, - Stop=StepRef.Stop, - End=StepRef.End, - Update=StepRef.Update, - OnEnd=StepRef.OnEnd, - OnStep=StepRef.OnStep, - FreeConnections=StepRef.FreeConnections - } - table.insert(event.Mainloop,temp) - event.last=temp - return temp - end, - createTStep=function(start,reset,timer,count) - think=1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - if not(endc) then - endc=false - end - timer=timer or 1 - local _alarm=event.newAlarm(timer,function(alarm) alarm.Link:Act() alarm:Reset() end,true) - temp= - { - Priority=event.Priority_Normal, - _Priority=0, - start=start or 1, - Parent=event.TSteps, - Type="TStep", - pos=start or 1, - endAt=reset or math.huge, - active=true, - skip= 0, - spos=0, - count=count or 1*think, - funcs={}, - steps={}, - alarm=_alarm, - Act=StepRef.Step, - FAct=StepRef.FStep, - Remove=function(self) - if self~=_G.__CAction__ then - for as=1,#event.Mainloop do - if tostring(event.Mainloop[as])==tostring(self) then - table.remove(event.Mainloop,as) - end - end - self.alarm:Remove() - else - table.insert(event.garbage,self) - end - end, - Reset=StepRef.Reset, - Set=StepRef.Set, - Pause=StepRef.Pause, - Resume=StepRef.Resume, - Stop=StepRef.Stop, - End=StepRef.End, - Update=function(self,start,reset,timer,count) - if start~=nil and reset~=nil then - if start>reset then - if not(count<0) then - print("less") - count=-count - end - end - end - self.start=start or self.start - self.endAt=reset or self.endAt - if timer~=nil then - self.alarm:Set(timer) - end - self.count=count or self.count - self.pos=self.start - self:Resume() - end, - OnEnd=StepRef.OnEnd, - OnStep=StepRef.OnStep, - FreeConnections=StepRef.FreeConnections - } - _alarm.Link=temp - event.last=temp - return temp - end, - createTrigger=function(func) - temp={ - active=true, - trigfunc=func, - Remove=function(self) - for i=1,#event.Triggers do - if event.Triggers[i]==self then - table.remove(event.Triggers,i) - end - end - end, - Pause=function(self) self.active=false end, - Resume=function(self) self.active=true end, - Fire=function(self,...) - if self.active==true then - local tempA=__CAction__ - __CAction__=self - self:trigfunc(...) - __CAction__=tempA - end - end, - } - table.insert(event.Triggers,temp) - return temp - end, - stop=function() - event.Active=false - end, - onStart=function() end, - onUpdate=function(func) - local temp=event.createLoop() - temp:OnLoop(func) - temp.Priority=1 - end, - onDraw=function(func) - table.insert(event.drawF,func) - end, - onClose=function() end, - manager=function() - if not(love) then - event.onStart() - event.Start=os.clock() - while event.Active==true do - event.DO_Order() - end - event.onClose() - return os.clock()-event.Start - else - return false - end - end, - cManager=function() - if event.Active==true then - event.DO_Order() - end - end, - uManager=function(dt) - if event.CT==false then - if dt then - event.pump=true - end - event.CT=true - event.onStart() - event.Start=os.clock() - end - event.pumpvar=dt - if event.Active==true then - event.DO_Order() - end - end, - dManager=function() - for ii=1,#event.drawF do - event.drawF[ii]() - end - end, - lManager=function() - if love.event then - love.event.pump() - for e,a,b,c,d in love.event.poll() do - if e == "quit" then - if not love.quit or not love.quit() then - if love.audio then - love.audio.stop() - end - return - end - end - love.handlers[e](a,b,c,d) - end - end - if love.timer then - love.timer.step() - dt = love.timer.getDelta() - end - if love.update then love.update(dt) end - event.uManager(dt) - if love.window and love.graphics and love.window.isCreated() then - love.graphics.clear() - love.graphics.origin() - if love.draw then love.draw() end - event.dManager() - love.graphics.present() - end - end, - benchMark=function(sec,p) - p=p or event.Priority_Normal - local temp=event.createStep(10) - temp.CC=0 - temp:OnStep(function(pos,step) step.CC=step.CC+1 end) - local Loud=event.newAlarm(sec,nil,true) - Loud.Link=temp - Loud:OnRing(function(alarm) print((alarm.Link.CC).." steps in "..alarm.set.." second(s)") end) - temp.Priority=p - Loud.Priority=p - return Loud - end, -} diff --git a/mulit/oldversions/MultiManager(0.3.0).lua b/mulit/oldversions/MultiManager(0.3.0).lua deleted file mode 100644 index 8cd58e3..0000000 --- a/mulit/oldversions/MultiManager(0.3.0).lua +++ /dev/null @@ -1,365 +0,0 @@ -multi = {} -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.Children={} -multi.Paused={} -multi.MasterId=0 -multi.Active=true -multi.Id=-1 --- System -function multi:newBase(ins) - local c = {} - setmetatable(c, multi) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Act=function() end - if ins then - table.insert(multi.Mainloop,ins,c) - else - table.insert(multi.Mainloop,c) - end - multi.MasterId=multi.MasterId+1 - return c -end -function multi:reboot(r) - multi.Mainloop={} - multi.Tasks={} - multi.Tasks2={} - multi.Garbage={} - multi.Children={} - multi.Paused={} - multi.MasterId=0 - multi.Active=true - multi.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=="table" then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end -end ---Processor -function multi.Do_Order() - for _D=#multi.Mainloop,1,-1 do - if multi.Mainloop[_D]~=nil then - multi.Mainloop[_D].Id=_D - multi.Mainloop[_D]:Act() - end - end -end -function multi:benchMark(sec) - local temp=multi:newStep(2) - temp.CC=0 - temp:OnStep(function(pos,step) step.CC=step.CC+1 end) - local Loud=multi:newAlarm(sec) - Loud.Link=temp - Loud:OnRing(function(alarm) alarm.Link.CC=alarm.Link.CC print((alarm.Link.CC).." steps in "..alarm.set.." second(s)") alarm.bench=alarm.Link.CC alarm.Link:Destroy() alarm:Destroy() end) - return Loud -end ---Helpers -function multi:FreeMainEvent() - self.func={} -end -function multi:isPaused() - return not(self.Active) -end -function multi:Pause(n) - if not(n) then - self.Active=false - table.remove(multi.Mainloop,self.Id) - table.insert(multi.Paused,self) - else - self:hold(n) - end -end -function multi:Resume() - if self:isPaused() then - self.Active=true - table.remove(multi.Paused,self.Id) - table.insert(multi.Mainloop,self) - end -end -function multi:Remove() - self:Pause() - self:Destroy() -end -function multi:Destroy() - self:Pause() - if self:isPaused() then - for i=1,#multi.Paused do - if multi.Paused[i]==self then - table.remove(multi.Paused,i) - return - end - end - else - table.remove(multi.Mainloop,self.Id) - end - self.Act=function() end -end -function multi:hold(task) - self:Pause() - if type(task)=="number" then - local alarm=multi:newAlarm(task) - while alarm.Active==true do - if love then - multi.lManager() - else - multi.Do_Order() - end - end - alarm:Destroy() - self:Resume() - elseif type(task)=="function" then - local env=multi:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt:Stop() end) - while env.Active do - if love then - multi.lManager() - else - multi.Do_Order() - end - end - env:Destroy() - self:Resume() - else - print("Error Data Type!!!") - end -end -function multi:oneTime(func,...) - for _k=1,#multi.Tasks2 do - if multi.Tasks2[_k]==func then - return false - end - end - table.insert(multi.Tasks2,func) - func(...) - return true -end ---Constructors -function multi:newEvent(task) - local c=multi:newBase() - c.Type="Event" - c.Task=task or function() end - function c:Act() - if self.Task(self) and self.Active==true then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - return c -end -function multi:newAlarm(set) - local c=multi:newBase() - c.Type="Alarm" - c.timer=os.clock() - c.set=set or 0 - function c:Act() - if self.Active==true then - if os.clock()-self.timer>=self.set then - self:Pause() - for i=1,#self.func do - self.func[i](self) - end - end - end - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - function c:OnRing(func) - table.insert(self.func,func) - end - return c -end -function multi:newTask(func) - table.insert(multi.Tasks,func) -end -function multi:newLoop() - local c=multi:newBase() - c.Type="Loop" - function c:Act() - if self.Active==true then - for i=1,#self.func do - self.func[i](os.clock()-multi.Start,self) - end - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - return c -end -function multi:newStep(start,reset,count,skip) - local c=multi:newBase() - think=1 - c.Type="Step" - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.Active==true then - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - c:OnStep(function(p,s) - if s.count>0 and s.endAt==p then - for fe=1,#s.funcE do - s.funcE[fe](s) - end - s.pos=s.start-1 - elseif s.count<0 and s.endAt==p then - for fe=1,#s.funcE do - s.funcE[fe](s) - end - s.pos=s.start-1 - end - end) - return c -end -function multi:newTStep(start,reset,count,set) - local c=multi:newBase() - think=1 - c.Type="TStep" - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=os.clock() - c.set=set or 1 - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=os.clock() - self:Resume() - end - function c:Act() - if self.Active then - if os.clock()-self.timer>=self.set then - self:Reset() - for i=1,#self.func do - self.func[i](self.pos,self) - end - if self.endAt==self.pos then - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start-1 - end - self.pos=self.pos+self.count - end - end - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - function c:OnStep(func) - table.insert(self.func,func) - end - return c -end - -function multi:inQueue(func) - if self.Id==-1 then - print("Error: Can't queue the multi object") - return - end - local c=multi:newBase(self.Id) - self.Id=self.Id-1 - c.Type="Queue" - c.Task=func - c.Link=self - function c:Act() - self.Task(self.Link) - self:Destroy() - end -end -function multi:newTrigger(func) - local c=multi:newBase() - c.Type="Trigger" - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - return c -end ---Managers -function multi:mainloop() - for i=1,#multi.Tasks do - multi.Tasks[i]() - end - multi.Start=os.clock() - while self.Active do - multi.Do_Order() - end -end -function multi._tFunc(dt) - if dt then - multi.pump=true - end - multi.pumpvar=dt - multi.Start=os.clock() -end -function multi:uManager(dt) - multi:oneTime(multi._tFunc,dt) - multi.Do_Order() -end diff --git a/mulit/oldversions/MultiManager(0.4.0-1).lua b/mulit/oldversions/MultiManager(0.4.0-1).lua deleted file mode 100644 index 1e38f26..0000000 --- a/mulit/oldversions/MultiManager(0.4.0-1).lua +++ /dev/null @@ -1,506 +0,0 @@ -multi = {} -multi.Version="4.0.1" -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.Children={} -multi.Paused={} -multi.MasterId=0 -multi.Active=true -multi.Id=-1 -multi.Type="mainint" -multi.Rest=0 -multi._type=type ---[[function type(v) - local t={} - if multi._type(v)=="table" then - t=getmetatable(v) - if v.Type~=nil then - if multi._type(v.Type)=="string" then - return v.Type - end - end - end - if t.__type~=nil then - return t.__type - else - return multi._type(v) - end -end]] --- System -function os.getOS() - if package.config:sub(1,1)=="\\" then - return "windows" - else - return "unix" - end -end -if os.getOS()=="windows" then - function os.sleep(n) - if n > 0 then os.execute("ping -n " .. tonumber(n+1) .. " localhost > NUL") end - end -else - function os.sleep(n) - os.execute("sleep " .. tonumber(n)) - end -end -function multi:newBase(ins) - if not(self.Type=="mainint" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Act=function() end - c.Parent=self - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - self.MasterId=self.MasterId+1 - return c -end -function multi:reboot(r) - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.MasterId=0 - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=="table" then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:Do_Order() - for _D=#self.Mainloop,1,-1 do - if self.Mainloop[_D]~=nil then - self.Mainloop[_D].Id=_D - self.Mainloop[_D]:Act() - end - if self.Mainloop[_D]~=nil then - if self.Mainloop[_D].rem~=nil then - table.remove(self.Mainloop,_D) - end - end - end - if self.Rest>0 then - os.sleep(self.Rest) - end -end -function multi:benchMark(sec) - local temp=self:newLoop(function(t,self) - if os.clock()-self.init>self.sec then - print(self.c.." steps in "..self.sec.." second(s)") - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=os.clock() - temp.c=0 - return temp -end -function multi:newInterface() - if not(self.Type=="mainint") then error("Can only create an interface on the multi obj") return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type="int" - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.MasterId=0 - c.Active=true - c.Id=-1 - c.Rest=0 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Stop() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - return c -end ---Helpers -function multi:FreeMainEvent() - self.func={} -end -function multi:isPaused() - return not(self.Active) -end -function multi:Pause(n) - if self.Type=="int" or self.Type=="mainint" then - self.Active=false - if not(n) then - local c=self:getChildren() - for i=1,#c do - c[i]:Pause() - end - else - self:hold(n) - end - else - if n==nil then - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - else - self:hold(n) - end - end -end -function multi:Resume() - if self.Type=="int" or self.Type=="mainint" then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:Destroy() - if self.Type=="int" or self.Type=="mainint" then - local c=self:getChildren() - for i=1,#c do - c[i]:Destroy() - end - else - self.rem=true - self.Active=false - end -end -function multi:hold(task) - self:Pause() - if type(task)=="number" then - local alarm=self.Parent:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - alarm:Destroy() - self:Resume() - elseif type(task)=="function" then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt:Stop() end) - while env.Active do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - env:Destroy() - self:Resume() - else - print("Error Data Type!!!") - end -end -function multi:oneTime(func,...) - if not(self.Type=="mainint" or self.Type=="int") then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end ---Constructors -function multi:newEvent(task) - local c=self:newBase() - c.Type="event" - c.Task=task or function() end - function c:Act() - if self.Task(self) and self.Active==true then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - return c -end -function multi:newAlarm(set) - local c=self:newBase() - c.Type="alarm" - c.timer=os.clock() - c.set=set or 0 - function c:Act() - if self.Active==true then - if os.clock()-self.timer>=self.set then - self:Pause() - for i=1,#self.func do - self.func[i](self) - end - end - end - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - self.Active=true - end - function c:OnRing(func) - table.insert(self.func,func) - end - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newLoop(func) - local c=self:newBase() - c.Type="loop" - if func then - c.func={func} - end - function c:Act() - if self.Active==true then - for i=1,#self.func do - self.func[i](os.clock()-self.Parent.Start,self) - end - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - function c:Break() - self.Active=nil - end - return c -end -function multi:newStep(start,reset,count,skip) - local c=self:newBase() - think=1 - c.Type="step" - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.Active==true then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - return c -end -function multi:newTStep(start,reset,count,set) - local c=self:newBase() - think=1 - c.Type="tstep" - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=os.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=os.clock() - self:Resume() - end - function c:Act() - if self.Active then - if os.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - return c -end -function multi:newTrigger(func) - local c=self:newBase() - c.Type="trigger" - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - return c -end ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - self.Start=os.clock() - while self.Active do - self:Do_Order() - end -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - self.Start=os.clock() -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - self:Do_Order() - end -end diff --git a/mulit/oldversions/MultiManager(0.4.0-5).lua b/mulit/oldversions/MultiManager(0.4.0-5).lua deleted file mode 100644 index f17b2cd..0000000 --- a/mulit/oldversions/MultiManager(0.4.0-5).lua +++ /dev/null @@ -1,596 +0,0 @@ -multi = {} -multi.Version="4.0.5" -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.Children={} -multi.Paused={} -multi.MasterId=0 -multi.Active=true -multi.Id=-1 -multi.Type="mainint" -multi.Rest=0 -multi._type=type -multi.Jobs={} -multi.queue={} -multi.jobUS=2 ---[[function type(v) - local t={} - if multi._type(v)=="table" then - t=getmetatable(v) - if v.Type~=nil then - if multi._type(v.Type)=="string" then - return v.Type - end - end - end - if t.__type~=nil then - return t.__type - else - return multi._type(v) - end -end]] --- System -function os.getOS() - if package.config:sub(1,1)=="\\" then - return "windows" - else - return "unix" - end -end -if os.getOS()=="windows" then - function os.sleep(n) - if n > 0 then os.execute("ping -n " .. tonumber(n+1) .. " localhost > NUL") end - end -else - function os.sleep(n) - os.execute("sleep " .. tonumber(n)) - end -end -function multi:newBase(ins) - if not(self.Type=="mainint" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Act=function() end - c.Parent=self - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - self.MasterId=self.MasterId+1 - return c -end -function multi:reboot(r) - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.MasterId=0 - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=="table" then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:Do_Order() - for _D=#self.Mainloop,1,-1 do - if self.Mainloop[_D]~=nil then - self.Mainloop[_D].Id=_D - self.Mainloop[_D]:Act() - end - if self.Mainloop[_D]~=nil then - if self.Mainloop[_D].rem~=nil then - table.remove(self.Mainloop,_D) - end - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end -end -function multi:benchMark(sec) - local temp=self:newLoop(function(t,self) - if os.clock()-self.init>self.sec then - print(self.c.." steps in "..self.sec.." second(s)") - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=os.clock() - temp.c=0 - return temp -end -function multi:newInterface() - if not(self.Type=="mainint") then error("Can only create an interface on the multi obj") return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type="int" - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.MasterId=0 - c.Active=true - c.Id=-1 - c.Rest=0 - c.Jobs={} - c.queue={} - c.jobUS=2 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Stop() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - return c -end ---Helpers -function multi:FreeMainEvent() - self.func={} -end -function multi:isPaused() - return not(self.Active) -end -function multi:Pause(n) - if self.Type=="int" or self.Type=="mainint" then - self.Active=false - if not(n) then - local c=self:getChildren() - for i=1,#c do - c[i]:Pause() - end - else - self:hold(n) - end - else - if n==nil then - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - else - self:hold(n) - end - end -end -function multi:Resume() - if self.Type=="int" or self.Type=="mainint" then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:Destroy() - if self.Type=="int" or self.Type=="mainint" then - local c=self:getChildren() - for i=1,#c do - c[i]:Destroy() - end - else - self.rem=true - self.Active=false - end -end -function multi:hold(task) - self:Pause() - if type(task)=="number" then - local alarm=self.Parent:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - alarm:Destroy() - self:Resume() - elseif type(task)=="function" then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt:Stop() end) - while env.Active do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - env:Destroy() - self:Resume() - else - print("Error Data Type!!!") - end -end -function multi:oneTime(func,...) - if not(self.Type=="mainint" or self.Type=="int") then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end ---Constructors -function multi:newEvent(task) - local c=self:newBase() - c.Type="event" - c.Task=task or function() end - function c:Act() - if self.Task(self) and self.Active==true then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - return c -end -function multi:newAlarm(set) - local c=self:newBase() - c.Type="alarm" - c.timer=os.clock() - c.set=set or 0 - function c:Act() - if self.Active==true then - if os.clock()-self.timer>=self.set then - self:Pause() - for i=1,#self.func do - self.func[i](self) - end - end - end - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - self.Active=true - end - function c:OnRing(func) - table.insert(self.func,func) - end - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newLoop(func) - local c=self:newBase() - c.Type="loop" - if func then - c.func={func} - end - function c:Act() - if self.Active==true then - for i=1,#self.func do - self.func[i](os.clock()-self.Parent.Start,self) - end - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - function c:Break() - self.Active=nil - end - return c -end -function multi:newStep(start,reset,count,skip) - local c=self:newBase() - think=1 - c.Type="step" - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.Active==true then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - return c -end -function multi:newTStep(start,reset,count,set) - local c=self:newBase() - think=1 - c.Type="tstep" - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=os.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=os.clock() - self:Resume() - end - function c:Act() - if self.Active then - if os.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - return c -end -function multi:newTrigger(func) - local c={}--self:newBase() - c.Type="trigger" - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - return c -end -function multi:newConnection() - local c={} - c.Type="connector" - c.func={} - function c:Fire(...) - for i=1,#self.func do - t,e=pcall(self.func[i],...) - if not(t) then - print(e) - end - end - end - function c:connect(func) - table.insert(self.func,func) - end - return c -end -function multi:newJob(func,name) - if not(self.Type=="mainint" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Parent=self - c.Type="job" - c.trigfunc=func or function() end - function c:Act() - self:trigfunc(self) - end - table.insert(self.Jobs,{c,name}) - if self.JobRunner==nil then - self.JobRunner=self:newAlarm(self.jobUS) - self.JobRunner:OnRing(function(self) - if #self.Parent.Jobs>0 then - if self.Parent.Jobs[1] then - self.Parent.Jobs[1][1]:Act() - table.remove(self.Parent.Jobs,1) - end - end - self:Reset(self.Parent.jobUS) - end) - end -end -function multi:setJobSpeed(n) - self.jobUS=n -end -function multi:hasJobs() - return #self.Jobs>0,#self.Jobs -end -function multi:getJobs() - return #self.Jobs -end -function multi:removeJob(name) - for i=#self.Jobs,1,-1 do - if self.Jobs[i][2]==name then - table.remove(self.Jobs,i) - end - end -end ---Incomplete -function multi:addToQueue(name,job) - if self.queue[name]~=nil then - table.insert(self.queue[name],job) - else - self.queue[name]={} - end - if self.QRunner==nil then - self.QRunner=self:newAlarm(.5) - self.QRunner:OnRing(function(self) - if #self.Parent.queue>0 then - local w=math.random(1,#self.Parent.Jobs) - self.Parent.Jobs[w]:Act() - table.remove(self.Parent.Jobs,w) - end - self:Reset() - end) - end -end ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - self.Start=os.clock() - while self.Active do - self:Do_Order() - end -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - self.Start=os.clock() -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - self:Do_Order() - end -end diff --git a/mulit/oldversions/MultiManager(0.5.1-6).lua b/mulit/oldversions/MultiManager(0.5.1-6).lua deleted file mode 100644 index 8aef936..0000000 --- a/mulit/oldversions/MultiManager(0.5.1-6).lua +++ /dev/null @@ -1,767 +0,0 @@ -multi = {} -multi.Version="5.1.6" -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.Children={} -multi.Paused={} -multi.MasterId=0 -multi.Active=true -multi.Id=-1 -multi.Type="mainint" -multi.Rest=0 -multi._type=type -multi.Jobs={} -multi.queue={} -multi.jobUS=2 --- System -function multi:Stop() - self.Active=false -end -function os.getOS() - if package.config:sub(1,1)=="\\" then - return "windows" - else - return "unix" - end -end -if os.getOS()=="windows" then - function os.sleep(n) - if n > 0 then os.execute("ping -n " .. tonumber(n+1) .. " localhost > NUL") end - end -else - function os.sleep(n) - os.execute("sleep " .. tonumber(n)) - end -end -function multi:newBase(ins) - if not(self.Type=="mainint" or self.Type=="int" or self.Type=="stack") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" or self.Type=="stack" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.ender={} - c.Id=0 - c.PId=0 - c.Act=function() end - c.Parent=self - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - self.MasterId=self.MasterId+1 - return c -end -function multi:reboot(r) - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.MasterId=0 - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=="table" then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:getError() - if self.error then - return self.error - end -end -function multi:Do_Order() - for _D=#self.Mainloop,1,-1 do - if self.Mainloop[_D]~=nil then - self.Mainloop[_D].Id=_D - self.Mainloop[_D]:Act() - end - if self.Mainloop[_D]~=nil then - if self.Mainloop[_D].rem~=nil then - table.remove(self.Mainloop,_D) - end - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end -end -function multi:benchMark(sec) - local temp=self:newLoop(function(t,self) - if os.clock()-self.init>self.sec then - print(self.c.." steps in "..self.sec.." second(s)") - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=os.clock() - temp.c=0 - return temp -end -function multi:newInterface() - if not(self.Type=="mainint") then error("Can only create an interface on the multi obj") return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type="int" - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.MasterId=0 - c.Active=true - c.Id=-1 - c.Rest=0 - c.Jobs={} - c.queue={} - c.jobUS=2 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Stop() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - return c -end -function multi:newStack(file) - local c=self:newInterface() - c.Type="stack" - stack=c - c.last={} - c.funcE={} - if file then - dofile(file) - end - function c:OnStackCompleted(func) - table.insert(self.funcE,func) - end - return c -end ---Helpers -function multi:protect() - function self:Do_Order() - for _D=#self.Mainloop,1,-1 do - if self.Mainloop[_D]~=nil then - self.Mainloop[_D].Id=_D - local status, err=pcall(self.Mainloop[_D].Act,self.Mainloop[_D]) - if err and not(self.Mainloop[_D].error) then - self.Mainloop[_D].error=err - print(err..": Ingoring error continuing...") - end - end - if self.Mainloop[_D]~=nil then - if self.Mainloop[_D].rem~=nil then - table.remove(self.Mainloop,_D) - end - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end - end -end -function multi:unProtect() - function self:Do_Order() - for _D=#self.Mainloop,1,-1 do - if self.Mainloop[_D]~=nil then - self.Mainloop[_D].Id=_D - self.Mainloop[_D]:Act() - end - if self.Mainloop[_D]~=nil then - if self.Mainloop[_D].rem~=nil then - table.remove(self.Mainloop,_D) - end - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end - end -end -function multi:setJobSpeed(n) - self.jobUS=n -end -function multi:hasJobs() - return #self.Jobs>0,#self.Jobs -end -function multi:getJobs() - return #self.Jobs -end -function multi:removeJob(name) - for i=#self.Jobs,1,-1 do - if self.Jobs[i][2]==name then - table.remove(self.Jobs,i) - end - end -end -function multi:FreeMainEvent() - self.func={} -end -function multi:connectFinal(func) - if self.Type=="event" then - self:OnEvent(func) - elseif self.Type=="alarm" then - self:OnRing(func) - elseif self.Type=="step" or self.Type=="tstep" then - self:OnEnd(func) - elseif self.Type=="loop" then - self:OnBreak(func) - else - error("No final event exists for: "..self.Type) - end -end -function multi:Break() - self:Pause() - self.Active=nil - for i=1,#self.ender do - self.ender[i](self) - end -end -function multi:OnBreak(func) - table.insert(self.ender,func) -end -function multi:isPaused() - return not(self.Active) -end -function multi:Pause(n) - if self.Type=="int" or self.Type=="mainint" then - self.Active=false - if not(n) then - local c=self:getChildren() - for i=1,#c do - c[i]:Pause() - end - else - self:hold(n) - end - else - if n==nil then - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - else - self:hold(n) - end - end -end -function multi:Resume() - if self.Type=="int" or self.Type=="mainint" then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:Destroy() - if self.Type=="int" or self.Type=="mainint" then - local c=self:getChildren() - for i=1,#c do - c[i]:Destroy() - end - else - self.rem=true - self.Active=false - end -end -function multi:hold(task) - self:Pause() - if type(task)=="number" then - local alarm=self.Parent:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - alarm:Destroy() - self:Resume() - elseif type(task)=="function" then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt:Stop() end) - while env.Active do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - env:Destroy() - self:Resume() - else - print("Error Data Type!!!") - end -end -function multi:oneTime(func,...) - if not(self.Type=="mainint" or self.Type=="int") then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end -function multi:Reset(n) - self:Resume() -end -function multi:isDone() - return self.Active~=true -end ---Constructors -function multi:newEvent(task) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type="event" - c.Task=task or function() end - function c:Act() - if self.Task(self) and self.Active==true then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newAlarm(set) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type="alarm" - c.timer=os.clock() - c.set=set or 0 - function c:Act() - if self.Active==true then - if os.clock()-self.timer>=self.set then - self:Pause() - self.Active=false - for i=1,#self.func do - self.func[i](self) - end - end - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer=os.clock() - self.Active=true - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - self.Active=true - end - function c:OnRing(func) - table.insert(self.func,func) - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - table.remove(self.Parent.Mainloop,#self.Parent.Mainloop) - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newLoop(func) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type="loop" - c.Start=os.clock() - if func then - c.func={func} - end - function c:Act() - if self.Active==true then - for i=1,#self.func do - self.func[i](os.clock()-self.Start,self) - end - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newStep(start,reset,count,skip) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type="step" - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.Active==true then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newTStep(start,reset,count,set) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type="tstep" - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=os.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=os.clock() - self:Resume() - end - function c:Act() - if self.Active then - if os.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=os.clock() - self:Resume() - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newTrigger(func) - local c={} - c.Type="trigger" - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - return c -end -function multi:newConnection() - local c={} - c.Type="connector" - c.func={} - function c:Fire(...) - for i=1,#self.func do - t,e=pcall(self.func[i],...) - if not(t) then - print(e) - end - end - end - function c:bind(t) - self.func=t - end - function c:connect(func) - table.insert(self.func,func) - end - return c -end -function multi:newJob(func,name) - if not(self.Type=="mainint" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Parent=self - c.Type="job" - c.trigfunc=func or function() end - function c:Act() - self:trigfunc(self) - end - table.insert(self.Jobs,{c,name}) - if self.JobRunner==nil then - self.JobRunner=self:newAlarm(self.jobUS) - self.JobRunner:OnRing(function(self) - if #self.Parent.Jobs>0 then - if self.Parent.Jobs[1] then - self.Parent.Jobs[1][1]:Act() - table.remove(self.Parent.Jobs,1) - end - end - self:Reset(self.Parent.jobUS) - end) - end -end ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - self.Start=os.clock() - while self.Active do - self:Do_Order() - end -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - self.Start=os.clock() -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - self:Do_Order() - end -end diff --git a/mulit/oldversions/MultiManager(0.6.1-6).lua b/mulit/oldversions/MultiManager(0.6.1-6).lua deleted file mode 100644 index cdd075a..0000000 --- a/mulit/oldversions/MultiManager(0.6.1-6).lua +++ /dev/null @@ -1,929 +0,0 @@ -multi = {} -multi.Version={6,1,6}-- History: EventManager,EventManager+,MultiManager <-- Current -multi.stage="stable" -multi.Features=multi.Version[1].."."..multi.Version[2].."."..multi.Version[3].." "..multi.stage..[[ - Objects: - Event - Alarm - Loop - Step - TStep - Trigger - Task - Connection - Timer - Job -]] -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.Children={} -multi.Paused={} -multi.Active=true -multi.Id=-1 -multi.Type="mainint" -multi.Rest=0 -multi._type=type -multi.Jobs={} -multi.queue={} -multi.jobUS=2 -multi.clock=os.clock -multi.time=os.time --- System -function multi:Stop() - self.Active=false -end -function os.getOS() - if package.config:sub(1,1)=="\\" then - return "windows" - else - return "unix" - end -end -if os.getOS()=="windows" then - function os.sleep(n) - if n > 0 then os.execute("ping -n " .. tonumber(n+1) .. " localhost > NUL") end - end -else - function os.sleep(n) - os.execute("sleep " .. tonumber(n)) - end -end -function multi.executeFunction(name,...) - if type(_G[name])=="function" then - _G[name](...) - else - print("Error: Not a function") - end -end -function multi:newBase(ins) - if not(self.Type=="mainint" or self.Type=="int" or self.Type=="stack") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" or self.Type=="stack" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.ender={} - c.Id=0 - c.PId=0 - c.Act=function() end - c.Parent=self - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - return c -end -function multi:reboot(r) - local before=collectgarbage("count") - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=="table" then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end - collectgarbage() - local after=collectgarbage("count") - print([[Before rebooting total Ram used was ]]..before..[[Kb -After rebooting total Ram used is ]]..after..[[ Kb -A total of ]]..(before-after)..[[Kb was cleaned up]]) -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:getError() - if self.error then - return self.error - end -end -function multi:Do_Order() - local Loop=self.Mainloop - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - Loop[_D]:Act() - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end -end -function multi:fromfile(path,int) - int=int or multi - local test2={} - local test=bin.load(path) - local tp=test:getBlock("s") - if tp=="event" then - test2=int:newEvent(test:getBlock("f")) - local t=test:getBlock("t") - for i=1,#t do - test2:OnEvent(t[i]) - end - elseif tp=="alarm" then - test2=int:newAlarm(test:getBlock("n")) - elseif tp=="loop" then - test2=int:newLoop(test:getBlock("t")[1]) - elseif tp=="step" or tp=="tstep" then - local func=test:getBlock("t") - local funcE=test:getBlock("t") - local funcS=test:getBlock("t") - local tab=test:getBlock("t") - test2=int:newStep() - table.merge(test2,tab) - test2.funcE=funcE - test2.funcS=funcS - test2.func=func - elseif tp=="trigger" then - test2=int:newTrigger(test:getBlock("f")) - elseif tp=="connector" then - test2=int:newConnection() - test2.func=test:getBlock("t") - elseif tp=="timer" then - test2=int:newTimer() - test2.count=tonumber(test:getBlock("n")) - else - print("Error: The file you selected is not a valid multi file object!") - return false - end - return test2 -end -function multi:benchMark(sec) - local temp=self:newLoop(function(t,self) - if multi.clock()-self.init>self.sec then - print(self.c.." steps in "..self.sec.." second(s)") - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=multi.clock() - temp.c=0 - return temp -end -function multi:tofile(path) - local items=self:getChildren() - io.mkDir(io.getName(path)) - for i=1,#items do - items[i]:tofile(io.getName(path).."\\item"..item[i]..".dat") - end - local int=bin.new() - int:addBlock("int") - int:addBlock(io.getName(path)) - int:addBlock(#self.Mainloop) - int:addBlock(self.Active) - int:addBlock(self.Rest) - int:addBlock(self.Jobs) - int:tofile() -end -function multi:newInterface(file) - if not(self.Type=="mainint") then error("Can only create an interface on the multi obj") return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type="int" - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.Active=true - c.Id=-1 - c.Rest=0 - c.Jobs={} - c.queue={} - c.jobUS=2 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Stop() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - if file then - multi.Cself=c - loadstring("interface=multi.Cself "..io.open(file,"rb"):read("*all"))() - end - return c -end -function multi:newStack(file) - local c=self:newInterface() - c.Type="stack" - c.last={} - c.funcE={} - if file then - multi.Cself=c - loadstring("stack=multi.Cself "..io.open(file,"rb"):read("*all"))() - end - function c:OnStackCompleted(func) - table.insert(self.funcE,func) - end - return c -end ---Helpers -function multi:protect() - function self:Do_Order() - local Loop=self.Mainloop - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - local status, err=pcall(Loop[_D].Act,Loop[_D]) - if err and not(Loop[_D].error) then - Loop[_D].error=err - print(err..": Ingoring error continuing...") - end - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end - end -end -function multi:unProtect() - function self:Do_Order() - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - Loop[_D]:Act() - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end - end -end -function multi:setJobSpeed(n) - self.jobUS=n -end -function multi:hasJobs() - return #self.Jobs>0,#self.Jobs -end -function multi:getJobs() - return #self.Jobs -end -function multi:removeJob(name) - for i=#self.Jobs,1,-1 do - if self.Jobs[i][2]==name then - table.remove(self.Jobs,i) - end - end -end -function multi:FreeMainEvent() - self.func={} -end -function multi:connectFinal(func) - if self.Type=="event" then - self:OnEvent(func) - elseif self.Type=="alarm" then - self:OnRing(func) - elseif self.Type=="step" or self.Type=="tstep" then - self:OnEnd(func) - elseif self.Type=="loop" then - self:OnBreak(func) - else - error("No final event exists for: "..self.Type) - end -end -function multi:Break() - self:Pause() - self.Active=nil - for i=1,#self.ender do - self.ender[i](self) - end -end -function multi:OnBreak(func) - table.insert(self.ender,func) -end -function multi:isPaused() - return not(self.Active) -end -function multi:Pause(n) - if self.Type=="int" or self.Type=="mainint" then - self.Active=false - if not(n) then - local c=self:getChildren() - for i=1,#c do - c[i]:Pause() - end - else - self:hold(n) - end - else - if n==nil then - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - else - self:hold(n) - end - end -end -function multi:Resume() - if self.Type=="int" or self.Type=="mainint" then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:resurrect() - table.insert(self.Parent.Mainloop,self) - self.Active=true -end -function multi:Destroy() - if self.Type=="int" or self.Type=="mainint" then - local c=self:getChildren() - for i=1,#c do - c[i]:Destroy() - end - else - for i=1,#self.Parent.Mainloop do - if self.Parent.Mainloop[i]==self then - table.remove(self.Parent.Mainloop,i) - break - end - end - self.Active=false - end -end -function multi:hold(task) - self:Pause() - if type(task)=="number" then - local alarm=self.Parent:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - alarm:Destroy() - self:Resume() - elseif type(task)=="function" then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt:Stop() end) - while env.Active do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - env:Destroy() - self:Resume() - else - print("Error Data Type!!!") - end -end -function multi:oneTime(func,...) - if not(self.Type=="mainint" or self.Type=="int") then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end -function multi:Reset(n) - self:Resume() -end -function multi:isDone() - return self.Active~=true -end ---Constructors -function multi:newEvent(task) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type="event" - c.Task=task or function() end - function c:Act() - if self.Task(self) and self.Active==true then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.Task) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newAlarm(set) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type="alarm" - c.timer=self:newTimer() - c.set=set or 0 - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.set) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.Active==true then - if self.timer:Get()>=self.set then - self:Pause() - self.Active=false - for i=1,#self.func do - self.func[i](self) - end - end - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer:Resume() - end - function c:Reset(n) - if n then self.set=n end - self:Resume() - self.timer:Reset() - end - function c:OnRing(func) - table.insert(self.func,func) - end - function c:Pause() - self.timer:Pause() - self.Parent.Pause(self) - end - if self.Type=="stack" then - c:Pause() - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - table.remove(self.Parent.Mainloop,#self.Parent.Mainloop) - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - else - c.timer:Start() - end - return c -end -function multi:newTimer() - local c={} - c.Type="timer" - c.time=0 - c.count=0 - function c:Start() - self.time=multi.clock() - end - function c:Get() - return (multi.clock()-self.time)+self.count - end - c.Reset=c.Start - function c:Pause() - self.time=self:Get() - end - function c:Resume() - self.time=multi.clock()-self.time - end - function c:tofile(path) - local m=bin.new() - self.count=self.count+self:Get() - m:addBlock(self.Type) - m:addBlock(self.count) - m:tofile(path) - end - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newLoop(func) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type="loop" - c.Start=multi.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.Active==true then - for i=1,#self.func do - self.func[i](multi.clock()-self.Start,self) - end - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newStep(start,reset,count,skip) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type="step" - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.Active==true then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newTStep(start,reset,count,set) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type="tstep" - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=multi.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=multi.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.Active then - if multi.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=multi.clock() - self:Resume() - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newTrigger(func) - local c={} - c.Type="trigger" - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.trigfunc) - m:tofile(path) - end - return c -end -function multi:newConnection() - local c={} - c.Type="connector" - c.func={} - function c:Fire(...) - for i=1,#self.func do - t,e=pcall(self.func[i],...) - if not(t) then - print(e) - end - end - end - function c:bind(t) - self.func=t - end - function c:connect(func) - table.insert(self.func,func) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:tofile(path) - end - return c -end -function multi:newJob(func,name) - if not(self.Type=="mainint" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Parent=self - c.Type="job" - c.trigfunc=func or function() end - function c:Act() - self:trigfunc(self) - end - table.insert(self.Jobs,{c,name}) - if self.JobRunner==nil then - self.JobRunner=self:newAlarm(self.jobUS) - self.JobRunner:OnRing(function(self) - if #self.Parent.Jobs>0 then - if self.Parent.Jobs[1] then - self.Parent.Jobs[1][1]:Act() - table.remove(self.Parent.Jobs,1) - end - end - self:Reset(self.Parent.jobUS) - end) - end -end ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,"Start",multi.clock()) - while self.Active do - self:Do_Order() - end -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - rawset(self,"Start",multi.clock()) -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - self:Do_Order() - end -end diff --git a/mulit/oldversions/MultiManager(0.6.2).lua b/mulit/oldversions/MultiManager(0.6.2).lua deleted file mode 100644 index ca66f34..0000000 --- a/mulit/oldversions/MultiManager(0.6.2).lua +++ /dev/null @@ -1,1056 +0,0 @@ -if not bin then - print("Warning the 'bin' library wasn't required! multi:tofile(path) and the multi:fromfile(path,int) feature will not work!") -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == "table" then - if type(t1[k] or false) == "table" then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -multi = {} -multi.Version={6,2,0}-- History: EventManager,EventManager+,MultiManager <-- Current -multi.stage="stable" -multi.Features=multi.Version[1].."."..multi.Version[2].."."..multi.Version[3].." "..multi.stage..[[ - Objects: - Event - Alarm - Loop - Step - TStep - Trigger - Task - Connection - Timer - Job -]] -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.Children={} -multi.Paused={} -multi.Active=true -multi.Id=-1 -multi.Type="mainint" -multi.Rest=0 -multi._type=type -multi.Jobs={} -multi.queue={} -multi.jobUS=2 -multi.clock=os.clock -multi.time=os.time -multi.LinkedPath=multi --- System -function multi:Stop() - self.Active=false -end -function os.getOS() - if package.config:sub(1,1)=="\\" then - return "windows" - else - return "unix" - end -end -if os.getOS()=="windows" then - function os.sleep(n) - if n > 0 then os.execute("ping -n " .. tonumber(n+1) .. " localhost > NUL") end - end -else - function os.sleep(n) - os.execute("sleep " .. tonumber(n)) - end -end -function multi.executeFunction(name,...) - if type(_G[name])=="function" then - _G[name](...) - else - print("Error: Not a function") - end -end -function multi:reboot(r) - local before=collectgarbage("count") - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=="table" then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end - collectgarbage() - local after=collectgarbage("count") - print([[Before rebooting total Ram used was ]]..before..[[Kb -After rebooting total Ram used is ]]..after..[[ Kb -A total of ]]..(before-after)..[[Kb was cleaned up]]) -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:getError() - if self.error then - return self.error - end -end -function multi:Do_Order() - local Loop=self.Mainloop - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - if Loop[_D].Active then - Loop[_D].Id=_D - Loop[_D]:Act() - end - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end -end -function multi:fromfile(path,int) - int=int or multi - local test2={} - local test=bin.load(path) - local tp=test:getBlock("s") - if tp=="event" then - test2=int:newEvent(test:getBlock("f")) - local t=test:getBlock("t") - for i=1,#t do - test2:OnEvent(t[i]) - end - elseif tp=="alarm" then - test2=int:newAlarm(test:getBlock("n")) - elseif tp=="loop" then - test2=int:newLoop(test:getBlock("t")[1]) - elseif tp=="step" or tp=="tstep" then - local func=test:getBlock("t") - local funcE=test:getBlock("t") - local funcS=test:getBlock("t") - local tab=test:getBlock("t") - test2=int:newStep() - table.merge(test2,tab) - test2.funcE=funcE - test2.funcS=funcS - test2.func=func - elseif tp=="trigger" then - test2=int:newTrigger(test:getBlock("f")) - elseif tp=="connector" then - test2=int:newConnection() - test2.func=test:getBlock("t") - elseif tp=="timer" then - test2=int:newTimer() - test2.count=tonumber(test:getBlock("n")) - else - print("Error: The file you selected is not a valid multi file object!") - return false - end - return test2 -end -function multi:benchMark(sec) - local temp=self:newLoop(function(t,self) - if multi.clock()-self.init>self.sec then - print(self.c.." steps in "..self.sec.." second(s)") - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=multi.clock() - temp.c=0 - return temp -end -function multi:tofile(path) - local items=self:getChildren() - io.mkDir(io.getName(path)) - for i=1,#items do - items[i]:tofile(io.getName(path).."\\item"..item[i]..".dat") - end - local int=bin.new() - int:addBlock("int") - int:addBlock(io.getName(path)) - int:addBlock(#self.Mainloop) - int:addBlock(self.Active) - int:addBlock(self.Rest) - int:addBlock(self.Jobs) - int:tofile() -end ---Helpers -function multi:OnMainConnect(func) - table.insert(self.func,func) -end -function multi:protect() - function self:Do_Order() - local Loop=self.Mainloop - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - local status, err=pcall(Loop[_D].Act,Loop[_D]) - if err and not(Loop[_D].error) then - Loop[_D].error=err - print(err..": Ingoring error continuing...") - end - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end - end -end -function multi:unProtect() - function self:Do_Order() - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - Loop[_D]:Act() - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end - end -end -function multi:setJobSpeed(n) - self.jobUS=n -end -function multi:hasJobs() - return #self.Jobs>0,#self.Jobs -end -function multi:getJobs() - return #self.Jobs -end -function multi:removeJob(name) - for i=#self.Jobs,1,-1 do - if self.Jobs[i][2]==name then - table.remove(self.Jobs,i) - end - end -end -function multi:FreeMainEvent() - self.func={} -end -function multi:connectFinal(func) - if self.Type=="event" then - self:OnEvent(func) - elseif self.Type=="alarm" then - self:OnRing(func) - elseif self.Type=="step" or self.Type=="tstep" then - self:OnEnd(func) - elseif self.Type=="loop" or self.Type=="updater" then - self:OnBreak(func) - else - error("No final event exists for: "..self.Type) - end -end -function multi:Break() - self:Pause() - self.Active=nil - for i=1,#self.ender do - self.ender[i](self) - end -end -function multi:OnBreak(func) - table.insert(self.ender,func) -end -function multi:isPaused() - return not(self.Active) -end -function multi:Pause(n) - if self.Type=="int" or self.Type=="mainint" then - self.Active=false - if not(n) then - local c=self:getChildren() - for i=1,#c do - c[i]:Pause() - end - else - self:hold(n) - end - else - if n==nil then - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - else - self:hold(n) - end - end -end -function multi:Resume() - if self.Type=="int" or self.Type=="mainint" then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:resurrect() - table.insert(self.Parent.Mainloop,self) - self.Active=true -end -function multi:Destroy() - if self.Type=="int" or self.Type=="mainint" then - local c=self:getChildren() - for i=1,#c do - c[i]:Destroy() - end - else - for i=1,#self.Parent.Mainloop do - if self.Parent.Mainloop[i]==self then - table.remove(self.Parent.Mainloop,i) - break - end - end - self.Active=false - end -end -function multi:hold(task) - self:Pause() - if type(task)=="number" then - local alarm=self.Parent:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - alarm:Destroy() - self:Resume() - elseif type(task)=="function" then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt:Stop() end) - while env.Active do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - env:Destroy() - self:Resume() - else - print("Error Data Type!!!") - end -end -function multi:oneTime(func,...) - if not(self.Type=="mainint" or self.Type=="int") then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end -function multi:Reset(n) - self:Resume() -end -function multi:isDone() - return self.Active~=true -end ---Constructors [CORE] -function multi:newBase(ins) - if not(self.Type=="mainint" or self.Type=="int" or self.Type=="stack") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" or self.Type=="stack" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.ender={} - c.Id=0 - c.PId=0 - c.Act=function() end - c.Parent=self - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - return c -end -function multi:newInterface(file) - if not(self.Type=="mainint") then error("Can only create an interface on the multi obj") return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type="int" - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.Active=true - c.Id=-1 - c.Rest=0 - c.Jobs={} - c.queue={} - c.jobUS=2 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Stop() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - if file then - multi.Cself=c - loadstring("interface=multi.Cself "..io.open(file,"rb"):read("*all"))() - end - return c -end -function multi:newStack(file) - local c=self:newInterface() - c.Type="stack" - c.last={} - c.funcE={} - if file then - multi.Cself=c - loadstring("stack=multi.Cself "..io.open(file,"rb"):read("*all"))() - end - function c:OnStackCompleted(func) - table.insert(self.funcE,func) - end - return c -end ---Constructors [ACTORS] -function multi:coustomObject(objRef,t) - local c={} - if t=="process" then - c=self:newBase() - if type(objRef)=="table" then - table.merge(c,objRef) - end - if not c.Act then - function c:Act() - -- Empty function - end - end - else - c=objRef or {} - end - if not c.Type then - c.Type="coustomObject" - end -end -function multi:newEvent(task) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type="event" - c.Task=task or function() end - function c:Act() - if self.Task(self) then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.Task) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newAlarm(set) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type="alarm" - c.timer=self:newTimer() - c.set=set or 0 - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.set) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.timer:Get()>=self.set then - self:Pause() - self.Active=false - for i=1,#self.func do - self.func[i](self) - end - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer:Resume() - end - function c:Reset(n) - if n then self.set=n end - self:Resume() - self.timer:Reset() - end - function c:OnRing(func) - table.insert(self.func,func) - end - function c:Pause() - self.timer:Pause() - self.Parent.Pause(self) - end - if self.Type=="stack" then - c:Pause() - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - table.remove(self.Parent.Mainloop,#self.Parent.Mainloop) - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - else - c.timer:Start() - end - return c -end -function multi:newLoop(func) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type="loop" - c.Start=multi.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - for i=1,#self.func do - self.func[i](multi.clock()-self.Start,self) - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newUpdater(skip) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type="updater" - c.pos=1 - c.skip=skip or 1 - function c:Act() - if self.pos>=skip then - self.pos=0 - for i=1,#self.func do - self.func[i](self) - end - end - self.pos=self.pos+1 - end - c.OnUpdate=multi.OnMainConnect - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newStep(start,reset,count,skip) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type="step" - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newTStep(start,reset,count,set) - local c={} - if self.Type=="stack" then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type="tstep" - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=multi.clock() - c.set=set or 1 - c.funcS={} - c.Reset=c.Resume - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=multi.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if multi.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=multi.clock() - self:Resume() - end - if self.Type=="stack" then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end --- Constructors [SEMI-ACTORS] -function multi:newJob(func,name) - if not(self.Type=="mainint" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end - local c = {} - if self.Type=="int" then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Parent=self - c.Type="job" - c.trigfunc=func or function() end - function c:Act() - self:trigfunc(self) - end - table.insert(self.Jobs,{c,name}) - if self.JobRunner==nil then - self.JobRunner=self:newAlarm(self.jobUS) - self.JobRunner:OnRing(function(self) - if #self.Parent.Jobs>0 then - if self.Parent.Jobs[1] then - self.Parent.Jobs[1][1]:Act() - table.remove(self.Parent.Jobs,1) - end - end - self:Reset(self.Parent.jobUS) - end) - end -end --- Constructors [NON-ACTORS] -function multi:newWatcher(namespace,name) - local function WatcherObj(ns,n) - local c=multi:newBase() - c.Type="watcher" - c.ns=ns - c.n=n - c.cv=ns[n] - function c:OnValueChanged(func) - table.insert(self.func,func) - end - function c:Act() - if self.cv~=self.ns[self.n] then - for i=1,#self.func do - self.func[i](self,self.cv,self.ns[self.n]) - end - self.cv=self.ns[self.n] - end - end - return c - end - if type(namespace)~="table" and type(namespace)=="string" then - return WatcherObj(_G,namespace) - elseif type(namespace)=="table" and (type(name)=="string" or "number") then - return WatcherObj(namespace,name) - else - print("Warning, invalid arguments! Nothing returned!") - end -end -function multi:newTimer() - local c={} - c.Type="timer" - c.time=0 - c.count=0 - function c:Start() - self.time=multi.clock() - end - function c:Get() - return (multi.clock()-self.time)+self.count - end - c.Reset=c.Start - function c:Pause() - self.time=self:Get() - end - function c:Resume() - self.time=multi.clock()-self.time - end - function c:tofile(path) - local m=bin.new() - self.count=self.count+self:Get() - m:addBlock(self.Type) - m:addBlock(self.count) - m:tofile(path) - end - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newTrigger(func) - local c={} - c.Type="trigger" - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.trigfunc) - m:tofile(path) - end - return c -end -function multi:newConnection() - local c={} - c.Type="connector" - c.func={} - c.ID=0 - function c:Fire(...) - for i=#self.func,1,-1 do - t,e=pcall(self.func[i][1],...) - if not(t) then - print(e) - end - end - end - function c:bind(t) - self.func=t - end - function c:remove() - self.func={} - end - function c:connect(func) - self.ID=self.ID+1 - table.insert(self.func,{func,self.ID}) - return { - Link=self.func, - ID=self.ID, - remove=function(self) - for i=1,#self.Link do - if self.Link[i][2]~=nil then - if self.Link[i][2]==self.ID then - table.remove(self.Link,i) - self.remove=function() end - self.Link=nil - self.ID=nil - return true - end - end - end - end - } - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:tofile(path) - end - return c -end ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,"Start",multi.clock()) - while self.Active do - self:Do_Order() - end -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - rawset(self,"Start",multi.clock()) -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - self:Do_Order() - end -end diff --git a/mulit/oldversions/MultiManager(0.6.3).lua b/mulit/oldversions/MultiManager(0.6.3).lua deleted file mode 100644 index 5221c83..0000000 --- a/mulit/oldversions/MultiManager(0.6.3).lua +++ /dev/null @@ -1,1112 +0,0 @@ -if not bin then - print('Warning the \'bin\' library wasn\'t required! multi:tofile(path) and the multi:fromfile(path,int) features will not work!') -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -multi = {} -multi.Version={6,3,0}-- History: EventManager,EventManager+,MultiManager <-- Current -multi.help=[[ -For a list of features do print(multi.Features) -For a list of changes do print(multi.changelog) -For current version do print(multi.Version) -For current stage do print(multi.stage) -For help do print(multi.help) :D -]] -multi.stage='stable' -multi.Features="Current Version: "..multi.Version[1]..'.'..multi.Version[2]..'.'..multi.Version[3]..' '..multi.stage..[[ -MultiManager has 15 Objects: -+Events -+Alarms -+Loops -+Steps -+TSteps -+Triggers -+Tasks -+Connections -+Timers -+Jobs -+Interfaces -+Stacks -+Updaters -+Watchers -+CustomObjects - -Constructors [Runners] ----------------------- -multi:newInterface([string: FILE defualt: nil]) -multi:newStack([string: FILE defualt: nil]) - -Constructors [ACTORS] ---------------------- -multi:newEvent([function: TASK defualt: function() end]) -multi:newAlarm([number: SET defualt: 0]) -multi:newLoop([function: FUNC]) -multi:newStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SKIP defualt: 0]) -multi:newTStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SET defualt: 1]) -multi:newUpdater([number: SKIP defualt: 0]) -multi:newWatcher(table: NAMESPACE,string: NAME) -multi:newCustomObject([table: OBJREF],[string: T="process"]) - -Constructors [Semi-ACTORS] --------------------------- -multi:newJob() - -Constructors [NON-ACTORS] -------------------------- -multi:newTriggers() -multi:newTasks() -multi:newConnections() -multi:newTimers() -]] -multi.changelog=[[Changelog starts at Version 6.3.0]] -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.Children={} -multi.Paused={} -multi.Active=true -multi.Id=-1 -multi.Type='mainint' -multi.Rest=0 -multi._type=type -multi.Jobs={} -multi.queue={} -multi.jobUS=2 -multi.clock=os.clock -multi.time=os.time -multi.LinkedPath=multi -multi.range={ - getN = function(self) multi:Do_Order() self.n=self.n+self.c if self.n>self.b then self.Link:Resume() return nil end return self.n end, -} -setmetatable(multi.range,{ - __call=function(self,a,b,c) - self.c=c or 1 - self.n=a-self.c - self.a=a - self.b=b - self.Link=multi.Mainloop[multi.CID] - self.Link:Pause() - return function() return self:getN() end - end -}) --- System -function multi:Stop() - self.Active=false -end -function os.getOS() - if package.config:sub(1,1)=='\\' then - return 'windows' - else - return 'unix' - end -end -if os.getOS()=='windows' then - function os.sleep(n) - if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end - end -else - function os.sleep(n) - os.execute('sleep ' .. tonumber(n)) - end -end -function multi.executeFunction(name,...) - if type(_G[name])=='function' then - _G[name](...) - else - print('Error: Not a function') - end -end -function multi:reboot(r) - local before=collectgarbage('count') - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=='table' then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end - collectgarbage() - local after=collectgarbage('count') - print([[Before rebooting total Ram used was ]]..before..[[Kb -After rebooting total Ram used is ]]..after..[[ Kb -A total of ]]..(before-after)..[[Kb was cleaned up]]) -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:getError() - if self.error then - return self.error - end -end -function multi:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end -end -function multi:fromfile(path,int) - int=int or multi - local test2={} - local test=bin.load(path) - local tp=test:getBlock('s') - if tp=='event' then - test2=int:newEvent(test:getBlock('f')) - local t=test:getBlock('t') - for i=1,#t do - test2:OnEvent(t[i]) - end - elseif tp=='alarm' then - test2=int:newAlarm(test:getBlock('n')) - elseif tp=='loop' then - test2=int:newLoop(test:getBlock('t')[1]) - elseif tp=='step' or tp=='tstep' then - local func=test:getBlock('t') - local funcE=test:getBlock('t') - local funcS=test:getBlock('t') - local tab=test:getBlock('t') - test2=int:newStep() - table.merge(test2,tab) - test2.funcE=funcE - test2.funcS=funcS - test2.func=func - elseif tp=='trigger' then - test2=int:newTrigger(test:getBlock('f')) - elseif tp=='connector' then - test2=int:newConnection() - test2.func=test:getBlock('t') - elseif tp=='timer' then - test2=int:newTimer() - test2.count=tonumber(test:getBlock('n')) - else - print('Error: The file you selected is not a valid multi file object!') - return false - end - return test2 -end -function multi:benchMark(sec) - local temp=self:newLoop(function(t,self) - if multi.clock()-self.init>self.sec then - print(self.c..' steps in '..self.sec..' second(s)') - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=multi.clock() - temp.c=0 - return temp -end -function multi:tofile(path) - local items=self:getChildren() - io.mkDir(io.getName(path)) - for i=1,#items do - items[i]:tofile(io.getName(path)..'\\item'..item[i]..'.dat') - end - local int=bin.new() - int:addBlock('int') - int:addBlock(io.getName(path)) - int:addBlock(#self.Mainloop) - int:addBlock(self.Active) - int:addBlock(self.Rest) - int:addBlock(self.Jobs) - int:tofile() -end ---Helpers -function multi:OnMainConnect(func) - table.insert(self.func,func) -end -function multi:protect() - function self:Do_Order() - local Loop=self.Mainloop - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - local status, err=pcall(Loop[_D].Act,Loop[_D]) - if err and not(Loop[_D].error) then - Loop[_D].error=err - print(err..': Ingoring error continuing...') - end - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end - end -end -function multi:unProtect() - function self:Do_Order() - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - Loop[_D]:Act() - end - end - if self.Rest~=0 then - os.sleep(self.Rest) - end - end -end -function multi:setJobSpeed(n) - self.jobUS=n -end -function multi:hasJobs() - return #self.Jobs>0,#self.Jobs -end -function multi:getJobs() - return #self.Jobs -end -function multi:removeJob(name) - for i=#self.Jobs,1,-1 do - if self.Jobs[i][2]==name then - table.remove(self.Jobs,i) - end - end -end -function multi:FreeMainEvent() - self.func={} -end -function multi:connectFinal(func) - if self.Type=='event' then - self:OnEvent(func) - elseif self.Type=='alarm' then - self:OnRing(func) - elseif self.Type=='step' or self.Type=='tstep' then - self:OnEnd(func) - elseif self.Type=='loop' or self.Type=='updater' then - self:OnBreak(func) - else - error('No final event exists for: '..self.Type) - end -end -function multi:Break() - self:Pause() - self.Active=nil - for i=1,#self.ender do - self.ender[i](self) - end -end -function multi:OnBreak(func) - table.insert(self.ender,func) -end -function multi:isPaused() - return not(self.Active) -end -function multi:Pause(n) - if self.Type=='int' or self.Type=='mainint' then - self.Active=false - if not(n) then - local c=self:getChildren() - for i=1,#c do - c[i]:Pause() - end - else - self:hold(n) - end - else - if n==nil then - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - else - self:hold(n) - end - end -end -function multi:Resume() - if self.Type=='int' or self.Type=='mainint' then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:resurrect() - table.insert(self.Parent.Mainloop,self) - self.Active=true -end -function multi:Destroy() - if self.Type=='int' or self.Type=='mainint' then - local c=self:getChildren() - for i=1,#c do - c[i]:Destroy() - end - else - for i=1,#self.Parent.Mainloop do - if self.Parent.Mainloop[i]==self then - table.remove(self.Parent.Mainloop,i) - break - end - end - self.Active=false - end -end -function multi:hold(task) - self:Pause() - if type(task)=='number' then - local alarm=self.Parent:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - alarm:Destroy() - self:Resume() - elseif type(task)=='function' then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt:Stop() end) - while env.Active do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - env:Destroy() - self:Resume() - else - print('Error Data Type!!!') - end -end -function multi:oneTime(func,...) - if not(self.Type=='mainint' or self.Type=='int') then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end -function multi:Reset(n) - self:Resume() -end -function multi:isDone() - return self.Active~=true -end ---Constructors [CORE] -function multi:newBase(ins) - if not(self.Type=='mainint' or self.Type=='int' or self.Type=='stack') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='int' or self.Type=='stack' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.ender={} - c.Id=0 - c.PId=0 - c.Act=function() end - c.Parent=self - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - return c -end -function multi:newInterface(file) - if not(self.Type=='mainint') then error('Can only create an interface on the multi obj') return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type='int' - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.Active=true - c.Id=-1 - c.Rest=0 - c.Jobs={} - c.queue={} - c.jobUS=2 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Stop() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - if file then - multi.Cself=c - loadstring('interface=multi.Cself '..io.open(file,'rb'):read('*all'))() - end - return c -end -function multi:newStack(file) - local c=self:newInterface() - c.Type='stack' - c.last={} - c.funcE={} - if file then - multi.Cself=c - loadstring('stack=multi.Cself '..io.open(file,'rb'):read('*all'))() - end - function c:OnStackCompleted(func) - table.insert(self.funcE,func) - end - return c -end ---Constructors [ACTORS] -function multi:newCustomObject(objRef,t) - local c={} - if t=='process' then - c=self:newBase() - if type(objRef)=='table' then - table.merge(c,objRef) - end - if not c.Act then - function c:Act() - -- Empty function - end - end - else - c=objRef or {} - end - if not c.Type then - c.Type='coustomObject' - end -end -function multi:newEvent(task) - local c={} - if self.Type=='stack' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='event' - c.Task=task or function() end - function c:Act() - if self.Task(self) then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.Task) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - if self.Type=='stack' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newAlarm(set) - local c={} - if self.Type=='stack' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='alarm' - c.timer=self:newTimer() - c.set=set or 0 - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.set) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.timer:Get()>=self.set then - self:Pause() - self.Active=false - for i=1,#self.func do - self.func[i](self) - end - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer:Resume() - end - function c:Reset(n) - if n then self.set=n end - self:Resume() - self.timer:Reset() - end - function c:OnRing(func) - table.insert(self.func,func) - end - function c:Pause() - self.timer:Pause() - self.Parent.Pause(self) - end - if self.Type=='stack' then - c:Pause() - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - table.remove(self.Parent.Mainloop,#self.Parent.Mainloop) - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - else - c.timer:Start() - end - return c -end -function multi:newLoop(func) - local c={} - if self.Type=='stack' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='loop' - c.Start=multi.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - for i=1,#self.func do - self.func[i](multi.clock()-self.Start,self) - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - if self.Type=='stack' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newUpdater(skip) - local c={} - if self.Type=='stack' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='updater' - c.pos=1 - c.skip=skip or 1 - function c:Act() - if self.pos>=skip then - self.pos=0 - for i=1,#self.func do - self.func[i](self) - end - end - self.pos=self.pos+1 - end - c.OnUpdate=multi.OnMainConnect - if self.Type=='stack' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newStep(start,reset,count,skip) - local c={} - if self.Type=='stack' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type='step' - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - if self.Type=='stack' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newTStep(start,reset,count,set) - local c={} - if self.Type=='stack' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type='tstep' - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=multi.clock() - c.set=set or 1 - c.funcS={} - c.Reset=c.Resume - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=multi.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if multi.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=multi.clock() - self:Resume() - end - if self.Type=='stack' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(function(self) - if self.Parent.last==self then - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end - self:Destroy() - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end) - end - return c -end -function multi:newWatcher(namespace,name) - local function WatcherObj(ns,n) - local c=multi:newBase() - c.Type='watcher' - c.ns=ns - c.n=n - c.cv=ns[n] - function c:OnValueChanged(func) - table.insert(self.func,func) - end - function c:Act() - if self.cv~=self.ns[self.n] then - for i=1,#self.func do - self.func[i](self,self.cv,self.ns[self.n]) - end - self.cv=self.ns[self.n] - end - end - return c - end - if type(namespace)~='table' and type(namespace)=='string' then - return WatcherObj(_G,namespace) - elseif type(namespace)=='table' and (type(name)=='string' or 'number') then - return WatcherObj(namespace,name) - else - print('Warning, invalid arguments! Nothing returned!') - end -end --- Constructors [SEMI-ACTORS] -function multi:newJob(func,name) - if not(self.Type=='mainint' or self.Type=='int') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='int' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Parent=self - c.Type='job' - c.trigfunc=func or function() end - function c:Act() - self:trigfunc(self) - end - table.insert(self.Jobs,{c,name}) - if self.JobRunner==nil then - self.JobRunner=self:newAlarm(self.jobUS) - self.JobRunner:OnRing(function(self) - if #self.Parent.Jobs>0 then - if self.Parent.Jobs[1] then - self.Parent.Jobs[1][1]:Act() - table.remove(self.Parent.Jobs,1) - end - end - self:Reset(self.Parent.jobUS) - end) - end -end --- Constructors [NON-ACTORS] -function multi:newTimer() - local c={} - c.Type='timer' - c.time=0 - c.count=0 - function c:Start() - self.time=multi.clock() - end - function c:Get() - return (multi.clock()-self.time)+self.count - end - c.Reset=c.Start - function c:Pause() - self.time=self:Get() - end - function c:Resume() - self.time=multi.clock()-self.time - end - function c:tofile(path) - local m=bin.new() - self.count=self.count+self:Get() - m:addBlock(self.Type) - m:addBlock(self.count) - m:tofile(path) - end - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newTrigger(func) - local c={} - c.Type='trigger' - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.trigfunc) - m:tofile(path) - end - return c -end -function multi:newConnection() - local c={} - c.Type='connector' - c.func={} - c.ID=0 - function c:Fire(...) - for i=#self.func,1,-1 do - t,e=pcall(self.func[i][1],...) - if not(t) then - print(e) - end - end - end - function c:bind(t) - self.func=t - end - function c:remove() - self.func={} - end - function c:connect(func) - self.ID=self.ID+1 - table.insert(self.func,{func,self.ID}) - return { - Link=self.func, - ID=self.ID, - remove=function(self) - for i=1,#self.Link do - if self.Link[i][2]~=nil then - if self.Link[i][2]==self.ID then - table.remove(self.Link,i) - self.remove=function() end - self.Link=nil - self.ID=nil - return true - end - end - end - end - } - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:tofile(path) - end - return c -end ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',multi.clock()) - while self.Active do - self:Do_Order() - end -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - rawset(self,'Start',multi.clock()) -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - self:Do_Order() - end -end diff --git a/mulit/oldversions/MultiManager(1.0.0).lua b/mulit/oldversions/MultiManager(1.0.0).lua deleted file mode 100644 index efd1991..0000000 --- a/mulit/oldversions/MultiManager(1.0.0).lua +++ /dev/null @@ -1,1375 +0,0 @@ -if not bin then - print('Warning the \'bin\' library wasn\'t required! multi:tofile(path) and the multi:fromfile(path,int) features will not work!') -end -if table.unpack then - unpack=table.unpack -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -multi = {} -multi.Version={'A',0,0}-- History: EventManager,EventManager+,MultiManager <-- Current After 6.3.0 Versioning scheme was altered. A.0.0 -multi.help=[[ -For a list of features do print(multi.Features) -For a list of changes do print(multi.changelog) -For current version do print(multi.Version) -For current stage do print(multi.stage) -For help do print(multi.help) :D -]] -multi.stage='stable' -multi.Features='Current Version: '..multi.Version[1]..'.'..multi.Version[2]..'.'..multi.Version[3]..' '..multi.stage..[[ -MultiManager has 19 Objects: -+Events -+Alarms -+Loops -+Steps -+TSteps -+Triggers -+Tasks -+Connections -+Timers -+Jobs -+Interfaces -+Conditions -+Ranges -+Threads -+Functions -+Queuers -+Updaters -+Watchers -+CustomObjects - -Constructors [Runners] ----------------------- Note: multi is the main Processor Obj It cannot be paused or destroyed (kinda) -intObj=multi:newProcessor([string: FILE defualt: nil]) -intObj=multi:newQueuer([string: FILE defualt: nil]) - -Constructors [ACTORS] ---------------------- Note: everything is a multiObj! -eventObj=multi:newEvent([function: TASK defualt: function() end]) -alarmObj=multi:newAlarm([number: SET defualt: 0]) -loopObj=multi:newLoop([function: FUNC]) -stepObj=multi:newStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SKIP defualt: 0]) -tstepObj=multi:newTStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SET defualt: 1]) -updaterObj=multi:newUpdater([number: SKIP defualt: 0]) -watcherObj=multi:newWatcher(table: NAMESPACE,string: NAME) -multiObj=multi:newCustomObject([table: OBJREF],[string: T='process']) -void=multi:newThread(string: name,function: func) - -Constructors [Semi-ACTORS] --------------------------- -multi:newJob(function: func,[string: name]) -multi:newRange(number: a,number: b,[number: c]) -multi:newCondition(func) - -Constructors [NON-ACTORS] -------------------------- -multi:newTrigger(function: func) -multi:newTask(function: func) -multi:newConnection() -multi:newTimer() -multi:newFunction(function: func) -]] -multi.changelog=[[Changelog starts at Version A.0.0 - -]] -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.ender={} -multi.Children={} -multi.Paused={} -multi.Active=true -multi.fps=60 -multi.Id=-1 -multi.Type='mainprocess' -multi.Rest=0 -multi._type=type -multi.Jobs={} -multi.queue={} -multi.jobUS=2 -multi.clock=os.clock -multi.time=os.time -multi.LinkedPath=multi -multi.queuefinal=function(self) - self:Destroy() - if self.Parent.Mainloop[#self.Parent.Mainloop] then - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - else - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end -end ---Do not change these ever...Any other number will not work (Unless you are using enablePriority2() then change can be made. Just ensure that Priority_Idle is the greatest and Priority_Core is 1!) -multi.Priority_Core=1 -multi.Priority_High=4 -multi.Priority_Above_Normal=16 -multi.Priority_Normal=64 -multi.Priority_Below_Normal=256 -multi.Priority_Low=1024 -multi.Priority_Idle=4096 -multi.PList={multi.Priority_Core,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Idle} -multi.PStep=1 ---^^^^ -multi.PriorityTick=1 -- Between 1 and 4 any greater and problems arise -multi.Priority=multi.Priority_Core -function multi:setDomainName(name) - self[name]={} -end -function multi:linkDomain(name) - return self[name] -end -function multi:_Pause() - self.Active=false -end -function multi:setPriority(s) - if type(s)==number then - self.Priority=s - elseif type(s)=='string' then - if s:lower()=='core' or s:lower()=='c' then - self.Priority=self.Priority_Core - elseif s:lower()=='high' or s:lower()=='h' then - self.Priority=self.Priority_High - elseif s:lower()=='above' or s:lower()=='an' then - self.Priority=self.Priority_Above_Normal - elseif s:lower()=='normal' or s:lower()=='n' then - self.Priority=self.Priority_Normal - elseif s:lower()=='below' or s:lower()=='bn' then - self.Priority=self.Priority_Below_Normal - elseif s:lower()=='low' or s:lower()=='l' then - self.Priority=self.Priority_Low - elseif s:lower()=='idle' or s:lower()=='i' then - self.Priority=self.Priority_Idle - end - end -end --- System -function os.getOS() - if package.config:sub(1,1)=='\\' then - return 'windows' - else - return 'unix' - end -end -if os.getOS()=='windows' then - function os.sleep(n) - if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end - end -else - function os.sleep(n) - os.execute('sleep ' .. tonumber(n)) - end -end -function multi:getParentProcess() - return self.Mainloop[self.CID] -end -function multi:Stop() - self.Active=false -end -function multi:condition(cond) - if not self.CD then - self:Pause() - self.held=true - self.CD=cond.condition - elseif not(cond.condition()) then - self.held=false - self:Resume() - self.CD=nil - return false - end - self.Parent:Do_Order() - return true -end -function multi:isHeld() - return self.held -end -function multi.executeFunction(name,...) - if type(_G[name])=='function' then - _G[name](...) - else - print('Error: Not a function') - end -end -function multi:waitFor(obj) - self:hold(function() return obj:isActive() end) -end -function multi:reboot(r) - local before=collectgarbage('count') - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=='table' then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end - collectgarbage() - local after=collectgarbage('count') - print([[Before rebooting total Ram used was ]]..before..[[Kb -After rebooting total Ram used is ]]..after..[[ Kb -A total of ]]..(before-after)..[[Kb was cleaned up]]) -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:getError() - if self.error then - return self.error - end -end -function multi:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:enablePriority() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PList[PS.PStep])%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>7 then - PS.PStep=1 - end - end -end -function multi:enablePriority2() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PStep)%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>self.Priority_Idle then - PS.PStep=1 - end - end -end -multi.disablePriority=multi.unProtect -function multi:fromfile(path,int) - int=int or self - local test2={} - local test=bin.load(path) - local tp=test:getBlock('s') - if tp=='event' then - test2=int:newEvent(test:getBlock('f')) - local t=test:getBlock('t') - for i=1,#t do - test2:OnEvent(t[i]) - end - elseif tp=='alarm' then - test2=int:newAlarm(test:getBlock('n')) - elseif tp=='loop' then - test2=int:newLoop(test:getBlock('t')[1]) - elseif tp=='step' or tp=='tstep' then - local func=test:getBlock('t') - local funcE=test:getBlock('t') - local funcS=test:getBlock('t') - local tab=test:getBlock('t') - test2=int:newStep() - table.merge(test2,tab) - test2.funcE=funcE - test2.funcS=funcS - test2.func=func - elseif tp=='trigger' then - test2=int:newTrigger(test:getBlock('f')) - elseif tp=='connector' then - test2=int:newConnection() - test2.func=test:getBlock('t') - elseif tp=='timer' then - test2=int:newTimer() - test2.count=tonumber(test:getBlock('n')) - else - print('Error: The file you selected is not a valid multi file object!') - return false - end - return test2 -end -function multi:benchMark(sec,p) - local temp=self:newLoop(function(t,self) - if self.clock()-self.init>self.sec then - print(self.c..' steps in '..self.sec..' second(s)') - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - temp.Priority=p or 1 - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=self.clock() - temp.c=0 - return temp -end -function multi:tofile(path) - local items=self:getChildren() - io.mkDir(io.getName(path)) - for i=1,#items do - items[i]:tofile(io.getName(path)..'\\item'..item[i]..'.dat') - end - local int=bin.new() - int:addBlock('process') - int:addBlock(io.getName(path)) - int:addBlock(#self.Mainloop) - int:addBlock(self.Active) - int:addBlock(self.Rest) - int:addBlock(self.Jobs) - int:tofile() -end -function multi.startFPSMonitior() - if not multi.runFPS then - multi.doFPS(s) - multi.runFPS=true - end -end -function multi.doFPS(s) - multi:benchMark(1):OnBench(doFPS) - if s then - multi.fps=s - end -end ---Helpers -function multi:OnMainConnect(func) - table.insert(self.func,func) -end -function multi:protect() - function self:Do_Order() - local Loop=self.Mainloop - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - self.CID=_D - if Loop[_D].Active then - local status, err=pcall(Loop[_D].Act,Loop[_D]) - if err and Loop[_D].error=="" then - Loop[_D].error=err - self.OnError:Fire(err,Loop[_D]) - end - end - end - end - end -end -function multi:unProtect() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:setJobSpeed(n) - self.jobUS=n -end -function multi:hasJobs() - return #self.Jobs>0,#self.Jobs -end -function multi:getJobs() - return #self.Jobs -end -function multi:removeJob(name) - for i=#self.Jobs,1,-1 do - if self.Jobs[i][2]==name then - table.remove(self.Jobs,i) - end - end -end -function multi:FreeMainEvent() - self.func={} -end -function multi:connectFinal(func) - if self.Type=='event' then - self:OnEvent(func) - elseif self.Type=='alarm' then - self:OnRing(func) - elseif self.Type=='step' or self.Type=='tstep' then - self:OnEnd(func) - else - print("Warning!!! "..self.Type.." doesn't contain a Final Connection State! Use "..self.Type..":Break(function) to trigger it's final event!") - self:OnBreak(func) - end -end -function multi:Break() - self:Pause() - self.Active=nil - for i=1,#self.ender do - if self.ender[i] then - self.ender[i](self) - end - end -end -function multi:OnBreak(func) - table.insert(self.ender,func) -end -function multi:isPaused() - return not(self.Active) -end -function multi:isActive() - return self.Active -end -function multi:getType() - return self.Type -end -function multi:Sleep(n) - self:hold(n) -end -function multi:Pause() - if self.Type=='mainprocess' then - print("You cannot pause the main process. Doing so will stop all methods and freeze your program! However if you still want to use multi:_Pause()") - else - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - end -end -function multi:Resume() - if self.Type=='process' or self.Type=='mainprocess' then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:resurrect() - table.insert(self.Parent.Mainloop,self) - self.Active=true -end -function multi:Destroy() - if self.Type=='process' or self.Type=='mainprocess' then - local c=self:getChildren() - for i=1,#c do - self.OnObjectDestroyed:Fire(c[i]) - c[i]:Destroy() - end - else - for i=1,#self.Parent.Mainloop do - if self.Parent.Mainloop[i]==self then - self.Parent.OnObjectDestroyed:Fire(self) - table.remove(self.Parent.Mainloop,i) - break - end - end - self.Active=false - end -end - -function multi:hold(task) - self:Pause() - self.held=true - if type(task)=='number' then - local alarm=self.Parent:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - alarm:Destroy() - self:Resume() - self.held=false - elseif type(task)=='function' then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt.Active=false end) - while env.Active do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - env:Destroy() - self:Resume() - self.held=false - else - print('Error Data Type!!!') - end -end -function multi:oneTime(func,...) - if not(self.Type=='mainprocess' or self.Type=='process') then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end -function multi:Reset(n) - self:Resume() -end -function multi:isDone() - return self.Active~=true -end -function multi:create(ref) - multi.OnObjectCreated:Fire(ref) -end ---Constructors [CORE] -function multi:newBase(ins) - if not(self.Type=='mainprocess' or self.Type=='process' or self.Type=='queue') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='process' or self.Type=='queue' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.ender={} - c.Id=0 - c.PId=0 - c.Act=function() end - c.Parent=self - c.error="" - c.held=false - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - return c -end -function multi:newProcess(file) - if not(self.Type=='mainprocess') then error('Can only create an interface on the multi obj') return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type='process' - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.Active=true - c.Id=-1 - c.Rest=0 - c.Jobs={} - c.queue={} - c.jobUS=2 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Pause() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - if file then - self.Cself=c - loadstring('local interface=multi.Cself '..io.open(file,'rb'):read('*all'))() - end - self:create(c) - return c -end -function multi:newQueuer(file) - local c=self:newProcess() - c.Type='queue' - c.last={} - c.funcE={} - function c:OnQueueCompleted(func) - table.insert(self.funcE,func) - end - if file then - self.Cself=c - loadstring('local queue=multi.Cself '..io.open(file,'rb'):read('*all'))() - end - self:create(c) - return c -end ---Constructors [ACTORS] -function multi:newCustomObject(objRef,t) - local c={} - if t=='process' then - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - print("This Custom Object was created on a queue! Ensure that it has a way to end! All objects have a obj:Break() method!") - else - c=self:newBase() - end - if type(objRef)=='table' then - table.merge(c,objRef) - end - if not c.Act then - function c:Act() - -- Empty function - end - end - else - c=objRef or {} - end - if not c.Type then - c.Type='coustomObject' - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newEvent(task) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='event' - c.Task=task or function() end - function c:Act() - if self.Task(self) then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.Task) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newAlarm(set) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='alarm' - c.Priority=self.Priority_Low - c.timer=self:newTimer() - c.set=set or 0 - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.set) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.timer:Get()>=self.set then - self:Pause() - self.Active=false - for i=1,#self.func do - self.func[i](self) - end - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer:Resume() - end - function c:Reset(n) - if n then self.set=n end - self:Resume() - self.timer:Reset() - end - function c:OnRing(func) - table.insert(self.func,func) - end - function c:Pause() - self.timer:Pause() - self.Parent.Pause(self) - end - if self.Type=='queue' then - c:Pause() - c:connectFinal(multi.queuefinal) - else - c.timer:Start() - end - self:create(c) - return c -end -function multi:newLoop(func) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='loop' - c.Start=self.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - for i=1,#self.func do - self.func[i](self.Parent.clock()-self.Start,self) - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newUpdater(skip) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='updater' - c.pos=1 - c.skip=skip or 1 - function c:Act() - if self.pos>=self.skip then - self.pos=0 - for i=1,#self.func do - self.func[i](self) - end - end - self.pos=self.pos+1 - end - function c:setSkip(n) - self.skip=n - end - c.OnUpdate=self.OnMainConnect - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newStep(start,reset,count,skip) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type='step' - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self~=nil then - if self.Active then - if self.spos==0 then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newTStep(start,reset,count,set) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type='tstep' - c.Priority=self.Priority_Low - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=self.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=self.start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=self.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=self.clock() - self:Resume() - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newWatcher(namespace,name) - local function WatcherObj(ns,n) - if self.Type=='queue' then - print("Cannot create a watcher on a queue! Creating on 'multi' instead!") - self=multi - end - local c=self:newBase() - c.Type='watcher' - c.ns=ns - c.n=n - c.cv=ns[n] - function c:OnValueChanged(func) - table.insert(self.func,func) - end - function c:Act() - if self.cv~=self.ns[self.n] then - for i=1,#self.func do - self.func[i](self,self.cv,self.ns[self.n]) - end - self.cv=self.ns[self.n] - end - end - self:create(c) - return c - end - if type(namespace)~='table' and type(namespace)=='string' then - return WatcherObj(_G,namespace) - elseif type(namespace)=='table' and (type(name)=='string' or 'number') then - return WatcherObj(namespace,name) - else - print('Warning, invalid arguments! Nothing returned!') - end -end -function multi:newThread(name,func) - local c={} - c.ref={} - c.Name=name - c.thread=coroutine.create(func) - c.sleep=1 - c.firstRunDone=false - c.timer=multi.scheduler:newTimer() - c.ref.Globals=self:linkDomain("Globals") - function c.ref:send(name,val) - ret=coroutine.yield({Name=name,Value=val}) - self:syncGlobals(ret) - end - function c.ref:get(name) - return self.Globals[name] - end - function c.ref:kill() - err=coroutine.yield({"_kill_"}) - if err then - error("Failed to kill a thread! Exiting...") - end - end - function c.ref:sleep(n) - n = tonumber(n) or 0 - ret=coroutine.yield({"_sleep_",n}) - self:syncGlobals(ret) - end - function c.ref:syncGlobals(v) - self.Globals=v - end - table.insert(self:linkDomain("Threads"),c) - if not multi.scheduler:isActive() then - multi.scheduler:Resume() - end -end --- Constructors [SEMI-ACTORS] -function multi:newJob(func,name) - if not(self.Type=='mainprocess' or self.Type=='process') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='process' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Parent=self - c.Type='job' - c.trigfunc=func or function() end - function c:Act() - self:trigfunc(self) - end - table.insert(self.Jobs,{c,name}) - if self.JobRunner==nil then - self.JobRunner=self:newAlarm(self.jobUS) - self.JobRunner:OnRing(function(self) - if #self.Parent.Jobs>0 then - if self.Parent.Jobs[1] then - self.Parent.Jobs[1][1]:Act() - table.remove(self.Parent.Jobs,1) - end - end - self:Reset(self.Parent.jobUS) - end) - end -end -function multi:newRange() - selflink=self - local temp={ - getN = function(self) selflink:Do_Order() self.n=self.n+self.c if self.n>self.b then self.Link.held=false self.Link:Resume() return nil end return self.n end, - } - setmetatable(temp,{ - __call=function(self,a,b,c) - self.c=c or 1 - self.n=a-self.c - self.a=a - self.b=b - self.Link=selflink.Parent.Mainloop[selflink.CID] - self.Link:Pause() - self.Link.held=true - return function() return self:getN() end - end - }) - self:create(temp) - return temp -end -function multi:newCondition(func) - local c={['condition']=func} - self:create(c) - return c -end --- Constructors [NON-ACTORS] -function multi:newFunction(func) - local c={} - c.func=func - mt={ - __index=multi, - __call=function(self,...) if self.Active then return self:func(...) end local t={...} return "PAUSED" end - } - c.Parent=self - function c:Pause() - self.Active=false - end - function c:Resume() - self.Active=true - end - setmetatable(c,mt) - self:create(c) - return c -end -function multi:newTimer() - local c={} - c.Type='timer' - c.time=0 - c.count=0 - function c:Start() - self.time=os.clock() - end - function c:Get() - return (os.clock()-self.time)+self.count - end - c.Reset=c.Start - function c:Pause() - self.time=self:Get() - end - function c:Resume() - self.time=os.clock()-self.time - end - function c:tofile(path) - local m=bin.new() - self.count=self.count+self:Get() - m:addBlock(self.Type) - m:addBlock(self.count) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newTrigger(func) - local c={} - c.Type='trigger' - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.trigfunc) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newConnection(protect) - local c={} - c.Type='connector' - c.func={} - c.ID=0 - c.protect=protect or true - function c:Fire(...) - local ret={} - for i=#self.func,1,-1 do - if self.protect then - local temp={pcall(self.func[i][1],...)} - if temp[1] then - table.remove(temp,1) - table.insert(ret,temp) - else - print(temp[2]) - end - else - table.insert(ret,{self.func[i][1](...)}) - end - end - return ret - end - function c:bind(t) - self.func=t - end - function c:remove() - self.func={} - end - function c:connect(func) - self.ID=self.ID+1 - table.insert(self.func,1,{func,self.ID}) - return { - Link=self.func, - ID=self.ID, - remove=function(self) - for i=1,#self.Link do - if self.Link[i][2]~=nil then - if self.Link[i][2]==self.ID then - table.remove(self.Link,i) - self.remove=function() end - self.Link=nil - self.ID=nil - return true - end - end - end - end - } - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:tofile(path) - end - return c -end -multi.OnObjectCreated=multi:newConnection() -multi.OnObjectDestroyed=multi:newConnection() ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - self:Do_Order() - end - print("Did you call multi:_Pause()? This method should not be used when using multi:mainloop()! There is now no way to restart the multiManager, except by using multi:reboot() and calling multi:mainloop() again or by using multi:uManager()") -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - rawset(self,'Start',self.clock()) -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - function self:uManager(dt) - self:Do_Order() - end - self:Do_Order() - end -end ---Thread Setup Stuff -multi:setDomainName("Threads") -multi:setDomainName("Globals") --- Scheduler -multi.scheduler=multi:newUpdater() -multi.scheduler.Type="scheduler" -function multi.scheduler:setStep(n) - self.skip=tonumber(n) or 24 -end -multi.scheduler.Threads=multi:linkDomain("Threads") -multi.scheduler.Globals=multi:linkDomain("Globals") -multi.scheduler:OnUpdate(function(self) - for i=#self.Threads,1,-1 do - ret={} - if coroutine.status(self.Threads[i].thread)=="dead" then - table.remove(self.Threads,i) - else - if self.Threads[i].timer:Get()>=self.Threads[i].sleep then - if self.Threads[i].firstRunDone==false then - self.Threads[i].firstRunDone=true - self.Threads[i].timer:Start() - _,ret=coroutine.resume(self.Threads[i].thread,self.Threads[i].ref) - else - _,ret=coroutine.resume(self.Threads[i].thread,self.Globals) - end - if ret==true or ret==false then - print("Thread Ended!!!") - ret={} - end - end - if ret then - if ret[1]=="_kill_" then - table.remove(self.Threads,i) - elseif ret[1]=="_sleep_" then - self.Threads[i].timer:Reset() - self.Threads[i].sleep=ret[2] - elseif ret.Name then - self.Globals[ret.Name]=ret.Value - end - end - end - end -end) -multi.scheduler:setStep() -multi.scheduler:Pause() -multi.OnError=multi:newConnection() diff --git a/mulit/oldversions/MultiManager(1.0.1).lua b/mulit/oldversions/MultiManager(1.0.1).lua deleted file mode 100644 index d3a2dd2..0000000 --- a/mulit/oldversions/MultiManager(1.0.1).lua +++ /dev/null @@ -1,1391 +0,0 @@ -if not bin then - print('Warning the \'bin\' library wasn\'t required! multi:tofile(path) and the multi:fromfile(path,int) features will not work!') -end -if table.unpack then - unpack=table.unpack -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -multi = {} -multi.Version={'A',0,1}-- History: EventManager,EventManager+,MultiManager <-- Current After 6.3.0 Versioning scheme was altered. A.0.0 -multi.help=[[ -For a list of features do print(multi.Features) -For a list of changes do print(multi.changelog) -For current version do print(multi.Version) -For current stage do print(multi.stage) -For help do print(multi.help) :D -]] -multi.stage='stable' -multi.Features='Current Version: '..multi.Version[1]..'.'..multi.Version[2]..'.'..multi.Version[3]..' '..multi.stage..[[ -MultiManager has 19 Objects: # indicates most commonly used 1-19 1 being the most used by me -+Events #7 -+Alarms #2 -+Loops #3 -+Steps #4 -+TSteps #6 -+Triggers #16 -+Tasks #12 -+Connections #1 -- This is a rather new feature of this library, but has become the most useful for async handling. Knowing this is already 50% of this library -+Timers #14 -- this was tricky because these make up both Alarms and TSteps, but in purly using this standalone is almost non existent -+Jobs #11 -+Process #10 -+Conditions #15 -+Ranges #8 -+Threads #13 -+Functions #5 -+Queuers #17 -+Updaters #9 -+Watchers #18 -+CustomObjects #19 - -Constructors [Runners] ----------------------- Note: multi is the main Processor Obj It cannot be paused or destroyed (kinda) -intObj=multi:newProcess([string: FILE defualt: nil]) -intObj=multi:newQueuer([string: FILE defualt: nil]) - -Constructors [ACTORS] ---------------------- Note: everything is a multiObj! -eventObj=multi:newEvent([function: TASK defualt: function() end]) -alarmObj=multi:newAlarm([number: SET defualt: 0]) -loopObj=multi:newLoop([function: FUNC]) -stepObj=multi:newStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SKIP defualt: 0]) -tstepObj=multi:newTStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SET defualt: 1]) -updaterObj=multi:newUpdater([number: SKIP defualt: 0]) -watcherObj=multi:newWatcher(table: NAMESPACE,string: NAME) -multiObj=multi:newCustomObject([table: OBJREF],[string: T='process']) -void=multi:newThread(string: name,function: func) - -Constructors [Semi-ACTORS] --------------------------- -multi:newJob(function: func,[string: name]) -multi:newRange(number: a,number: b,[number: c]) -multi:newCondition(func) - -Constructors [NON-ACTORS] -------------------------- -multi:newTrigger(function: func) -multi:newTask(function: func) -multi:newConnection() -multi:newTimer() -multi:newFunction(function: func) -]] -multi.changelog=[[Changelog starts at Version A.0.0 -New in A.0.0 - Nothing really however a changelog will now be recorded! Feel free to remove this extra strings if space is a requriment - version.major.minor -New in A.1.0 - Changed: multi:newConnection(protect) method - Changed the way you are able to interact with it by adding the __call metamethod - Old usage: - - OnUpdate=multi:newConnection() - OnUpdate:connect(function(...) - print("Updating",...) - end) - OnUpdate:Fire(1,2,3) - - New usage: notice that connect is no longer needed! Both ways still work! and always will work :) - - OnUpdate=multi:newConnection() - OnUpdate(function(...) - print("Updating",...) - end) - OnUpdate:Fire(1,2,3) -]] -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.ender={} -multi.Children={} -multi.Paused={} -multi.Active=true -multi.fps=60 -multi.Id=-1 -multi.Type='mainprocess' -multi.Rest=0 -multi._type=type -multi.Jobs={} -multi.queue={} -multi.jobUS=2 -multi.clock=os.clock -multi.time=os.time -multi.LinkedPath=multi -multi.queuefinal=function(self) - self:Destroy() - if self.Parent.Mainloop[#self.Parent.Mainloop] then - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - else - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end -end ---Do not change these ever...Any other number will not work (Unless you are using enablePriority2() then change can be made. Just ensure that Priority_Idle is the greatest and Priority_Core is 1!) -multi.Priority_Core=1 -multi.Priority_High=4 -multi.Priority_Above_Normal=16 -multi.Priority_Normal=64 -multi.Priority_Below_Normal=256 -multi.Priority_Low=1024 -multi.Priority_Idle=4096 -multi.PList={multi.Priority_Core,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Idle} -multi.PStep=1 ---^^^^ -multi.PriorityTick=1 -- Between 1 and 4 any greater and problems arise -multi.Priority=multi.Priority_Core -function multi:setDomainName(name) - self[name]={} -end -function multi:linkDomain(name) - return self[name] -end -function multi:_Pause() - self.Active=false -end -function multi:setPriority(s) - if type(s)==number then - self.Priority=s - elseif type(s)=='string' then - if s:lower()=='core' or s:lower()=='c' then - self.Priority=self.Priority_Core - elseif s:lower()=='high' or s:lower()=='h' then - self.Priority=self.Priority_High - elseif s:lower()=='above' or s:lower()=='an' then - self.Priority=self.Priority_Above_Normal - elseif s:lower()=='normal' or s:lower()=='n' then - self.Priority=self.Priority_Normal - elseif s:lower()=='below' or s:lower()=='bn' then - self.Priority=self.Priority_Below_Normal - elseif s:lower()=='low' or s:lower()=='l' then - self.Priority=self.Priority_Low - elseif s:lower()=='idle' or s:lower()=='i' then - self.Priority=self.Priority_Idle - end - end -end --- System -function os.getOS() - if package.config:sub(1,1)=='\\' then - return 'windows' - else - return 'unix' - end -end -if os.getOS()=='windows' then - function os.sleep(n) - if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end - end -else - function os.sleep(n) - os.execute('sleep ' .. tonumber(n)) - end -end -function multi:getParentProcess() - return self.Mainloop[self.CID] -end -function multi:Stop() - self.Active=false -end -function multi:condition(cond) - if not self.CD then - self:Pause() - self.held=true - self.CD=cond.condition - elseif not(cond.condition()) then - self.held=false - self:Resume() - self.CD=nil - return false - end - self.Parent:Do_Order() - return true -end -function multi:isHeld() - return self.held -end -function multi.executeFunction(name,...) - if type(_G[name])=='function' then - _G[name](...) - else - print('Error: Not a function') - end -end -function multi:waitFor(obj) - self:hold(function() return obj:isActive() end) -end -function multi:reboot(r) - local before=collectgarbage('count') - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=='table' then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end - collectgarbage() - local after=collectgarbage('count') - print([[Before rebooting total Ram used was ]]..before..[[Kb -After rebooting total Ram used is ]]..after..[[ Kb -A total of ]]..(before-after)..[[Kb was cleaned up]]) -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:getError() - if self.error then - return self.error - end -end -function multi:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:enablePriority() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PList[PS.PStep])%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>7 then - PS.PStep=1 - end - end -end -function multi:enablePriority2() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PStep)%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>self.Priority_Idle then - PS.PStep=1 - end - end -end -multi.disablePriority=multi.unProtect -function multi:fromfile(path,int) - int=int or self - local test2={} - local test=bin.load(path) - local tp=test:getBlock('s') - if tp=='event' then - test2=int:newEvent(test:getBlock('f')) - local t=test:getBlock('t') - for i=1,#t do - test2:OnEvent(t[i]) - end - elseif tp=='alarm' then - test2=int:newAlarm(test:getBlock('n')) - elseif tp=='loop' then - test2=int:newLoop(test:getBlock('t')[1]) - elseif tp=='step' or tp=='tstep' then - local func=test:getBlock('t') - local funcE=test:getBlock('t') - local funcS=test:getBlock('t') - local tab=test:getBlock('t') - test2=int:newStep() - table.merge(test2,tab) - test2.funcE=funcE - test2.funcS=funcS - test2.func=func - elseif tp=='trigger' then - test2=int:newTrigger(test:getBlock('f')) - elseif tp=='connector' then - test2=int:newConnection() - test2.func=test:getBlock('t') - elseif tp=='timer' then - test2=int:newTimer() - test2.count=tonumber(test:getBlock('n')) - else - print('Error: The file you selected is not a valid multi file object!') - return false - end - return test2 -end -function multi:benchMark(sec,p) - local temp=self:newLoop(function(t,self) - if self.clock()-self.init>self.sec then - print(self.c..' steps in '..self.sec..' second(s)') - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - temp.Priority=p or 1 - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=self.clock() - temp.c=0 - return temp -end -function multi:tofile(path) - local items=self:getChildren() - io.mkDir(io.getName(path)) - for i=1,#items do - items[i]:tofile(io.getName(path)..'\\item'..item[i]..'.dat') - end - local int=bin.new() - int:addBlock('process') - int:addBlock(io.getName(path)) - int:addBlock(#self.Mainloop) - int:addBlock(self.Active) - int:addBlock(self.Rest) - int:addBlock(self.Jobs) - int:tofile() -end -function multi.startFPSMonitior() - if not multi.runFPS then - multi.doFPS(s) - multi.runFPS=true - end -end -function multi.doFPS(s) - multi:benchMark(1):OnBench(doFPS) - if s then - multi.fps=s - end -end ---Helpers -function multi:OnMainConnect(func) - table.insert(self.func,func) -end -function multi:protect() - function self:Do_Order() - local Loop=self.Mainloop - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - self.CID=_D - local status, err=pcall(Loop[_D].Act,Loop[_D]) - if err and not(Loop[_D].error) then - Loop[_D].error=err - self.OnError:Fire(err,Loop[_D]) - end - end - end - end -end -function multi:unProtect() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:setJobSpeed(n) - self.jobUS=n -end -function multi:hasJobs() - return #self.Jobs>0,#self.Jobs -end -function multi:getJobs() - return #self.Jobs -end -function multi:removeJob(name) - for i=#self.Jobs,1,-1 do - if self.Jobs[i][2]==name then - table.remove(self.Jobs,i) - end - end -end -function multi:FreeMainEvent() - self.func={} -end -function multi:connectFinal(func) - if self.Type=='event' then - self:OnEvent(func) - elseif self.Type=='alarm' then - self:OnRing(func) - elseif self.Type=='step' or self.Type=='tstep' then - self:OnEnd(func) - else - print("Warning!!! "..self.Type.." doesn't contain a Final Connection State! Use "..self.Type..":Break(function) to trigger it's final event!") - self:OnBreak(func) - end -end -function multi:Break() - self:Pause() - self.Active=nil - for i=1,#self.ender do - if self.ender[i] then - self.ender[i](self) - end - end -end -function multi:OnBreak(func) - table.insert(self.ender,func) -end -function multi:isPaused() - return not(self.Active) -end -function multi:isActive() - return self.Active -end -function multi:getType() - return self.Type -end -function multi:Sleep(n) - self:hold(n) -end -function multi:Pause() - if self.Type=='mainprocess' then - print("You cannot pause the main process. Doing so will stop all methods and freeze your program! However if you still want to use multi:_Pause()") - else - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - end -end -function multi:Resume() - if self.Type=='process' or self.Type=='mainprocess' then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:resurrect() - table.insert(self.Parent.Mainloop,self) - self.Active=true -end -function multi:Destroy() - if self.Type=='process' or self.Type=='mainprocess' then - local c=self:getChildren() - for i=1,#c do - self.OnObjectDestroyed:Fire(c[i]) - c[i]:Destroy() - end - else - for i=1,#self.Parent.Mainloop do - if self.Parent.Mainloop[i]==self then - self.Parent.OnObjectDestroyed:Fire(self) - table.remove(self.Parent.Mainloop,i) - break - end - end - self.Active=false - end -end - -function multi:hold(task) - self:Pause() - self.held=true - if type(task)=='number' then - local alarm=self.Parent:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - alarm:Destroy() - self:Resume() - self.held=false - elseif type(task)=='function' then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt.Active=false end) - while env.Active do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - env:Destroy() - self:Resume() - self.held=false - else - print('Error Data Type!!!') - end -end -function multi:oneTime(func,...) - if not(self.Type=='mainprocess' or self.Type=='process') then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end -function multi:Reset(n) - self:Resume() -end -function multi:isDone() - return self.Active~=true -end -function multi:create(ref) - multi.OnObjectCreated:Fire(ref) -end ---Constructors [CORE] -function multi:newBase(ins) - if not(self.Type=='mainprocess' or self.Type=='process' or self.Type=='queue') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='process' or self.Type=='queue' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.ender={} - c.Id=0 - c.PId=0 - c.Act=function() end - c.Parent=self - c.held=false - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - return c -end -function multi:newProcess(file) - if not(self.Type=='mainprocess') then error('Can only create an interface on the multi obj') return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type='process' - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.Active=true - c.Id=-1 - c.Rest=0 - c.Jobs={} - c.queue={} - c.jobUS=2 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Pause() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - if file then - self.Cself=c - loadstring('local interface=multi.Cself '..io.open(file,'rb'):read('*all'))() - end - self:create(c) - return c -end -function multi:newQueuer(file) - local c=self:newProcess() - c.Type='queue' - c.last={} - c.funcE={} - function c:OnQueueCompleted(func) - table.insert(self.funcE,func) - end - if file then - self.Cself=c - loadstring('local queue=multi.Cself '..io.open(file,'rb'):read('*all'))() - end - self:create(c) - return c -end ---Constructors [ACTORS] -function multi:newCustomObject(objRef,t) - local c={} - if t=='process' then - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - print("This Custom Object was created on a queue! Ensure that it has a way to end! All objects have a obj:Break() method!") - else - c=self:newBase() - end - if type(objRef)=='table' then - table.merge(c,objRef) - end - if not c.Act then - function c:Act() - -- Empty function - end - end - else - c=objRef or {} - end - if not c.Type then - c.Type='coustomObject' - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newEvent(task) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='event' - c.Task=task or function() end - function c:Act() - if self.Task(self) then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.Task) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newAlarm(set) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='alarm' - c.Priority=self.Priority_Low - c.timer=self:newTimer() - c.set=set or 0 - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.set) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.timer:Get()>=self.set then - self:Pause() - self.Active=false - for i=1,#self.func do - self.func[i](self) - end - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer:Resume() - end - function c:Reset(n) - if n then self.set=n end - self:Resume() - self.timer:Reset() - end - function c:OnRing(func) - table.insert(self.func,func) - end - function c:Pause() - self.timer:Pause() - self.Parent.Pause(self) - end - if self.Type=='queue' then - c:Pause() - c:connectFinal(multi.queuefinal) - else - c.timer:Start() - end - self:create(c) - return c -end -function multi:newLoop(func) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='loop' - c.Start=self.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - for i=1,#self.func do - self.func[i](self.Parent.clock()-self.Start,self) - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newUpdater(skip) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='updater' - c.pos=1 - c.skip=skip or 1 - function c:Act() - if self.pos>=self.skip then - self.pos=0 - for i=1,#self.func do - self.func[i](self) - end - end - self.pos=self.pos+1 - end - function c:setSkip(n) - self.skip=n - end - c.OnUpdate=self.OnMainConnect - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newStep(start,reset,count,skip) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type='step' - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newTStep(start,reset,count,set) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type='tstep' - c.Priority=self.Priority_Low - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=self.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=self.start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=self.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=self.clock() - self:Resume() - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newWatcher(namespace,name) - local function WatcherObj(ns,n) - if self.Type=='queue' then - print("Cannot create a watcher on a queue! Creating on 'multi' instead!") - self=multi - end - local c=self:newBase() - c.Type='watcher' - c.ns=ns - c.n=n - c.cv=ns[n] - function c:OnValueChanged(func) - table.insert(self.func,func) - end - function c:Act() - if self.cv~=self.ns[self.n] then - for i=1,#self.func do - self.func[i](self,self.cv,self.ns[self.n]) - end - self.cv=self.ns[self.n] - end - end - self:create(c) - return c - end - if type(namespace)~='table' and type(namespace)=='string' then - return WatcherObj(_G,namespace) - elseif type(namespace)=='table' and (type(name)=='string' or 'number') then - return WatcherObj(namespace,name) - else - print('Warning, invalid arguments! Nothing returned!') - end -end -function multi:newThread(name,func) - local c={} - c.ref={} - c.Name=name - c.thread=coroutine.create(func) - c.sleep=1 - c.firstRunDone=false - c.timer=multi.scheduler:newTimer() - c.ref.Globals=self:linkDomain("Globals") - function c.ref:send(name,val) - ret=coroutine.yield({Name=name,Value=val}) - self:syncGlobals(ret) - end - function c.ref:get(name) - return self.Globals[name] - end - function c.ref:kill() - err=coroutine.yield({"_kill_"}) - if err then - error("Failed to kill a thread! Exiting...") - end - end - function c.ref:sleep(n) - n = tonumber(n) or 0 - ret=coroutine.yield({"_sleep_",n}) - self:syncGlobals(ret) - end - function c.ref:syncGlobals(v) - self.Globals=v - end - table.insert(self:linkDomain("Threads"),c) - if not multi.scheduler:isActive() then - multi.scheduler:Resume() - end -end --- Constructors [SEMI-ACTORS] -function multi:newJob(func,name) - if not(self.Type=='mainprocess' or self.Type=='process') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='process' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Parent=self - c.Type='job' - c.trigfunc=func or function() end - function c:Act() - self:trigfunc(self) - end - table.insert(self.Jobs,{c,name}) - if self.JobRunner==nil then - self.JobRunner=self:newAlarm(self.jobUS) - self.JobRunner:OnRing(function(self) - if #self.Parent.Jobs>0 then - if self.Parent.Jobs[1] then - self.Parent.Jobs[1][1]:Act() - table.remove(self.Parent.Jobs,1) - end - end - self:Reset(self.Parent.jobUS) - end) - end -end -function multi:newRange() - selflink=self - local temp={ - getN = function(self) selflink:Do_Order() self.n=self.n+self.c if self.n>self.b then self.Link.held=false self.Link:Resume() return nil end return self.n end, - } - setmetatable(temp,{ - __call=function(self,a,b,c) - self.c=c or 1 - self.n=a-self.c - self.a=a - self.b=b - self.Link=selflink.Parent.Mainloop[selflink.CID] - self.Link:Pause() - self.Link.held=true - return function() return self:getN() end - end - }) - self:create(temp) - return temp -end -function multi:newCondition(func) - local c={['condition']=func} - self:create(c) - return c -end --- Constructors [NON-ACTORS] -function multi:newFunction(func) - local c={} - c.func=func - mt={ - __index=multi, - __call=function(self,...) if self.Active then return self:func(...) end local t={...} return "PAUSED" end - } - c.Parent=self - function c:Pause() - self.Active=false - end - function c:Resume() - self.Active=true - end - setmetatable(c,mt) - self:create(c) - return c -end -function multi:newTimer() - local c={} - c.Type='timer' - c.time=0 - c.count=0 - function c:Start() - self.time=os.clock() - end - function c:Get() - return (os.clock()-self.time)+self.count - end - c.Reset=c.Start - function c:Pause() - self.time=self:Get() - end - function c:Resume() - self.time=os.clock()-self.time - end - function c:tofile(path) - local m=bin.new() - self.count=self.count+self:Get() - m:addBlock(self.Type) - m:addBlock(self.count) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newTrigger(func) - local c={} - c.Type='trigger' - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.trigfunc) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newConnection(protect) - local c={} - setmetatable(c,{__call=function(self,...) self:connect(...) end}) - c.Type='connector' - c.func={} - c.ID=0 - c.protect=protect or true - function c:Fire(...) - local ret={} - for i=#self.func,1,-1 do - if self.protect then - local temp={pcall(self.func[i][1],...)} - if temp[1] then - table.remove(temp,1) - table.insert(ret,temp) - else - print(temp[2]) - end - else - table.insert(ret,{self.func[i][1](...)}) - end - end - return ret - end - function c:bind(t) - self.func=t - end - function c:remove() - self.func={} - end - function c:connect(func) - self.ID=self.ID+1 - table.insert(self.func,1,{func,self.ID}) - return { - Link=self.func, - ID=self.ID, - remove=function(self) - for i=1,#self.Link do - if self.Link[i][2]~=nil then - if self.Link[i][2]==self.ID then - table.remove(self.Link,i) - self.remove=function() end - self.Link=nil - self.ID=nil - return true - end - end - end - end - } - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:tofile(path) - end - return c -end -multi.OnObjectCreated=multi:newConnection() -multi.OnObjectDestroyed=multi:newConnection() ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - self:Do_Order() - end - print("Did you call multi:Stop()? This method should not be used when using multi:mainloop()! You now need to restart the multiManager, by using multi:reboot() and calling multi:mainloop() again or by using multi:uManager()") -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - rawset(self,'Start',self.clock()) -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - function self:uManager(dt) - self:Do_Order() - end - self:Do_Order() - end -end ---Thread Setup Stuff -multi:setDomainName("Threads") -multi:setDomainName("Globals") --- Scheduler -multi.scheduler=multi:newUpdater() -multi.scheduler.Type="scheduler" -function multi.scheduler:setStep(n) - self.skip=tonumber(n) or 24 -end -multi.scheduler.Threads=multi:linkDomain("Threads") -multi.scheduler.Globals=multi:linkDomain("Globals") -multi.scheduler:OnUpdate(function(self) - for i=#self.Threads,1,-1 do - ret={} - if coroutine.status(self.Threads[i].thread)=="dead" then - table.remove(self.Threads,i) - else - if self.Threads[i].timer:Get()>=self.Threads[i].sleep then - if self.Threads[i].firstRunDone==false then - self.Threads[i].firstRunDone=true - self.Threads[i].timer:Start() - _,ret=coroutine.resume(self.Threads[i].thread,self.Threads[i].ref) - else - _,ret=coroutine.resume(self.Threads[i].thread,self.Globals) - end - if ret==true or ret==false then - print("Thread Ended!!!") - ret={} - end - end - if ret then - if ret[1]=="_kill_" then - table.remove(self.Threads,i) - elseif ret[1]=="_sleep_" then - self.Threads[i].timer:Reset() - self.Threads[i].sleep=ret[2] - elseif ret.Name then - self.Globals[ret.Name]=ret.Value - end - end - end - end -end) -multi.scheduler:setStep() -multi.scheduler:Pause() -multi.OnError=multi:newConnection() diff --git a/mulit/oldversions/MultiManager(1.2.0).lua b/mulit/oldversions/MultiManager(1.2.0).lua deleted file mode 100644 index 94f47e5..0000000 --- a/mulit/oldversions/MultiManager(1.2.0).lua +++ /dev/null @@ -1,1434 +0,0 @@ -if not bin then - print('Warning the \'bin\' library wasn\'t required! multi:tofile(path) and the multi:fromfile(path,int) features will not work!') -end -if table.unpack then - unpack=table.unpack -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -multi = {} -multi.Version={'A',2,0}-- History: EventManager,EventManager+,MultiManager <-- Current After 6.3.0 Versioning scheme was altered. A.0.0 -multi.help=[[ -For a list of features do print(multi.Features) -For a list of changes do print(multi.changelog) -For current version do print(multi.Version) -For current stage do print(multi.stage) -For help do print(multi.help) :D -]] -multi.stage='stable' -multi.Features='Current Version: '..multi.Version[1]..'.'..multi.Version[2]..'.'..multi.Version[3]..' '..multi.stage..[[ -MultiManager has 19 Objects: # indicates most commonly used 1-19 1 being the most used by me -+Events #7 -+Alarms #2 -+Loops #3 -+Steps #4 -+TSteps #6 -+Triggers #16 -+Tasks #12 -+Connections #1 -- This is a rather new feature of this library, but has become the most useful for async handling. Knowing this is already 50% of this library -+Timers #14 -- this was tricky because these make up both Alarms and TSteps, but in purly using this standalone is almost non existent -+Jobs #11 -+Process #10 -+Conditions #15 -+Ranges #8 -+Threads #13 -+Functions #5 -+Queuers #17 -+Updaters #9 -+Watchers #18 -+CustomObjects #19 - -Constructors [Runners] ----------------------- Note: multi is the main Processor Obj It cannot be paused or destroyed (kinda) -intObj=multi:newProcess([string: FILE defualt: nil]) -intObj=multi:newQueuer([string: FILE defualt: nil]) - -Constructors [ACTORS] ---------------------- Note: everything is a multiObj! -eventObj=multi:newEvent([function: TASK defualt: function() end]) -alarmObj=multi:newAlarm([number: SET defualt: 0]) -loopObj=multi:newLoop([function: FUNC]) -stepObj=multi:newStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SKIP defualt: 0]) -tstepObj=multi:newTStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SET defualt: 1]) -updaterObj=multi:newUpdater([number: SKIP defualt: 0]) -watcherObj=multi:newWatcher(table: NAMESPACE,string: NAME) -multiObj=multi:newCustomObject([table: OBJREF],[string: T='process']) -void=multi:newThread(string: name,function: func) - -Constructors [Semi-ACTORS] --------------------------- -multi:newJob(function: func,[string: name]) -multi:newRange(number: a,number: b,[number: c]) -multi:newCondition(func) - -Constructors [NON-ACTORS] -------------------------- -multi:newTrigger(function: func) -multi:newTask(function: func) -multi:newConnection() -multi:newTimer() -multi:newFunction(function: func) -]] -multi.changelog=[[Changelog starts at Version A.0.0 -New in A.0.0 - Nothing really however a changelog will now be recorded! Feel free to remove this extra strings if space is a requriment - version.major.minor -New in A.1.0 - Changed: multi:newConnection(protect) method - Changed the way you are able to interact with it by adding the __call metamethod - Old usage: - OnUpdate=multi:newConnection() - OnUpdate:connect(function(...) - print("Updating",...) - end) - OnUpdate:Fire(1,2,3) - New usage: notice that connect is no longer needed! Both ways still work! and always will work :) - OnUpdate=multi:newConnection() - OnUpdate(function(...) - print("Updating",...) - end) - OnUpdate:Fire(1,2,3) -New in A.2.0 (12/31/2016) - Added: - connectionobj.getConnection(name) - returns a list of an instance (or instances) of a single connect made with connectionobj:connect(func,name) or connectionobj(func,name) - if you can orginize data before hand you can route info to certain connections thus saving a lot of cpu time. NOTE: only one name per each connection... you can't have 2 of the same names in a dictonary... the last one will be used - Changed: obj=multi:newConnection() - obj:connect(func,name) and obj(func,name) - Added the name argument to allow indexing specific connection objects... Useful when creating an async library -]] -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.ender={} -multi.Children={} -multi.Paused={} -multi.Active=true -multi.fps=60 -multi.Id=-1 -multi.Type='mainprocess' -multi.Rest=0 -multi._type=type -multi.Jobs={} -multi.queue={} -multi.jobUS=2 -multi.clock=os.clock -multi.time=os.time -multi.LinkedPath=multi -multi.queuefinal=function(self) - self:Destroy() - if self.Parent.Mainloop[#self.Parent.Mainloop] then - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - else - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end -end ---Do not change these ever...Any other number will not work (Unless you are using enablePriority2() then change can be made. Just ensure that Priority_Idle is the greatest and Priority_Core is 1!) -multi.Priority_Core=1 -multi.Priority_High=4 -multi.Priority_Above_Normal=16 -multi.Priority_Normal=64 -multi.Priority_Below_Normal=256 -multi.Priority_Low=1024 -multi.Priority_Idle=4096 -multi.PList={multi.Priority_Core,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Idle} -multi.PStep=1 ---^^^^ -multi.PriorityTick=1 -- Between 1 and 4 any greater and problems arise -multi.Priority=multi.Priority_Core -function multi:setDomainName(name) - self[name]={} -end -function multi:linkDomain(name) - return self[name] -end -function multi:_Pause() - self.Active=false -end -function multi:setPriority(s) - if type(s)==number then - self.Priority=s - elseif type(s)=='string' then - if s:lower()=='core' or s:lower()=='c' then - self.Priority=self.Priority_Core - elseif s:lower()=='high' or s:lower()=='h' then - self.Priority=self.Priority_High - elseif s:lower()=='above' or s:lower()=='an' then - self.Priority=self.Priority_Above_Normal - elseif s:lower()=='normal' or s:lower()=='n' then - self.Priority=self.Priority_Normal - elseif s:lower()=='below' or s:lower()=='bn' then - self.Priority=self.Priority_Below_Normal - elseif s:lower()=='low' or s:lower()=='l' then - self.Priority=self.Priority_Low - elseif s:lower()=='idle' or s:lower()=='i' then - self.Priority=self.Priority_Idle - end - end -end --- System -function os.getOS() - if package.config:sub(1,1)=='\\' then - return 'windows' - else - return 'unix' - end -end -if os.getOS()=='windows' then - function os.sleep(n) - if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end - end -else - function os.sleep(n) - os.execute('sleep ' .. tonumber(n)) - end -end -function multi:getParentProcess() - return self.Mainloop[self.CID] -end -function multi:Stop() - self.Active=false -end -function multi:condition(cond) - if not self.CD then - self:Pause() - self.held=true - self.CD=cond.condition - elseif not(cond.condition()) then - self.held=false - self:Resume() - self.CD=nil - return false - end - self.Parent:Do_Order() - return true -end -function multi:isHeld() - return self.held -end -function multi.executeFunction(name,...) - if type(_G[name])=='function' then - _G[name](...) - else - print('Error: Not a function') - end -end -function multi:waitFor(obj) - self:hold(function() return obj:isActive() end) -end -function multi:reboot(r) - local before=collectgarbage('count') - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=='table' then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end - collectgarbage() - local after=collectgarbage('count') - print([[Before rebooting total Ram used was ]]..before..[[Kb -After rebooting total Ram used is ]]..after..[[ Kb -A total of ]]..(before-after)..[[Kb was cleaned up]]) -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:getError() - if self.error then - return self.error - end -end -function multi:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:enablePriority() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PList[PS.PStep])%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>7 then - PS.PStep=1 - end - end -end -function multi:enablePriority2() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PStep)%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>self.Priority_Idle then - PS.PStep=1 - end - end -end -multi.disablePriority=multi.unProtect -function multi:fromfile(path,int) - int=int or self - local test2={} - local test=bin.load(path) - local tp=test:getBlock('s') - if tp=='event' then - test2=int:newEvent(test:getBlock('f')) - local t=test:getBlock('t') - for i=1,#t do - test2:OnEvent(t[i]) - end - elseif tp=='alarm' then - test2=int:newAlarm(test:getBlock('n')) - elseif tp=='loop' then - test2=int:newLoop(test:getBlock('t')[1]) - elseif tp=='step' or tp=='tstep' then - local func=test:getBlock('t') - local funcE=test:getBlock('t') - local funcS=test:getBlock('t') - local tab=test:getBlock('t') - test2=int:newStep() - table.merge(test2,tab) - test2.funcE=funcE - test2.funcS=funcS - test2.func=func - elseif tp=='trigger' then - test2=int:newTrigger(test:getBlock('f')) - elseif tp=='connector' then - test2=int:newConnection() - test2.func=test:getBlock('t') - elseif tp=='timer' then - test2=int:newTimer() - test2.count=tonumber(test:getBlock('n')) - else - print('Error: The file you selected is not a valid multi file object!') - return false - end - return test2 -end -function multi:benchMark(sec,p) - local temp=self:newLoop(function(t,self) - if self.clock()-self.init>self.sec then - print(self.c..' steps in '..self.sec..' second(s)') - self.tt(self.sec) - self:Destroy() - else - self.c=self.c+1 - end - end) - temp.Priority=p or 1 - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=self.clock() - temp.c=0 - return temp -end -function multi:tofile(path) - local items=self:getChildren() - io.mkDir(io.getName(path)) - for i=1,#items do - items[i]:tofile(io.getName(path)..'\\item'..item[i]..'.dat') - end - local int=bin.new() - int:addBlock('process') - int:addBlock(io.getName(path)) - int:addBlock(#self.Mainloop) - int:addBlock(self.Active) - int:addBlock(self.Rest) - int:addBlock(self.Jobs) - int:tofile() -end -function multi.startFPSMonitior() - if not multi.runFPS then - multi.doFPS(s) - multi.runFPS=true - end -end -function multi.doFPS(s) - multi:benchMark(1):OnBench(doFPS) - if s then - multi.fps=s - end -end ---Helpers -function multi:OnMainConnect(func) - table.insert(self.func,func) -end -function multi:protect() - function self:Do_Order() - local Loop=self.Mainloop - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - self.CID=_D - local status, err=pcall(Loop[_D].Act,Loop[_D]) - if err and not(Loop[_D].error) then - Loop[_D].error=err - self.OnError:Fire(err,Loop[_D]) - end - end - end - end -end -function multi:unProtect() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:setJobSpeed(n) - self.jobUS=n -end -function multi:hasJobs() - return #self.Jobs>0,#self.Jobs -end -function multi:getJobs() - return #self.Jobs -end -function multi:removeJob(name) - for i=#self.Jobs,1,-1 do - if self.Jobs[i][2]==name then - table.remove(self.Jobs,i) - end - end -end -function multi:FreeMainEvent() - self.func={} -end -function multi:connectFinal(func) - if self.Type=='event' then - self:OnEvent(func) - elseif self.Type=='alarm' then - self:OnRing(func) - elseif self.Type=='step' or self.Type=='tstep' then - self:OnEnd(func) - else - print("Warning!!! "..self.Type.." doesn't contain a Final Connection State! Use "..self.Type..":Break(function) to trigger it's final event!") - self:OnBreak(func) - end -end -function multi:Break() - self:Pause() - self.Active=nil - for i=1,#self.ender do - if self.ender[i] then - self.ender[i](self) - end - end -end -function multi:OnBreak(func) - table.insert(self.ender,func) -end -function multi:isPaused() - return not(self.Active) -end -function multi:isActive() - return self.Active -end -function multi:getType() - return self.Type -end -function multi:Sleep(n) - self:hold(n) -end -function multi:Pause() - if self.Type=='mainprocess' then - print("You cannot pause the main process. Doing so will stop all methods and freeze your program! However if you still want to use multi:_Pause()") - else - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - end -end -function multi:Resume() - if self.Type=='process' or self.Type=='mainprocess' then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:resurrect() - table.insert(self.Parent.Mainloop,self) - self.Active=true -end -function multi:Destroy() - if self.Type=='process' or self.Type=='mainprocess' then - local c=self:getChildren() - for i=1,#c do - self.OnObjectDestroyed:Fire(c[i]) - c[i]:Destroy() - end - else - for i=1,#self.Parent.Mainloop do - if self.Parent.Mainloop[i]==self then - self.Parent.OnObjectDestroyed:Fire(self) - table.remove(self.Parent.Mainloop,i) - break - end - end - self.Active=false - end -end - -function multi:hold(task) - self:Pause() - self.held=true - if type(task)=='number' then - local alarm=self.Parent:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - alarm:Destroy() - self:Resume() - self.held=false - elseif type(task)=='function' then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt.Active=false end) - while env.Active do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - env:Destroy() - self:Resume() - self.held=false - else - print('Error Data Type!!!') - end -end -function multi:oneTime(func,...) - if not(self.Type=='mainprocess' or self.Type=='process') then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end -function multi:Reset(n) - self:Resume() -end -function multi:isDone() - return self.Active~=true -end -function multi:create(ref) - multi.OnObjectCreated:Fire(ref) -end ---Constructors [CORE] -function multi:newBase(ins) - if not(self.Type=='mainprocess' or self.Type=='process' or self.Type=='queue') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='process' or self.Type=='queue' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.ender={} - c.Id=0 - c.PId=0 - c.Act=function() end - c.Parent=self - c.held=false - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - return c -end -function multi:newProcess(file) - if not(self.Type=='mainprocess') then error('Can only create an interface on the multi obj') return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type='process' - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.Active=true - c.Id=-1 - c.Rest=0 - c.Jobs={} - c.queue={} - c.jobUS=2 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Pause() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - if file then - self.Cself=c - loadstring('local interface=multi.Cself '..io.open(file,'rb'):read('*all'))() - end - self:create(c) - return c -end -function multi:newQueuer(file) - local c=self:newProcess() - c.Type='queue' - c.last={} - c.funcE={} - function c:OnQueueCompleted(func) - table.insert(self.funcE,func) - end - if file then - self.Cself=c - loadstring('local queue=multi.Cself '..io.open(file,'rb'):read('*all'))() - end - self:create(c) - return c -end ---Constructors [ACTORS] -function multi:newCustomObject(objRef,t) - local c={} - if t=='process' then - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - print("This Custom Object was created on a queue! Ensure that it has a way to end! All objects have a obj:Break() method!") - else - c=self:newBase() - end - if type(objRef)=='table' then - table.merge(c,objRef) - end - if not c.Act then - function c:Act() - -- Empty function - end - end - else - c=objRef or {} - end - if not c.Type then - c.Type='coustomObject' - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newEvent(task) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='event' - c.Task=task or function() end - function c:Act() - if self.Task(self) then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.Task) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newAlarm(set) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='alarm' - c.Priority=self.Priority_Low - c.timer=self:newTimer() - c.set=set or 0 - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.set) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.timer:Get()>=self.set then - self:Pause() - self.Active=false - for i=1,#self.func do - self.func[i](self) - end - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer:Resume() - end - function c:Reset(n) - if n then self.set=n end - self:Resume() - self.timer:Reset() - end - function c:OnRing(func) - table.insert(self.func,func) - end - function c:Pause() - self.timer:Pause() - self.Parent.Pause(self) - end - if self.Type=='queue' then - c:Pause() - c:connectFinal(multi.queuefinal) - else - c.timer:Start() - end - self:create(c) - return c -end -function multi:newLoop(func) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='loop' - c.Start=self.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - for i=1,#self.func do - self.func[i](self.Parent.clock()-self.Start,self) - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newUpdater(skip) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='updater' - c.pos=1 - c.skip=skip or 1 - function c:Act() - if self.pos>=self.skip then - self.pos=0 - for i=1,#self.func do - self.func[i](self) - end - end - self.pos=self.pos+1 - end - function c:setSkip(n) - self.skip=n - end - c.OnUpdate=self.OnMainConnect - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newStep(start,reset,count,skip) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type='step' - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newTStep(start,reset,count,set) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type='tstep' - c.Priority=self.Priority_Low - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=self.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=self.start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=self.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=self.clock() - self:Resume() - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newWatcher(namespace,name) - local function WatcherObj(ns,n) - if self.Type=='queue' then - print("Cannot create a watcher on a queue! Creating on 'multi' instead!") - self=multi - end - local c=self:newBase() - c.Type='watcher' - c.ns=ns - c.n=n - c.cv=ns[n] - function c:OnValueChanged(func) - table.insert(self.func,func) - end - function c:Act() - if self.cv~=self.ns[self.n] then - for i=1,#self.func do - self.func[i](self,self.cv,self.ns[self.n]) - end - self.cv=self.ns[self.n] - end - end - self:create(c) - return c - end - if type(namespace)~='table' and type(namespace)=='string' then - return WatcherObj(_G,namespace) - elseif type(namespace)=='table' and (type(name)=='string' or 'number') then - return WatcherObj(namespace,name) - else - print('Warning, invalid arguments! Nothing returned!') - end -end -function multi:newThread(name,func) - local c={} - c.ref={} - c.Name=name - c.thread=coroutine.create(func) - c.sleep=1 - c.firstRunDone=false - c.timer=multi.scheduler:newTimer() - c.ref.Globals=self:linkDomain("Globals") - function c.ref:send(name,val) - ret=coroutine.yield({Name=name,Value=val}) - self:syncGlobals(ret) - end - function c.ref:get(name) - return self.Globals[name] - end - function c.ref:kill() - err=coroutine.yield({"_kill_"}) - if err then - error("Failed to kill a thread! Exiting...") - end - end - function c.ref:sleep(n) - n = tonumber(n) or 0 - ret=coroutine.yield({"_sleep_",n}) - self:syncGlobals(ret) - end - function c.ref:syncGlobals(v) - self.Globals=v - end - table.insert(self:linkDomain("Threads"),c) - if not multi.scheduler:isActive() then - multi.scheduler:Resume() - end -end --- Constructors [SEMI-ACTORS] -function multi:newJob(func,name) - if not(self.Type=='mainprocess' or self.Type=='process') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='process' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Parent=self - c.Type='job' - c.trigfunc=func or function() end - function c:Act() - self:trigfunc(self) - end - table.insert(self.Jobs,{c,name}) - if self.JobRunner==nil then - self.JobRunner=self:newAlarm(self.jobUS) - self.JobRunner:OnRing(function(self) - if #self.Parent.Jobs>0 then - if self.Parent.Jobs[1] then - self.Parent.Jobs[1][1]:Act() - table.remove(self.Parent.Jobs,1) - end - end - self:Reset(self.Parent.jobUS) - end) - end -end -function multi:newRange() - local selflink=self - local temp={ - getN = function(self) selflink:Do_Order() self.n=self.n+self.c if self.n>self.b then self.Link.held=false self.Link:Resume() return nil end return self.n end, - } - setmetatable(temp,{ - __call=function(self,a,b,c) - self.c=c or 1 - self.n=a-self.c - self.a=a - self.b=b - self.Link=selflink--.Parent.Mainloop[selflink.CID] or - self.Link:Pause() - self.Link.held=true - return function() return self:getN() end - end - }) - self:create(temp) - return temp -end -function multi:newCondition(func) - local c={['condition']=func} - self:create(c) - return c -end --- Constructors [NON-ACTORS] -function multi:newFunction(func) - local c={} - c.func=func - mt={ - __index=multi, - __call=function(self,...) if self.Active then return self:func(...) end local t={...} return "PAUSED" end - } - c.Parent=self - function c:Pause() - self.Active=false - end - function c:Resume() - self.Active=true - end - setmetatable(c,mt) - self:create(c) - return c -end -function multi:newTimer() - local c={} - c.Type='timer' - c.time=0 - c.count=0 - function c:Start() - self.time=os.clock() - end - function c:Get() - return (os.clock()-self.time)+self.count - end - c.Reset=c.Start - function c:Pause() - self.time=self:Get() - end - function c:Resume() - self.time=os.clock()-self.time - end - function c:tofile(path) - local m=bin.new() - self.count=self.count+self:Get() - m:addBlock(self.Type) - m:addBlock(self.count) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newTrigger(func) - local c={} - c.Type='trigger' - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.trigfunc) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newConnection(protect) - local c={} - setmetatable(c,{__call=function(self,...) self:connect(...) end}) - c.Type='connector' - c.func={} - c.ID=0 - c.protect=protect or true - c.connections={} - c.fconnections={} - c.FC=0 - function c:fConnect(func) - local temp=self:connect(func) - table.insert(self.fconnections,temp) - self.FC=self.FC+1 - end - function c:getConnection(name,ingore) - if ingore then - return self.connections[name] or { - Fire=function() end -- if the connection doesn't exist lets call all of them or silently ingore - } - else - return self.connections[name] or self - end - end - function c:Fire(...) - local ret={} - for i=#self.func,1,-1 do - if self.protect then - local temp={pcall(self.func[i][1],...)} - if temp[1] then - table.remove(temp,1) - table.insert(ret,temp) - else - print(temp[2]) - end - else - table.insert(ret,{self.func[i][1](...)}) - end - end - return ret - end - function c:bind(t) - self.func=t - end - function c:remove() - self.func={} - end - function c:connect(func,name) - self.ID=self.ID+1 - table.insert(self.func,1,{func,self.ID}) - local temp = { - Link=self.func, - func=func, - ID=self.ID, - Parent=self, - Fire=function(self,...) - if self.Parent.FC>0 then - for i=1,#self.Parent.FC do - self.Parent.FC[i]:Fire(...) - end - end - if self.Parent.protect then - local t=pcall(self.func,...) - if t then - return t - end - else - return self.func(...) - end - end, - remove=function(self) - for i=1,#self.Link do - if self.Link[i][2]~=nil then - if self.Link[i][2]==self.ID then - table.remove(self.Link,i) - self.remove=function() end - self.Link=nil - self.ID=nil - return true - end - end - end - end - } - if name then - self.connections[name]=temp - end - return temp - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:tofile(path) - end - return c -end -multi.OnObjectCreated=multi:newConnection() -multi.OnObjectDestroyed=multi:newConnection() ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - self:Do_Order() - end - print("Did you call multi:Stop()? This method should not be used when using multi:mainloop()! You now need to restart the multiManager, by using multi:reboot() and calling multi:mainloop() again or by using multi:uManager()") -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - rawset(self,'Start',self.clock()) -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - function self:uManager(dt) - self:Do_Order() - end - self:Do_Order() - end -end ---Thread Setup Stuff -multi:setDomainName("Threads") -multi:setDomainName("Globals") --- Scheduler -multi.scheduler=multi:newUpdater() -multi.scheduler.Type="scheduler" -function multi.scheduler:setStep(n) - self.skip=tonumber(n) or 24 -end -multi.scheduler.Threads=multi:linkDomain("Threads") -multi.scheduler.Globals=multi:linkDomain("Globals") -multi.scheduler:OnUpdate(function(self) - for i=#self.Threads,1,-1 do - ret={} - if coroutine.status(self.Threads[i].thread)=="dead" then - table.remove(self.Threads,i) - else - if self.Threads[i].timer:Get()>=self.Threads[i].sleep then - if self.Threads[i].firstRunDone==false then - self.Threads[i].firstRunDone=true - self.Threads[i].timer:Start() - _,ret=coroutine.resume(self.Threads[i].thread,self.Threads[i].ref) - else - _,ret=coroutine.resume(self.Threads[i].thread,self.Globals) - end - if ret==true or ret==false then - print("Thread Ended!!!") - ret={} - end - end - if ret then - if ret[1]=="_kill_" then - table.remove(self.Threads,i) - elseif ret[1]=="_sleep_" then - self.Threads[i].timer:Reset() - self.Threads[i].sleep=ret[2] - elseif ret.Name then - self.Globals[ret.Name]=ret.Value - end - end - end - end -end) -multi.scheduler:setStep() -multi.scheduler:Pause() -multi.OnError=multi:newConnection() diff --git a/mulit/oldversions/MultiManager(1.3.0).lua b/mulit/oldversions/MultiManager(1.3.0).lua deleted file mode 100644 index 204ea05..0000000 --- a/mulit/oldversions/MultiManager(1.3.0).lua +++ /dev/null @@ -1,1460 +0,0 @@ -if table.unpack then - unpack=table.unpack -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -multi = {} -multi.Version={'A',3,0}-- History: EventManager,EventManager+,MultiManager <-- Current After 6.3.0 Versioning scheme was altered. A.0.0 -multi.help=[[ -For a list of features do print(multi.Features) -For a list of changes do print(multi.changelog) -For current version do print(multi.Version) -For current stage do print(multi.stage) -For help do print(multi.help) :D -]] -multi.stage='stable' -multi.Features='Current Version: '..multi.Version[1]..'.'..multi.Version[2]..'.'..multi.Version[3]..' '..multi.stage..[[ -MultiManager has 19 Objects: # indicates most commonly used 1-19 1 being the most used by me -+Events #7 -+Alarms #2 -+Loops #3 -+Steps #4 -+TSteps #6 -+Triggers #16 -+Tasks #12 -+Connections #1 -- This is a rather new feature of this library, but has become the most useful for async handling. Knowing this is already 50% of this library -+Timers #14 -- this was tricky because these make up both Alarms and TSteps, but in purly using this standalone is almost non existent -+Jobs #11 -+Process #10 -+Conditions #15 -+Ranges #8 -+Threads #13 -+Functions #5 -+Queuers #17 -+Updaters #9 -+Watchers #18 -+CustomObjects #19 - -Constructors [Runners] ----------------------- Note: multi is the main Processor Obj It cannot be paused or destroyed (kinda) -intObj=multi:newProcess([string: FILE defualt: nil]) -intObj=multi:newQueuer([string: FILE defualt: nil]) - -Constructors [ACTORS] ---------------------- Note: everything is a multiObj! -eventObj=multi:newEvent([function: TASK defualt: function() end]) -alarmObj=multi:newAlarm([number: SET defualt: 0]) -loopObj=multi:newLoop([function: FUNC]) -stepObj=multi:newStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SKIP defualt: 0]) -tstepObj=multi:newTStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SET defualt: 1]) -updaterObj=multi:newUpdater([number: SKIP defualt: 0]) -watcherObj=multi:newWatcher(table: NAMESPACE,string: NAME) -multiObj=multi:newCustomObject([table: OBJREF],[string: T='process']) -void=multi:newThread(string: name,function: func) - -Constructors [Semi-ACTORS] --------------------------- -multi:newJob(function: func,[string: name]) -multi:newRange(number: a,number: b,[number: c]) -multi:newCondition(func) - -Constructors [NON-ACTORS] -------------------------- -multi:newTrigger(function: func) -multi:newTask(function: func) -multi:newConnection() -multi:newTimer() -multi:newFunction(function: func) -]] -multi.changelog=[[Changelog starts at Version A.0.0 -New in A.0.0 - Nothing really however a changelog will now be recorded! Feel free to remove this extra strings if space is a requriment - version.major.minor -New in A.1.0 - Changed: multi:newConnection(protect) method - Changed the way you are able to interact with it by adding the __call metamethod - Old usage: - OnUpdate=multi:newConnection() - OnUpdate:connect(function(...) - print("Updating",...) - end) - OnUpdate:Fire(1,2,3) - New usage: notice that connect is no longer needed! Both ways still work! and always will work :) - OnUpdate=multi:newConnection() - OnUpdate(function(...) - print("Updating",...) - end) - OnUpdate:Fire(1,2,3) -New in A.2.0 (12/31/2016) - Added: - connectionobj.getConnection(name) - returns a list of an instance (or instances) of a single connect made with connectionobj:connect(func,name) or connectionobj(func,name) - if you can orginize data before hand you can route info to certain connections thus saving a lot of cpu time. NOTE: only one name per each connection... you can't have 2 of the same names in a dictonary... the last one will be used - Changed: obj=multi:newConnection() - obj:connect(func,name) and obj(func,name) - Added the name argument to allow indexing specific connection objects... Useful when creating an async library -New in A.3.0 (1/29/2017) - Added: - Load detection! - multi.threshold -- minimum amount of cycles that all mObjs should be allotted before the Manager is considered burdened. Defualt: 256 - multi.threstimed -- amount of time when counting the number of cycles, Greater gives a more accurate view of the load, but takes more time. Defualt: .001 - multi:setThreshold(n) -- method used to set multi.threshold - multi:setThrestimed(n) -- method used to set multi.threstimed - multi:getLoad() -- returns a number between 0 and 100 -]] -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.ender={} -multi.Children={} -multi.Paused={} -multi.Active=true -multi.fps=60 -multi.Id=-1 -multi.Type='mainprocess' -multi.Rest=0 -multi._type=type -multi.Jobs={} -multi.queue={} -multi.jobUS=2 -multi.clock=os.clock -multi.time=os.time -multi.LinkedPath=multi -multi.queuefinal=function(self) - self:Destroy() - if self.Parent.Mainloop[#self.Parent.Mainloop] then - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - else - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end -end ---Do not change these ever...Any other number will not work (Unless you are using enablePriority2() then change can be made. Just ensure that Priority_Idle is the greatest and Priority_Core is 1!) -multi.Priority_Core=1 -multi.Priority_High=4 -multi.Priority_Above_Normal=16 -multi.Priority_Normal=64 -multi.Priority_Below_Normal=256 -multi.Priority_Low=1024 -multi.Priority_Idle=4096 -multi.PList={multi.Priority_Core,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Idle} -multi.PStep=1 ---^^^^ -multi.PriorityTick=1 -- Between 1 and 4 any greater and problems arise -multi.Priority=multi.Priority_Core -multi.threshold=256 -multi.threstimed=.001 -function multi:setThreshold(n) - self.threshold=n or 120 -end -function multi:setThrestimed(n) - self.threstimed=n or .001 -end -function multi:getLoad() - return multi:newFunction(function(self) - local sample=#multi.Mainloop - local FFloadtest=0 - multi:benchMark(multi.threstimed):OnBench(function(_,l3) FFloadtest=l3*(1/multi.threstimed) end) - self:hold(function() return FFloadtest~=0 end) - local val=FFloadtest/sample - if val>multi.threshold then - return 0 - else - return 100-((val/multi.threshold)*100) - end - end)() -end -function multi:setDomainName(name) - self[name]={} -end -function multi:linkDomain(name) - return self[name] -end -function multi:_Pause() - self.Active=false -end -function multi:setPriority(s) - if type(s)==number then - self.Priority=s - elseif type(s)=='string' then - if s:lower()=='core' or s:lower()=='c' then - self.Priority=self.Priority_Core - elseif s:lower()=='high' or s:lower()=='h' then - self.Priority=self.Priority_High - elseif s:lower()=='above' or s:lower()=='an' then - self.Priority=self.Priority_Above_Normal - elseif s:lower()=='normal' or s:lower()=='n' then - self.Priority=self.Priority_Normal - elseif s:lower()=='below' or s:lower()=='bn' then - self.Priority=self.Priority_Below_Normal - elseif s:lower()=='low' or s:lower()=='l' then - self.Priority=self.Priority_Low - elseif s:lower()=='idle' or s:lower()=='i' then - self.Priority=self.Priority_Idle - end - end -end --- System -function os.getOS() - if package.config:sub(1,1)=='\\' then - return 'windows' - else - return 'unix' - end -end -if os.getOS()=='windows' then - function os.sleep(n) - if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end - end -else - function os.sleep(n) - os.execute('sleep ' .. tonumber(n)) - end -end -function multi:getParentProcess() - return self.Mainloop[self.CID] -end -function multi:Stop() - self.Active=false -end -function multi:condition(cond) - if not self.CD then - self:Pause() - self.held=true - self.CD=cond.condition - elseif not(cond.condition()) then - self.held=false - self:Resume() - self.CD=nil - return false - end - self.Parent:Do_Order() - return true -end -function multi:isHeld() - return self.held -end -function multi.executeFunction(name,...) - if type(_G[name])=='function' then - _G[name](...) - else - print('Error: Not a function') - end -end -function multi:waitFor(obj) - self:hold(function() return obj:isActive() end) -end -function multi:reboot(r) - local before=collectgarbage('count') - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=='table' then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end - collectgarbage() - local after=collectgarbage('count') - print([[Before rebooting total Ram used was ]]..before..[[Kb -After rebooting total Ram used is ]]..after..[[ Kb -A total of ]]..(before-after)..[[Kb was cleaned up]]) -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:getError() - if self.error then - return self.error - end -end -function multi:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:enablePriority() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PList[PS.PStep])%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>7 then - PS.PStep=1 - end - end -end -function multi:enablePriority2() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PStep)%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>self.Priority_Idle then - PS.PStep=1 - end - end -end -multi.disablePriority=multi.unProtect -function multi:fromfile(path,int) - int=int or self - local test2={} - local test=bin.load(path) - local tp=test:getBlock('s') - if tp=='event' then - test2=int:newEvent(test:getBlock('f')) - local t=test:getBlock('t') - for i=1,#t do - test2:OnEvent(t[i]) - end - elseif tp=='alarm' then - test2=int:newAlarm(test:getBlock('n')) - elseif tp=='loop' then - test2=int:newLoop(test:getBlock('t')[1]) - elseif tp=='step' or tp=='tstep' then - local func=test:getBlock('t') - local funcE=test:getBlock('t') - local funcS=test:getBlock('t') - local tab=test:getBlock('t') - test2=int:newStep() - table.merge(test2,tab) - test2.funcE=funcE - test2.funcS=funcS - test2.func=func - elseif tp=='trigger' then - test2=int:newTrigger(test:getBlock('f')) - elseif tp=='connector' then - test2=int:newConnection() - test2.func=test:getBlock('t') - elseif tp=='timer' then - test2=int:newTimer() - test2.count=tonumber(test:getBlock('n')) - else - print('Error: The file you selected is not a valid multi file object!') - return false - end - return test2 -end -function multi:benchMark(sec,p) - local temp=self:newLoop(function(t,self) - if self.clock()-self.init>self.sec then - self.tt(self.sec,self.c) - self:Destroy() - else - self.c=self.c+1 - end - end) - temp.Priority=p or 1 - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=self.clock() - temp.c=0 - return temp -end -function multi:tofile(path) - local items=self:getChildren() - io.mkDir(io.getName(path)) - for i=1,#items do - items[i]:tofile(io.getName(path)..'\\item'..item[i]..'.dat') - end - local int=bin.new() - int:addBlock('process') - int:addBlock(io.getName(path)) - int:addBlock(#self.Mainloop) - int:addBlock(self.Active) - int:addBlock(self.Rest) - int:addBlock(self.Jobs) - int:tofile() -end -function multi.startFPSMonitior() - if not multi.runFPS then - multi.doFPS(s) - multi.runFPS=true - end -end -function multi.doFPS(s) - multi:benchMark(1):OnBench(doFPS) - if s then - multi.fps=s - end -end ---Helpers -function multi:OnMainConnect(func) - table.insert(self.func,func) -end -function multi:protect() - function self:Do_Order() - local Loop=self.Mainloop - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - self.CID=_D - local status, err=pcall(Loop[_D].Act,Loop[_D]) - if err and not(Loop[_D].error) then - Loop[_D].error=err - self.OnError:Fire(err,Loop[_D]) - end - end - end - end -end -function multi:unProtect() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:setJobSpeed(n) - self.jobUS=n -end -function multi:hasJobs() - return #self.Jobs>0,#self.Jobs -end -function multi:getJobs() - return #self.Jobs -end -function multi:removeJob(name) - for i=#self.Jobs,1,-1 do - if self.Jobs[i][2]==name then - table.remove(self.Jobs,i) - end - end -end -function multi:FreeMainEvent() - self.func={} -end -function multi:connectFinal(func) - if self.Type=='event' then - self:OnEvent(func) - elseif self.Type=='alarm' then - self:OnRing(func) - elseif self.Type=='step' or self.Type=='tstep' then - self:OnEnd(func) - else - print("Warning!!! "..self.Type.." doesn't contain a Final Connection State! Use "..self.Type..":Break(function) to trigger it's final event!") - self:OnBreak(func) - end -end -function multi:Break() - self:Pause() - self.Active=nil - for i=1,#self.ender do - if self.ender[i] then - self.ender[i](self) - end - end -end -function multi:OnBreak(func) - table.insert(self.ender,func) -end -function multi:isPaused() - return not(self.Active) -end -function multi:isActive() - return self.Active -end -function multi:getType() - return self.Type -end -function multi:Sleep(n) - self:hold(n) -end -function multi:Pause() - if self.Type=='mainprocess' then - print("You cannot pause the main process. Doing so will stop all methods and freeze your program! However if you still want to use multi:_Pause()") - else - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - end -end -function multi:Resume() - if self.Type=='process' or self.Type=='mainprocess' then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:resurrect() - table.insert(self.Parent.Mainloop,self) - self.Active=true -end -function multi:Destroy() - if self.Type=='process' or self.Type=='mainprocess' then - local c=self:getChildren() - for i=1,#c do - self.OnObjectDestroyed:Fire(c[i]) - c[i]:Destroy() - end - else - for i=1,#self.Parent.Mainloop do - if self.Parent.Mainloop[i]==self then - self.Parent.OnObjectDestroyed:Fire(self) - table.remove(self.Parent.Mainloop,i) - break - end - end - self.Active=false - end -end - -function multi:hold(task) - self:Pause() - self.held=true - if type(task)=='number' then - local alarm=self.Parent:newAlarm(task) - while alarm.Active==true do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - alarm:Destroy() - self:Resume() - self.held=false - elseif type(task)=='function' then - local env=self.Parent:newEvent(task) - env:OnEvent(function(envt) envt:Pause() envt.Active=false end) - while env.Active do - if love then - self.Parent:lManager() - else - self.Parent:Do_Order() - end - end - env:Destroy() - self:Resume() - self.held=false - else - print('Error Data Type!!!') - end -end -function multi:oneTime(func,...) - if not(self.Type=='mainprocess' or self.Type=='process') then - for _k=1,#self.Parent.Tasks2 do - if self.Parent.Tasks2[_k]==func then - return false - end - end - table.insert(self.Parent.Tasks2,func) - func(...) - return true - else - for _k=1,#self.Tasks2 do - if self.Tasks2[_k]==func then - return false - end - end - table.insert(self.Tasks2,func) - func(...) - return true - end -end -function multi:Reset(n) - self:Resume() -end -function multi:isDone() - return self.Active~=true -end -function multi:create(ref) - multi.OnObjectCreated:Fire(ref) -end ---Constructors [CORE] -function multi:newBase(ins) - if not(self.Type=='mainprocess' or self.Type=='process' or self.Type=='queue') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='process' or self.Type=='queue' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.ender={} - c.Id=0 - c.PId=0 - c.Act=function() end - c.Parent=self - c.held=false - if ins then - table.insert(self.Mainloop,ins,c) - else - table.insert(self.Mainloop,c) - end - return c -end -function multi:newProcess(file) - if not(self.Type=='mainprocess') then error('Can only create an interface on the multi obj') return false end - local c = {} - setmetatable(c, self) - c.Parent=self - c.Active=true - c.func={} - c.Id=0 - c.Type='process' - c.Mainloop={} - c.Tasks={} - c.Tasks2={} - c.Garbage={} - c.Children={} - c.Paused={} - c.Active=true - c.Id=-1 - c.Rest=0 - c.Jobs={} - c.queue={} - c.jobUS=2 - function c:Start() - if self.l then - self.l:Resume() - else - self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) - end - end - function c:Pause() - if self.l then - self.l:Pause() - end - end - function c:Remove() - self:Destroy() - self.l:Destroy() - end - if file then - self.Cself=c - loadstring('local interface=multi.Cself '..io.open(file,'rb'):read('*all'))() - end - self:create(c) - return c -end -function multi:newQueuer(file) - local c=self:newProcess() - c.Type='queue' - c.last={} - c.funcE={} - function c:OnQueueCompleted(func) - table.insert(self.funcE,func) - end - if file then - self.Cself=c - loadstring('local queue=multi.Cself '..io.open(file,'rb'):read('*all'))() - end - self:create(c) - return c -end ---Constructors [ACTORS] -function multi:newCustomObject(objRef,t) - local c={} - if t=='process' then - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - print("This Custom Object was created on a queue! Ensure that it has a way to end! All objects have a obj:Break() method!") - else - c=self:newBase() - end - if type(objRef)=='table' then - table.merge(c,objRef) - end - if not c.Act then - function c:Act() - -- Empty function - end - end - else - c=objRef or {} - end - if not c.Type then - c.Type='coustomObject' - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newEvent(task) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='event' - c.Task=task or function() end - function c:Act() - if self.Task(self) then - self:Pause() - for _E=1,#self.func do - self.func[_E](self) - end - end - end - function c:OnEvent(func) - table.insert(self.func,func) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.Task) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newAlarm(set) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='alarm' - c.Priority=self.Priority_Low - c.timer=self:newTimer() - c.set=set or 0 - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.set) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.timer:Get()>=self.set then - self:Pause() - self.Active=false - for i=1,#self.func do - self.func[i](self) - end - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer:Resume() - end - function c:Reset(n) - if n then self.set=n end - self:Resume() - self.timer:Reset() - end - function c:OnRing(func) - table.insert(self.func,func) - end - function c:Pause() - self.timer:Pause() - self.Parent.Pause(self) - end - if self.Type=='queue' then - c:Pause() - c:connectFinal(multi.queuefinal) - else - c.timer:Start() - end - self:create(c) - return c -end -function multi:newLoop(func) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='loop' - c.Start=self.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - for i=1,#self.func do - self.func[i](self.Parent.clock()-self.Start,self) - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newUpdater(skip) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - c.Type='updater' - c.pos=1 - c.skip=skip or 1 - function c:Act() - if self.pos>=self.skip then - self.pos=0 - for i=1,#self.func do - self.func[i](self) - end - end - self.pos=self.pos+1 - end - function c:setSkip(n) - self.skip=n - end - c.OnUpdate=self.OnMainConnect - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newStep(start,reset,count,skip) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type='step' - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newTStep(start,reset,count,set) - local c={} - if self.Type=='queue' then - c=self:newBase(1) - self.last=c - else - c=self:newBase() - end - think=1 - c.Type='tstep' - c.Priority=self.Priority_Low - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=self.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=self.start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=self.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=self.clock() - self:Resume() - end - if self.Type=='queue' then - if #self.Mainloop>1 then - c:Pause() - end - c:connectFinal(multi.queuefinal) - end - self:create(c) - return c -end -function multi:newWatcher(namespace,name) - local function WatcherObj(ns,n) - if self.Type=='queue' then - print("Cannot create a watcher on a queue! Creating on 'multi' instead!") - self=multi - end - local c=self:newBase() - c.Type='watcher' - c.ns=ns - c.n=n - c.cv=ns[n] - function c:OnValueChanged(func) - table.insert(self.func,func) - end - function c:Act() - if self.cv~=self.ns[self.n] then - for i=1,#self.func do - self.func[i](self,self.cv,self.ns[self.n]) - end - self.cv=self.ns[self.n] - end - end - self:create(c) - return c - end - if type(namespace)~='table' and type(namespace)=='string' then - return WatcherObj(_G,namespace) - elseif type(namespace)=='table' and (type(name)=='string' or 'number') then - return WatcherObj(namespace,name) - else - print('Warning, invalid arguments! Nothing returned!') - end -end -function multi:newThread(name,func) - local c={} - c.ref={} - c.Name=name - c.thread=coroutine.create(func) - c.sleep=1 - c.firstRunDone=false - c.timer=multi.scheduler:newTimer() - c.ref.Globals=self:linkDomain("Globals") - function c.ref:send(name,val) - ret=coroutine.yield({Name=name,Value=val}) - self:syncGlobals(ret) - end - function c.ref:get(name) - return self.Globals[name] - end - function c.ref:kill() - err=coroutine.yield({"_kill_"}) - if err then - error("Failed to kill a thread! Exiting...") - end - end - function c.ref:sleep(n) - n = tonumber(n) or 0 - ret=coroutine.yield({"_sleep_",n}) - self:syncGlobals(ret) - end - function c.ref:syncGlobals(v) - self.Globals=v - end - table.insert(self:linkDomain("Threads"),c) - if not multi.scheduler:isActive() then - multi.scheduler:Resume() - end -end --- Constructors [SEMI-ACTORS] -function multi:newJob(func,name) - if not(self.Type=='mainprocess' or self.Type=='process') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='process' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Parent=self - c.Type='job' - c.trigfunc=func or function() end - function c:Act() - self:trigfunc(self) - end - table.insert(self.Jobs,{c,name}) - if self.JobRunner==nil then - self.JobRunner=self:newAlarm(self.jobUS) - self.JobRunner:OnRing(function(self) - if #self.Parent.Jobs>0 then - if self.Parent.Jobs[1] then - self.Parent.Jobs[1][1]:Act() - table.remove(self.Parent.Jobs,1) - end - end - self:Reset(self.Parent.jobUS) - end) - end -end -function multi:newRange() - local selflink=self - local temp={ - getN = function(self) selflink:Do_Order() self.n=self.n+self.c if self.n>self.b then self.Link.held=false self.Link:Resume() return nil end return self.n end, - } - setmetatable(temp,{ - __call=function(self,a,b,c) - self.c=c or 1 - self.n=a-self.c - self.a=a - self.b=b - self.Link=selflink--.Parent.Mainloop[selflink.CID] or - self.Link:Pause() - self.Link.held=true - return function() return self:getN() end - end - }) - self:create(temp) - return temp -end -function multi:newCondition(func) - local c={['condition']=func} - self:create(c) - return c -end --- Constructors [NON-ACTORS] -function multi:newFunction(func) - local c={} - c.func=func - mt={ - __index=multi, - __call=function(self,...) if self.Active then return self:func(...) end local t={...} return "PAUSED" end - } - c.Parent=self - function c:Pause() - self.Active=false - end - function c:Resume() - self.Active=true - end - setmetatable(c,mt) - self:create(c) - return c -end -function multi:newTimer() - local c={} - c.Type='timer' - c.time=0 - c.count=0 - function c:Start() - self.time=os.clock() - end - function c:Get() - return (os.clock()-self.time)+self.count - end - c.Reset=c.Start - function c:Pause() - self.time=self:Get() - end - function c:Resume() - self.time=os.clock()-self.time - end - function c:tofile(path) - local m=bin.new() - self.count=self.count+self:Get() - m:addBlock(self.Type) - m:addBlock(self.count) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newTrigger(func) - local c={} - c.Type='trigger' - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.trigfunc) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newConnection(protect) - local c={} - setmetatable(c,{__call=function(self,...) self:connect(...) end}) - c.Type='connector' - c.func={} - c.ID=0 - c.protect=protect or true - c.connections={} - c.fconnections={} - c.FC=0 - function c:fConnect(func) - local temp=self:connect(func) - table.insert(self.fconnections,temp) - self.FC=self.FC+1 - end - function c:getConnection(name,ingore) - if ingore then - return self.connections[name] or { - Fire=function() end -- if the connection doesn't exist lets call all of them or silently ingore - } - else - return self.connections[name] or self - end - end - function c:Fire(...) - local ret={} - for i=#self.func,1,-1 do - if self.protect then - local temp={pcall(self.func[i][1],...)} - if temp[1] then - table.remove(temp,1) - table.insert(ret,temp) - else - print(temp[2]) - end - else - table.insert(ret,{self.func[i][1](...)}) - end - end - return ret - end - function c:bind(t) - self.func=t - end - function c:remove() - self.func={} - end - function c:connect(func,name) - self.ID=self.ID+1 - table.insert(self.func,1,{func,self.ID}) - local temp = { - Link=self.func, - func=func, - ID=self.ID, - Parent=self, - Fire=function(self,...) - if self.Parent.FC>0 then - for i=1,#self.Parent.FC do - self.Parent.FC[i]:Fire(...) - end - end - if self.Parent.protect then - local t=pcall(self.func,...) - if t then - return t - end - else - return self.func(...) - end - end, - remove=function(self) - for i=1,#self.Link do - if self.Link[i][2]~=nil then - if self.Link[i][2]==self.ID then - table.remove(self.Link,i) - self.remove=function() end - self.Link=nil - self.ID=nil - return true - end - end - end - end - } - if name then - self.connections[name]=temp - end - return temp - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:tofile(path) - end - return c -end -multi.OnObjectCreated=multi:newConnection() -multi.OnObjectDestroyed=multi:newConnection() ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - self:Do_Order() - end - print("Did you call multi:Stop()? This method should not be used when using multi:mainloop()! You now need to restart the multiManager, by using multi:reboot() and calling multi:mainloop() again or by using multi:uManager()") -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - rawset(self,'Start',self.clock()) -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - function self:uManager(dt) - self:Do_Order() - end - self:Do_Order() - end -end ---Thread Setup Stuff -multi:setDomainName("Threads") -multi:setDomainName("Globals") --- Scheduler -multi.scheduler=multi:newUpdater() -multi.scheduler.Type="scheduler" -function multi.scheduler:setStep(n) - self.skip=tonumber(n) or 24 -end -multi.scheduler.Threads=multi:linkDomain("Threads") -multi.scheduler.Globals=multi:linkDomain("Globals") -multi.scheduler:OnUpdate(function(self) - for i=#self.Threads,1,-1 do - ret={} - if coroutine.status(self.Threads[i].thread)=="dead" then - table.remove(self.Threads,i) - else - if self.Threads[i].timer:Get()>=self.Threads[i].sleep then - if self.Threads[i].firstRunDone==false then - self.Threads[i].firstRunDone=true - self.Threads[i].timer:Start() - _,ret=coroutine.resume(self.Threads[i].thread,self.Threads[i].ref) - else - _,ret=coroutine.resume(self.Threads[i].thread,self.Globals) - end - if ret==true or ret==false then - print("Thread Ended!!!") - ret={} - end - end - if ret then - if ret[1]=="_kill_" then - table.remove(self.Threads,i) - elseif ret[1]=="_sleep_" then - self.Threads[i].timer:Reset() - self.Threads[i].sleep=ret[2] - elseif ret.Name then - self.Globals[ret.Name]=ret.Value - end - end - end - end -end) -multi.scheduler:setStep() -multi.scheduler:Pause() -multi.OnError=multi:newConnection() diff --git a/mulit/oldversions/MultiManager(1.4.1).lua b/mulit/oldversions/MultiManager(1.4.1).lua deleted file mode 100644 index b370e19..0000000 --- a/mulit/oldversions/MultiManager(1.4.1).lua +++ /dev/null @@ -1,1518 +0,0 @@ -if table.unpack then - unpack=table.unpack -end -function table.merge(t1, t2) - for k,v in pairs(t2) do - if type(v) == 'table' then - if type(t1[k] or false) == 'table' then - table.merge(t1[k] or {}, t2[k] or {}) - else - t1[k] = v - end - else - t1[k] = v - end - end - return t1 -end -_print=print -function print(...) - if not __SUPPRESSPRINTS then - _print(...) - end -end -multi = {} -multi.Version={'A',4,1}-- History: EventManager,EventManager+,MultiManager <-- Current After 6.3.0 Versioning scheme was altered. A.0.0 -multi.help=[[ -For a list of features do print(multi.Features) -For a list of changes do print(multi.changelog) -For current version do print(multi.Version) -For current stage do print(multi.stage) -For help do print(multi.help) :D -]] -multi.stage='stable' -multi.Features='Current Version: '..multi.Version[1]..'.'..multi.Version[2]..'.'..multi.Version[3]..' '..multi.stage..[[ -MultiManager has 19 Objects: # indicates most commonly used 1-19 1 being the most used by me -+Events #7 -+Alarms #2 -+Loops #3 -+Steps #4 -+TSteps #6 -+Triggers #16 -+Tasks #12 -+Connections #1 -- This is a rather new feature of this library, but has become the most useful for async handling. Knowing this is already 50% of this library -+Timers #14 -- this was tricky because these make up both Alarms and TSteps, but in purly using this standalone is almost non existent -+Jobs #11 -+Process #10 -+Conditions #15 -+Ranges #8 -+Threads #13 -+Functions #5 -+Queuers #17 -+Updaters #9 -+Watchers #18 -+CustomObjects #19 - -Constructors [Runners] ----------------------- Note: multi is the main Processor Obj It cannot be paused or destroyed (kinda) -ProcessObj=multi:newProcess([string: FILE defualt: nil]) -ProcessObj=multi:newQueuer([string: FILE defualt: nil]) - -NOTE: The multi namespace is also a ProcessObj - - -Constructors [ACTORS] ---------------------- Note: everything is a multiObj! -eventObj=multi:newEvent([function: TASK defualt: function() end]) -alarmObj=multi:newAlarm([number: SET defualt: 0]) -loopObj=multi:newLoop([function: FUNC]) -stepObj=multi:newStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SKIP defualt: 0]) -tstepObj=multi:newTStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SET defualt: 1]) -updaterObj=multi:newUpdater([number: SKIP defualt: 0]) -watcherObj=multi:newWatcher(table: NAMESPACE,string: NAME) -multiObj=multi:newCustomObject([table: OBJREF],[string: T='process']) - -Constructors [Semi-ACTORS] --------------------------- -multi:newJob(function: func,[string: name]) -multi:newRange(number: a,number: b,[number: c]) -multi:newCondition(func) -void=multi:newThread(string: name,function: func) - -Constructors [NON-ACTORS] -------------------------- -multi:newTrigger(function: func) -multi:newTask(function: func) -multi:newConnection() -multi:newTimer() -multi:newFunction(function: func) -]] -multi.changelog=[[Changelog starts at Version A.0.0 -New in A.0.0 - Nothing really however a changelog will now be recorded! Feel free to remove this extra strings if space is a requirement - version.major.minor -New in A.1.0 - Changed: multi:newConnection(protect) method - Changed the way you are able to interact with it by adding the __call metamethod - Old usage: - OnUpdate=multi:newConnection() - OnUpdate:connect(function(...) - print("Updating",...) - end) - OnUpdate:Fire(1,2,3) - New usage: notice that connect is no longer needed! Both ways still work! and always will work :) - OnUpdate=multi:newConnection() - OnUpdate(function(...) - print("Updating",...) - end) - OnUpdate:Fire(1,2,3) -New in A.2.0 (12/31/2016) - Added: - connectionobj.getConnection(name) - returns a list of an instance (or instances) of a single connect made with connectionobj:connect(func,name) or connectionobj(func,name) - if you can orginize data before hand you can route info to certain connections thus saving a lot of cpu time. NOTE: only one name per each connection... you can't have 2 of the same names in a dictonary... the last one will be used - Changed: obj=multi:newConnection() - obj:connect(func,name) and obj(func,name) - Added the name argument to allow indexing specific connection objects... Useful when creating an async library -New in A.3.0 (1/29/2017) - Added: - Load detection! - multi.threshold -- minimum amount of cycles that all mObjs should be allotted before the Manager is considered burdened. Defualt: 256 - multi.threstimed -- amount of time when counting the number of cycles, Greater gives a more accurate view of the load, but takes more time. Defualt: .001 - multi:setThreshold(n) -- method used to set multi.threshold - multi:setThrestimed(n) -- method used to set multi.threstimed - multi:getLoad() -- returns a number between 0 and 100 -New in A.4.0 (3/20/2017) - Added: - multiobj:reallocate(ProcessObj) -- changes the parent process of an object - ProcessObj:getController() -- returns the mThread so you can opperate on it like a multiobj - Example1: - require("multimanager") -- require the library - int1=multi:newProcess() -- create a process - int1.NAME="int1" -- give it a name for example purposes - int2=multi:newProcess() -- create another process to reallocate - int2.NAME="int2" -- name this a different name - step=int1:newTStep(1,10) -- create a TStep so we can slowly see what is going on - step:OnStep(function(p,s) -- connect to the onstep event - print(p,s.Parent.NAME) -- print the position and process name - end) - step:OnEnd(function(s) -- when the step ends lets reallocate it to the other process - if s.Parent.NAME=="int1" then -- lets only do this if it is in the int1 process - s:reallocate(int2) -- send it to int2 - s:Reset() -- reset the object - else - print("We are done!") - os.exit() -- end the program when int2 did its thing - end - end) - int1:Start() -- start process 1 - int2:Start() -- start process 2 - multi:mainloop() -- start the main loop - Fixed/Updated: - queuer=multi:newQueuer([string: file]) - Alarms now preform as they should on a queuer - Example2: - int=multi:newQueuer() - step=int:newTStep(1,10,1,.5) - alarm=int:newAlarm(2) - step2=int:newTStep(1,5,1,.5) - step:OnStep(function(p,s) - print(p) - end) - step2:OnStep(function(p,s) - print(p,"!") - end) - alarm:OnRing(function(a) - print("Ring1!!!") - end) - int:OnQueueCompleted(function(s) - s:Pause() - print("Done!") - os.exit() - end) - int:Start() - multi:mainloop() -New in A.4.1 (4/10/2017) - Change: - small change to the hold method to make it a bit more lightweight - Using a timer instead of an alarm object! - Limits to hold: - cannot hold more than 1 object at a time, and doing so could cause a deadlock! - Upcomming: - Threaded objects wrapped in corutines, so you can hold/sleep without problems! -]] -multi.__index = multi -multi.Mainloop={} -multi.Tasks={} -multi.Tasks2={} -multi.Garbage={} -multi.ender={} -multi.Children={} -multi.Paused={} -multi.Active=true -multi.fps=60 -multi.Id=-1 -multi.Type='mainprocess' -multi.Rest=0 -multi._type=type -multi.Jobs={} -multi.queue={} -multi.jobUS=2 -multi.clock=os.clock -multi.time=os.time -multi.LinkedPath=multi -multi.queuefinal=function(self) - self:Destroy() - if self.Parent.Mainloop[#self.Parent.Mainloop] then - if self.Parent.Mainloop[#self.Parent.Mainloop].Type=="alarm" then - self.Parent.Mainloop[#self.Parent.Mainloop]:Reset() - self.Parent.Mainloop[#self.Parent.Mainloop].Active=true - else - self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() - end - else - for i=1,#self.Parent.funcE do - self.Parent.funcE[i](self) - end - self.Parent:Remove() - end -end ---Do not change these ever...Any other number will not work (Unless you are using enablePriority2() then change can be made. Just ensure that Priority_Idle is the greatest and Priority_Core is 1!) -multi.Priority_Core=1 -multi.Priority_High=4 -multi.Priority_Above_Normal=16 -multi.Priority_Normal=64 -multi.Priority_Below_Normal=256 -multi.Priority_Low=1024 -multi.Priority_Idle=4096 -multi.PList={multi.Priority_Core,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Idle} -multi.PStep=1 ---^^^^ -multi.PriorityTick=1 -- Between 1 and 4 any greater and problems arise -multi.Priority=multi.Priority_Core -multi.threshold=256 -multi.threstimed=.001 -function multi:setThreshold(n) - self.threshold=n or 120 -end -function multi:setThrestimed(n) - self.threstimed=n or .001 -end -function multi:getLoad() - return multi:newFunction(function(self) - local sample=#multi.Mainloop - local FFloadtest=0 - multi:benchMark(multi.threstimed):OnBench(function(_,l3) FFloadtest=l3*(1/multi.threstimed) end) - self:hold(function() return FFloadtest~=0 end) - local val=FFloadtest/sample - if val>multi.threshold then - return 0 - else - return 100-((val/multi.threshold)*100) - end - end)() -end -function multi:setDomainName(name) - self[name]={} -end -function multi:linkDomain(name) - return self[name] -end -function multi:_Pause() - self.Active=false -end -function multi:setPriority(s) - if type(s)==number then - self.Priority=s - elseif type(s)=='string' then - if s:lower()=='core' or s:lower()=='c' then - self.Priority=self.Priority_Core - elseif s:lower()=='high' or s:lower()=='h' then - self.Priority=self.Priority_High - elseif s:lower()=='above' or s:lower()=='an' then - self.Priority=self.Priority_Above_Normal - elseif s:lower()=='normal' or s:lower()=='n' then - self.Priority=self.Priority_Normal - elseif s:lower()=='below' or s:lower()=='bn' then - self.Priority=self.Priority_Below_Normal - elseif s:lower()=='low' or s:lower()=='l' then - self.Priority=self.Priority_Low - elseif s:lower()=='idle' or s:lower()=='i' then - self.Priority=self.Priority_Idle - end - end -end --- System -function os.getOS() - if package.config:sub(1,1)=='\\' then - return 'windows' - else - return 'unix' - end -end -if os.getOS()=='windows' then - function os.sleep(n) - if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end - end -else - function os.sleep(n) - os.execute('sleep ' .. tonumber(n)) - end -end -function multi:getParentProcess() - return self.Mainloop[self.CID] -end -function multi:Stop() - self.Active=false -end -function multi:condition(cond) - if not self.CD then - self:Pause() - self.held=true - self.CD=cond.condition - elseif not(cond.condition()) then - self.held=false - self:Resume() - self.CD=nil - return false - end - self.Parent:Do_Order() - return true -end -function multi:isHeld() - return self.held -end -function multi.executeFunction(name,...) - if type(_G[name])=='function' then - _G[name](...) - else - print('Error: Not a function') - end -end -function multi:waitFor(obj) - local value=false - self.__waiting=function() - value=true - end - obj:connectFinal(self.__waiting) - self:hold(function() return value end) -end -function multi:reboot(r) - local before=collectgarbage('count') - self.Mainloop={} - self.Tasks={} - self.Tasks2={} - self.Garbage={} - self.Children={} - self.Paused={} - self.Active=true - self.Id=-1 - if r then - for i,v in pairs(_G) do - if type(i)=='table' then - if i.Parent and i.Id and i.Act then - i={} - end - end - end - end - collectgarbage() - local after=collectgarbage('count') - print([[Before rebooting total Ram used was ]]..before..[[Kb -After rebooting total Ram used is ]]..after..[[ Kb -A total of ]]..(before-after)..[[Kb was cleaned up]]) -end -function multi:getChildren() - return self.Mainloop -end ---Processor -function multi:getError() - if self.error then - return self.error - end -end -function multi:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:enablePriority() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PList[PS.PStep])%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>7 then - PS.PStep=1 - end - end -end -function multi:enablePriority2() - function self:Do_Order() - local Loop=self.Mainloop - _G.ID=0 - local PS=self - for _D=#Loop,1,-1 do - if Loop[_D] then - if (PS.PStep)%Loop[_D].Priority==0 then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end - end - PS.PStep=PS.PStep+1 - if PS.PStep>self.Priority_Idle then - PS.PStep=1 - end - end -end -multi.disablePriority=multi.unProtect -function multi:fromfile(path,int) - int=int or self - local test2={} - local test=bin.load(path) - local tp=test:getBlock('s') - if tp=='event' then - test2=int:newEvent(test:getBlock('f')) - local t=test:getBlock('t') - for i=1,#t do - test2:OnEvent(t[i]) - end - elseif tp=='alarm' then - test2=int:newAlarm(test:getBlock('n')) - elseif tp=='loop' then - test2=int:newLoop(test:getBlock('t')[1]) - elseif tp=='step' or tp=='tstep' then - local func=test:getBlock('t') - local funcE=test:getBlock('t') - local funcS=test:getBlock('t') - local tab=test:getBlock('t') - test2=int:newStep() - table.merge(test2,tab) - test2.funcE=funcE - test2.funcS=funcS - test2.func=func - elseif tp=='trigger' then - test2=int:newTrigger(test:getBlock('f')) - elseif tp=='connector' then - test2=int:newConnection() - test2.func=test:getBlock('t') - elseif tp=='timer' then - test2=int:newTimer() - test2.count=tonumber(test:getBlock('n')) - else - print('Error: The file you selected is not a valid multi file object!') - return false - end - return test2 -end -function multi:benchMark(sec,p) - local temp=self:newLoop(function(t,self) - if self.clock()-self.init>self.sec then - self.tt(self.sec,self.c) - self:Destroy() - else - self.c=self.c+1 - end - end) - temp.Priority=p or 1 - function temp:OnBench(func) - self.tt=func - end - self.tt=function() end - temp.sec=sec - temp.init=self.clock() - temp.c=0 - return temp -end -function multi:tofile(path) - local items=self:getChildren() - io.mkDir(io.getName(path)) - for i=1,#items do - items[i]:tofile(io.getName(path)..'\\item'..item[i]..'.dat') - end - local int=bin.new() - int:addBlock('process') - int:addBlock(io.getName(path)) - int:addBlock(#self.Mainloop) - int:addBlock(self.Active) - int:addBlock(self.Rest) - int:addBlock(self.Jobs) - int:tofile() -end -function multi.startFPSMonitior() - if not multi.runFPS then - multi.doFPS(s) - multi.runFPS=true - end -end -function multi.doFPS(s) - multi:benchMark(1):OnBench(doFPS) - if s then - multi.fps=s - end -end ---Helpers -function multi:isAnActor() - return ({watcher=true,tstep=true,step=true,updater=true,loop=true,alarm=true,event=true})[self.Type] -end -function multi:OnMainConnect(func) - table.insert(self.func,func) -end -function multi:protect() - function self:Do_Order() - local Loop=self.Mainloop - for _D=#Loop,1,-1 do - if Loop[_D]~=nil then - Loop[_D].Id=_D - self.CID=_D - local status, err=pcall(Loop[_D].Act,Loop[_D]) - if err and not(Loop[_D].error) then - Loop[_D].error=err - self.OnError:Fire(err,Loop[_D]) - end - end - end - end -end -function multi:unProtect() - local Loop=self.Mainloop - _G.ID=0 - for _D=#Loop,1,-1 do - if Loop[_D] then - if Loop[_D].Active then - Loop[_D].Id=_D - self.CID=_D - Loop[_D]:Act() - end - end - end -end -function multi:reallocate(o,n) - n=n or #o.Mainloop+1 - local int=self.Parent - self:Destroy() - self.Parent=o - table.insert(o.Mainloop,n,self) - self.Active=true -end -function multi:setJobSpeed(n) - self.jobUS=n -end -function multi:hasJobs() - return #self.Jobs>0,#self.Jobs -end -function multi:getJobs() - return #self.Jobs -end -function multi:removeJob(name) - for i=#self.Jobs,1,-1 do - if self.Jobs[i][2]==name then - table.remove(self.Jobs,i) - end - end -end -function multi:FreeMainEvent() - self.func={} -end -function multi:connectFinal(func) - if self.Type=='event' then - self:OnEvent(func) - elseif self.Type=='alarm' then - self:OnRing(func) - elseif self.Type=='step' or self.Type=='tstep' then - self:OnEnd(func) - else - print("Warning!!! "..self.Type.." doesn't contain a Final Connection State! Use "..self.Type..":Break(function) to trigger it's final event!") - self:OnBreak(func) - end -end -function multi:Break() - self:Pause() - self.Active=nil - for i=1,#self.ender do - if self.ender[i] then - self.ender[i](self) - end - end -end -function multi:OnBreak(func) - table.insert(self.ender,func) -end -function multi:isPaused() - return not(self.Active) -end -function multi:isActive() - return self.Active -end -function multi:getType() - return self.Type -end -function multi:Sleep(n) - self:hold(n) -end -function multi:Pause() - if self.Type=='mainprocess' then - print("You cannot pause the main process. Doing so will stop all methods and freeze your program! However if you still want to use multi:_Pause()") - else - self.Active=false - if self.Parent.Mainloop[self.Id]~=nil then - table.remove(self.Parent.Mainloop,self.Id) - table.insert(self.Parent.Paused,self) - self.PId=#self.Parent.Paused - end - end -end -function multi:Resume() - if self.Type=='process' or self.Type=='mainprocess' then - self.Active=true - local c=self:getChildren() - for i=1,#c do - c[i]:Resume() - end - else - if self:isPaused() then - table.remove(self.Parent.Paused,self.PId) - table.insert(self.Parent.Mainloop,self) - self.Id=#self.Parent.Mainloop - self.Active=true - end - end -end -function multi:resurrect() - table.insert(self.Parent.Mainloop,self) - self.Active=true -end -function multi:Destroy() - if self.Type=='process' or self.Type=='mainprocess' then - local c=self:getChildren() - for i=1,#c do - self.OnObjectDestroyed:Fire(c[i]) - c[i]:Destroy() - end - else - for i=1,#self.Parent.Mainloop do - if self.Parent.Mainloop[i]==self then - self.Parent.OnObjectDestroyed:Fire(self) - table.remove(self.Parent.Mainloop,i) - break - end - end - self.Active=false - end -end - -function multi:hold(task) - self:Pause() - self.held=true - if type(task)=='number' then - local timer=multi:newTimer() - timer:Start() - while timer:Get()=self.set then - self:Pause() - self.Active=false - for i=1,#self.func do - self.func[i](self) - end - end - end - function c:Resume() - self.Parent.Resume(self) - self.timer:Resume() - end - function c:Reset(n) - if n then self.set=n end - self:Resume() - self.timer:Reset() - end - function c:OnRing(func) - table.insert(self.func,func) - end - function c:Pause() - self.timer:Pause() - self.Parent.Pause(self) - end - self:create(c) - return c -end -function multi:newLoop(func) - local c=self:newBase() - c.Type='loop' - c.Start=self.clock() - if func then - c.func={func} - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - for i=1,#self.func do - self.func[i](self.Parent.clock()-self.Start,self) - end - end - function c:OnLoop(func) - table.insert(self.func,func) - end - self:create(c) - return c -end -function multi:newUpdater(skip) - local c=self:newBase() - c.Type='updater' - c.pos=1 - c.skip=skip or 1 - function c:Act() - if self.pos>=self.skip then - self.pos=0 - for i=1,#self.func do - self.func[i](self) - end - end - self.pos=self.pos+1 - end - function c:setSkip(n) - self.skip=n - end - c.OnUpdate=self.OnMainConnect - self:create(c) - return c -end -function multi:newStep(start,reset,count,skip) - local c=self:newBase() - think=1 - c.Type='step' - c.pos=start or 1 - c.endAt=reset or math.huge - c.skip=skip or 0 - c.spos=0 - c.count=count or 1*think - c.funcE={} - c.funcS={} - c.start=start or 1 - if start~=nil and reset~=nil then - if start>reset then - think=-1 - end - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self~=nil then - if self.spos==0 then - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - self.spos=self.spos+1 - if self.spos>=self.skip then - self.spos=0 - end - end - c.Reset=c.Resume - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,1,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Update(start,reset,count,skip) - self.start=start or self.start - self.endAt=reset or self.endAt - self.skip=skip or self.skip - self.count=count or self.count - self:Resume() - end - self:create(c) - return c -end -function multi:newTStep(start,reset,count,set) - local c=self:newBase() - think=1 - c.Type='tstep' - c.Priority=self.Priority_Low - c.start=start or 1 - local reset = reset or math.huge - c.endAt=reset - c.pos=start or 1 - c.skip=skip or 0 - c.count=count or 1*think - c.funcE={} - c.timer=self.clock() - c.set=set or 1 - c.funcS={} - function c:Update(start,reset,count,set) - self.start=start or self.start - self.pos=self.start - self.endAt=reset or self.endAt - self.set=set or self.set - self.count=count or self.count or 1 - self.timer=self.clock() - self:Resume() - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:addBlock(self.funcE) - m:addBlock(self.funcS) - m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) - m:addBlock(self.Active) - m:tofile(path) - end - function c:Act() - if self.clock()-self.timer>=self.set then - self:Reset() - if self.pos==self.start then - for fe=1,#self.funcS do - self.funcS[fe](self) - end - end - for i=1,#self.func do - self.func[i](self.pos,self) - end - self.pos=self.pos+self.count - if self.pos-self.count==self.endAt then - self:Pause() - for fe=1,#self.funcE do - self.funcE[fe](self) - end - self.pos=self.start - end - end - end - function c:OnStart(func) - table.insert(self.funcS,func) - end - function c:OnStep(func) - table.insert(self.func,func) - end - function c:OnEnd(func) - table.insert(self.funcE,func) - end - function c:Break() - self.Active=nil - end - function c:Reset(n) - if n then self.set=n end - self.timer=self.clock() - self:Resume() - end - self:create(c) - return c -end -function multi:newWatcher(namespace,name) - local function WatcherObj(ns,n) - if self.Type=='queue' then - print("Cannot create a watcher on a queue! Creating on 'multi' instead!") - self=multi - end - local c=self:newBase() - c.Type='watcher' - c.ns=ns - c.n=n - c.cv=ns[n] - function c:OnValueChanged(func) - table.insert(self.func,func) - end - function c:Act() - if self.cv~=self.ns[self.n] then - for i=1,#self.func do - self.func[i](self,self.cv,self.ns[self.n]) - end - self.cv=self.ns[self.n] - end - end - self:create(c) - return c - end - if type(namespace)~='table' and type(namespace)=='string' then - return WatcherObj(_G,namespace) - elseif type(namespace)=='table' and (type(name)=='string' or 'number') then - return WatcherObj(namespace,name) - else - print('Warning, invalid arguments! Nothing returned!') - end -end --- Constructors [SEMI-ACTORS] -function multi:newThread(name,func) - local c={} - c.ref={} - c.Name=name - c.thread=coroutine.create(func) - c.sleep=1 - c.firstRunDone=false - c.timer=multi.scheduler:newTimer() - c.ref.Globals=self:linkDomain("Globals") - function c.ref:send(name,val) - ret=coroutine.yield({Name=name,Value=val}) - self:syncGlobals(ret) - end - function c.ref:get(name) - return self.Globals[name] - end - function c.ref:kill() - err=coroutine.yield({"_kill_"}) - if err then - error("Failed to kill a thread! Exiting...") - end - end - function c.ref:sleep(n) - if type(n)=="function" then - ret=coroutine.yield({"_hold_",n}) - self:syncGlobals(ret) - elseif type(n)=="number" then - n = tonumber(n) or 0 - ret=coroutine.yield({"_sleep_",n}) - self:syncGlobals(ret) - else - error("Invalid Type for sleep!") - end - end - function c.ref:syncGlobals(v) - self.Globals=v - end - table.insert(self:linkDomain("Threads"),c) - if not multi.scheduler:isActive() then - multi.scheduler:Resume() - end -end -function multi:newJob(func,name) - if not(self.Type=='mainprocess' or self.Type=='process') then error('Can only create an object on multi or an interface obj') return false end - local c = {} - if self.Type=='process' then - setmetatable(c, self.Parent) - else - setmetatable(c, self) - end - c.Active=true - c.func={} - c.Id=0 - c.PId=0 - c.Parent=self - c.Type='job' - c.trigfunc=func or function() end - function c:Act() - self:trigfunc(self) - end - table.insert(self.Jobs,{c,name}) - if self.JobRunner==nil then - self.JobRunner=self:newAlarm(self.jobUS) - self.JobRunner:OnRing(function(self) - if #self.Parent.Jobs>0 then - if self.Parent.Jobs[1] then - self.Parent.Jobs[1][1]:Act() - table.remove(self.Parent.Jobs,1) - end - end - self:Reset(self.Parent.jobUS) - end) - end -end -function multi:newRange() - local selflink=self - local temp={ - getN = function(self) selflink:Do_Order() self.n=self.n+self.c if self.n>self.b then self.Link.held=false self.Link:Resume() return nil end return self.n end, - } - setmetatable(temp,{ - __call=function(self,a,b,c) - self.c=c or 1 - self.n=a-self.c - self.a=a - self.b=b - self.Link=selflink--.Parent.Mainloop[selflink.CID] or - self.Link:Pause() - self.Link.held=true - return function() return self:getN() end - end - }) - self:create(temp) - return temp -end -function multi:newCondition(func) - local c={['condition']=func} - self:create(c) - return c -end --- Constructors [NON-ACTORS] -function multi:newFunction(func) - local c={} - c.func=func - mt={ - __index=multi, - __call=function(self,...) if self.Active then return self:func(...) end local t={...} return "PAUSED" end - } - c.Parent=self - function c:Pause() - self.Active=false - end - function c:Resume() - self.Active=true - end - setmetatable(c,mt) - self:create(c) - return c -end -function multi:newTimer() - local c={} - c.Type='timer' - c.time=0 - c.count=0 - function c:Start() - self.time=os.clock() - end - function c:Get() - return (os.clock()-self.time)+self.count - end - c.Reset=c.Start - function c:Pause() - self.time=self:Get() - end - function c:Resume() - self.time=os.clock()-self.time - end - function c:tofile(path) - local m=bin.new() - self.count=self.count+self:Get() - m:addBlock(self.Type) - m:addBlock(self.count) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newTask(func) - table.insert(self.Tasks,func) -end -function multi:newTrigger(func) - local c={} - c.Type='trigger' - c.trigfunc=func or function() end - function c:Fire(...) - self:trigfunc(self,...) - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.trigfunc) - m:tofile(path) - end - self:create(c) - return c -end -function multi:newConnection(protect) - local c={} - setmetatable(c,{__call=function(self,...) self:connect(...) end}) - c.Type='connector' - c.func={} - c.ID=0 - c.protect=protect or true - c.connections={} - c.fconnections={} - c.FC=0 - function c:fConnect(func) - local temp=self:connect(func) - table.insert(self.fconnections,temp) - self.FC=self.FC+1 - end - function c:getConnection(name,ingore) - if ingore then - return self.connections[name] or { - Fire=function() end -- if the connection doesn't exist lets call all of them or silently ingore - } - else - return self.connections[name] or self - end - end - function c:Fire(...) - local ret={} - for i=#self.func,1,-1 do - if self.protect then - local temp={pcall(self.func[i][1],...)} - if temp[1] then - table.remove(temp,1) - table.insert(ret,temp) - else - print(temp[2]) - end - else - table.insert(ret,{self.func[i][1](...)}) - end - end - return ret - end - function c:bind(t) - self.func=t - end - function c:remove() - self.func={} - end - function c:connect(func,name) - self.ID=self.ID+1 - table.insert(self.func,1,{func,self.ID}) - local temp = { - Link=self.func, - func=func, - ID=self.ID, - Parent=self, - Fire=function(self,...) ---~ if self.Parent.FC>0 then ---~ for i=1,#self.Parent.FC do ---~ self.Parent.FC[i]:Fire(...) ---~ end ---~ end - if self.Parent.protect then - local t=pcall(self.func,...) - if t then - return t - end - else - return self.func(...) - end - end, - remove=function(self) - for i=1,#self.Link do - if self.Link[i][2]~=nil then - if self.Link[i][2]==self.ID then - table.remove(self.Link,i) - self.remove=function() end - self.Link=nil - self.ID=nil - return true - end - end - end - end - } - if name then - self.connections[name]=temp - end - return temp - end - function c:tofile(path) - local m=bin.new() - m:addBlock(self.Type) - m:addBlock(self.func) - m:tofile(path) - end - return c -end -multi.OnObjectCreated=multi:newConnection() -multi.OnObjectDestroyed=multi:newConnection() ---Managers -function multi:mainloop() - for i=1,#self.Tasks do - self.Tasks[i](self) - end - rawset(self,'Start',self.clock()) - while self.Active do - self:Do_Order() - end - print("Did you call multi:Stop()? This method should not be used when using multi:mainloop()! You now need to restart the multiManager, by using multi:reboot() and calling multi:mainloop() again or by using multi:uManager()") -end -function multi._tFunc(self,dt) - for i=1,#self.Tasks do - self.Tasks[i](self) - end - if dt then - self.pump=true - end - self.pumpvar=dt - rawset(self,'Start',self.clock()) -end -function multi:uManager(dt) - if self.Active then - self:oneTime(self._tFunc,self,dt) - function self:uManager(dt) - self:Do_Order() - end - self:Do_Order() - end -end ---Thread Setup Stuff -multi:setDomainName("Threads") -multi:setDomainName("Globals") --- Scheduler -multi.scheduler=multi:newUpdater() -multi.scheduler.Type="scheduler" -function multi.scheduler:setStep(n) - self.skip=tonumber(n) or 24 -end -multi.scheduler.Threads=multi:linkDomain("Threads") -multi.scheduler.Globals=multi:linkDomain("Globals") -multi.scheduler:OnUpdate(function(self) - for i=#self.Threads,1,-1 do - ret={} - if coroutine.status(self.Threads[i].thread)=="dead" then - table.remove(self.Threads,i) - else - if self.Threads[i].timer:Get()>=self.Threads[i].sleep then - if self.Threads[i].firstRunDone==false then - self.Threads[i].firstRunDone=true - self.Threads[i].timer:Start() - _,ret=coroutine.resume(self.Threads[i].thread,self.Threads[i].ref) - else - _,ret=coroutine.resume(self.Threads[i].thread,self.Globals) - end - if ret==true or ret==false then - print("Thread Ended!!!") - ret={} - end - end - if ret then - if ret[1]=="_kill_" then - table.remove(self.Threads,i) - elseif ret[1]=="_sleep_" then - self.Threads[i].timer:Reset() - self.Threads[i].sleep=ret[2] - elseif ret[1]=="_hold_" then - self.Threads[i].timer:Reset() - self.Threads[i].sleep=math.huge - local event=multi:newEvent(ret[2]) - event.link=self.Threads[i] - event:OnEvent(function(evnt) - evnt.link.sleep=0 - end) - elseif ret.Name then - self.Globals[ret.Name]=ret.Value - end - end - end - end -end) -multi.scheduler:setStep() -multi.scheduler:Pause() -multi.OnError=multi:newConnection() ----------TESTS -multi:newThread("test",function(ref) - while true do - print(">!") - ref:sleep(1) - end -end) -multi:newThread("test",function(ref) - while true do - print("!<") - ref:sleep(1) - end -end) -multi:mainloop() diff --git a/mulit/rockspecs/multi-1.8-2.rockspec b/mulit/rockspecs/multi-1.8-2.rockspec deleted file mode 100644 index 6ffbdf9..0000000 --- a/mulit/rockspecs/multi-1.8-2.rockspec +++ /dev/null @@ -1,30 +0,0 @@ -package = "multi" -version = "1.8-2" -source = { - url = "git://github.com/rayaman/multi.git", - tag = "v1.8.2", -} -description = { - summary = "Lua Multi tasking library", - detailed = [[ - This library contains many methods for multi tasking. From simple side by side code using multi objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 - ]], - homepage = "https://github.com/rayaman/multi", - license = "MIT" -} -dependencies = { - "lua >= 5.1, < 5.2" -} -build = { - type = "builtin", - modules = { - -- Note the required Lua syntax when listing submodules as keys - ["multi.init"] = "multi/init.lua", - ["multi.all"] = "multi/all.lua", - ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", - ["multi.compat.love2d"] = "multi/compat/love2d.lua", - ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", - ["multi.integration.loveManager"] = "multi/integration/loveManager.lua", - ["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua" - } -} \ No newline at end of file diff --git a/mulit/rockspecs/multi-1.8-3.rockspec b/mulit/rockspecs/multi-1.8-3.rockspec deleted file mode 100644 index e3e152f..0000000 --- a/mulit/rockspecs/multi-1.8-3.rockspec +++ /dev/null @@ -1,30 +0,0 @@ -package = "multi" -version = "1.8-3" -source = { - url = "git://github.com/rayaman/multi.git", - tag = "v1.8.3", -} -description = { - summary = "Lua Multi tasking library", - detailed = [[ - This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 - ]], - homepage = "https://github.com/rayaman/multi", - license = "MIT" -} -dependencies = { - "lua >= 5.1, < 5.2" -} -build = { - type = "builtin", - modules = { - -- Note the required Lua syntax when listing submodules as keys - ["multi.init"] = "multi/init.lua", - ["multi.all"] = "multi/all.lua", - ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", - ["multi.compat.love2d"] = "multi/compat/love2d.lua", - ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", - ["multi.integration.loveManager"] = "multi/integration/loveManager.lua", - ["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua" - } -} \ No newline at end of file diff --git a/mulit/rockspecs/multi-1.8-4.rockspec b/mulit/rockspecs/multi-1.8-4.rockspec deleted file mode 100644 index 07d2b5a..0000000 --- a/mulit/rockspecs/multi-1.8-4.rockspec +++ /dev/null @@ -1,30 +0,0 @@ -package = "multi" -version = "1.8-4" -source = { - url = "git://github.com/rayaman/multi.git", - tag = "v1.8.4", -} -description = { - summary = "Lua Multi tasking library", - detailed = [[ - This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 - ]], - homepage = "https://github.com/rayaman/multi", - license = "MIT" -} -dependencies = { - "lua >= 5.1, < 5.2" -} -build = { - type = "builtin", - modules = { - -- Note the required Lua syntax when listing submodules as keys - ["multi.init"] = "multi/init.lua", - ["multi.all"] = "multi/all.lua", - ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", - ["multi.compat.love2d"] = "multi/compat/love2d.lua", - ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", - ["multi.integration.loveManager"] = "multi/integration/loveManager.lua", - ["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua" - } -} \ No newline at end of file diff --git a/mulit/rockspecs/multi-1.8-5.rockspec b/mulit/rockspecs/multi-1.8-5.rockspec deleted file mode 100644 index 808cd24..0000000 --- a/mulit/rockspecs/multi-1.8-5.rockspec +++ /dev/null @@ -1,30 +0,0 @@ -package = "multi" -version = "1.8-5" -source = { - url = "git://github.com/rayaman/multi.git", - tag = "v1.8.5", -} -description = { - summary = "Lua Multi tasking library", - detailed = [[ - This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 - ]], - homepage = "https://github.com/rayaman/multi", - license = "MIT" -} -dependencies = { - "lua >= 5.1, < 5.2" -} -build = { - type = "builtin", - modules = { - -- Note the required Lua syntax when listing submodules as keys - ["multi.init"] = "multi/init.lua", - ["multi.all"] = "multi/all.lua", - ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", - ["multi.compat.love2d"] = "multi/compat/love2d.lua", - ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", - ["multi.integration.loveManager"] = "multi/integration/loveManager.lua", - ["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua" - } -} \ No newline at end of file diff --git a/mulit/rockspecs/multi-1.8-6.rockspec b/mulit/rockspecs/multi-1.8-6.rockspec deleted file mode 100644 index 1c64eda..0000000 --- a/mulit/rockspecs/multi-1.8-6.rockspec +++ /dev/null @@ -1,30 +0,0 @@ -package = "multi" -version = "1.8-6" -source = { - url = "git://github.com/rayaman/multi.git", - tag = "v1.8.6", -} -description = { - summary = "Lua Multi tasking library", - detailed = [[ - This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 due to love2d and lua lanes being lua 5.1 only! - ]], - homepage = "https://github.com/rayaman/multi", - license = "MIT" -} -dependencies = { - "lua >= 5.1, < 5.2" -} -build = { - type = "builtin", - modules = { - -- Note the required Lua syntax when listing submodules as keys - ["multi.init"] = "multi/init.lua", - ["multi.all"] = "multi/all.lua", - ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", - ["multi.compat.love2d"] = "multi/compat/love2d.lua", - ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", - ["multi.integration.loveManager"] = "multi/integration/loveManager.lua", - ["multi.integration.shared"] = "multi/integration/shared.lua" - } -} \ No newline at end of file