Skip to content
This repository has been archived by the owner on Apr 9, 2019. It is now read-only.

dev/0.1.0 #1

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2337d87
initial commit
inversion Sep 3, 2018
0a86ac3
Merge branch 'master' into dev/0.1.0
inversion Sep 6, 2018
e5a41b6
add infrastructure for lemur tests
inversion Sep 6, 2018
53abed3
reformat code
inversion Sep 6, 2018
5c9b0ab
delete old coverage data
inversion Sep 11, 2018
694f508
Add a LoadRobase function for tests
ckdavid Oct 4, 2018
cacf0b0
Update the lemur submodule to use CK's fork
ckdavid Oct 4, 2018
cb37a6b
Add ProjectileService
ckdavid Oct 4, 2018
056a52d
Remove pointless module loading code from LoadRobase
ckdavid Oct 4, 2018
510b22c
Delete the majority of Robase
ckdavid Oct 4, 2018
92c24ce
Update .luacheckrc
ckdavid Oct 4, 2018
99973e1
Style fix
ckdavid Oct 4, 2018
e3dae9b
Merge pull request #4 from CodeKingdomsTeam/dev/projectiles
ckdavid Oct 4, 2018
2b6d35d
add debounce util
inversion Oct 5, 2018
dff95a0
add assertions for debounce usage
inversion Oct 8, 2018
14f3d07
add empty init.lua for compatibility with plugin loader
inversion Oct 8, 2018
221dd25
Fix varargs usage within Roblox
inversion Oct 8, 2018
6299a4b
Update lemur reference
Hugheth Oct 25, 2018
a94b606
Add HSM and FSM to robase along with HSM tests
ckdavid Nov 1, 2018
54440d4
Update lemur submodule
ckdavid Nov 2, 2018
09efe90
Remove print statement
ckdavid Nov 2, 2018
0bd35d4
Make tests write report to file to avoid noise from stdout
ckdavid Nov 2, 2018
6618f73
Make debounce use seconds clearly
Hugheth Nov 28, 2018
94557cc
Minor fixes
ckdavid Nov 30, 2018
abceefd
Add lua-fsm as a submodule
ckdavid Nov 30, 2018
fc4e620
Update utils ref in Robase
Hugheth Dec 4, 2018
0160941
PR fixes
ckdavid Dec 6, 2018
d6ba354
Merge pull request #6 from CodeKingdomsTeam/robase-hsm
ckdavid Dec 6, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ luac.out
/robase-venv

# JUnit test report
/testReport.xml
/junit-report*.xml

node_modules

9 changes: 9 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[submodule "modules/lemur"]
path = modules/lemur
url = https://github.com/CodeKingdomsTeam/lemur.git
[submodule "modules/Utils"]
path = modules/Utils
url = https://github.com/CodeKingdomsTeam/lua-utils
[submodule "modules/lua-fsm"]
path = modules/lua-fsm
url = https://github.com/unindented/lua-fsm
9 changes: 9 additions & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
exclude_files = {
".luacheckrc"
}

stds.roblox = {
read_globals = {
-- global functions
Expand All @@ -18,6 +22,7 @@ stds.roblox = {
"shared",
"workspace",
"plugin",
"ypcall",
-- types
"Axes",
"BrickColor",
Expand Down Expand Up @@ -63,6 +68,10 @@ stds.roblox = {
}
}

-- Does not correctly detect usage of ...
files["lib/Utils.lua"] = {ignore = {"212"}}
files["spec/Utils_spec.lua"] = {ignore = {"212"}}

std = "lua51+roblox"

files["spec/*.lua"] = {
Expand Down
11 changes: 8 additions & 3 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ pipeline {

stage('Tests') {
steps {
sh 'rm -f testReport.xml cobertura.xml && ./test.sh --verbose --coverage --output junit > testReport.xml && ./lua_install/bin/luacov-cobertura -o cobertura.xml'
sh '''
rm -f luacov.stats.* luacov.report.* junit-report.xml cobertura.xml && \
./test.sh --verbose --coverage --output junit -Xoutput junit-report.xml && \
sed -i '/^\\s*$/d' junit-report.xml && \
./lua_install/bin/luacov-cobertura -o cobertura.xml
'''
}
post {
failure {
Expand Down Expand Up @@ -79,7 +84,7 @@ pipeline {

post {
always {
junit "testReport.xml"
junit "junit-report.xml"
cobertura coberturaReportFile: 'cobertura.xml'
}
failure {
Expand All @@ -93,4 +98,4 @@ pipeline {
}
}

}
}
119 changes: 119 additions & 0 deletions lib/Hsm.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
local Fsm = require(script.Parent.Fsm)

local Hsm = {}

function Hsm.new()
local hsm = {}
hsm.fsms = {}

local function hsmEvent(event)
local handlingFsmIndex = nil
for i = #hsm.fsms, 1, -1 do
if hsm.fsms[i][event] then
handlingFsmIndex = i
end
end
if handlingFsmIndex == nil then
-- There is no such action on any fsm, so return nil.
return nil
else
return function(...)
-- Remove nested FSMs we won't need now.
for i = #hsm.fsms, handlingFsmIndex + 1, -1 do
-- Call the on_leave_ function for the current state, if there is one.
local fsm = hsm.fsms[i]
if fsm.current and fsm["on_leave_" .. fsm.current] then
fsm["on_leave_" .. fsm.current](fsm, event, fsm.current, "none", ...)
end

table.remove(hsm.fsms)
end

-- Call the event function on the FSM that can handle it.
local handlingFsm = hsm.fsms[handlingFsmIndex]
handlingFsm[event](...)
end
end
end

setmetatable(
hsm,
{
__index = function(_, key)
return Hsm[key] or hsmEvent(key)
end
}
)

return hsm
end

-- Adds an FSM representing a substate to the HSM's stack of FSMs.
function Hsm:pushFsm(fsmConfig)
-- Defer the initial state until the FSM is added to the HSM.
local initial = fsmConfig.initial
if type(initial) == "string" then
initial = {state = initial}
elseif not initial then
initial = {state = "none"}
else
assert(type(initial) == "table")
end
initial.event = "init"
initial.defer = true
fsmConfig.initial = initial

local fsm = Fsm.create(fsmConfig)
table.insert(self.fsms, fsm)

-- Call the init event created above to trigger the transition to the initial state.
fsm.init()
end

-- Returns an array of the current substates for the HSM, starting with
-- the root FSM's substate.
function Hsm:current()
local currentStates = {}
for _, fsm in ipairs(self.fsms) do
table.insert(currentStates, fsm.current)
end
return currentStates
end

-- Returns whether the HSM has the given state for one of
-- its substates.
function Hsm:is(state)
for _, fsm in ipairs(self.fsms) do
if fsm.is(state) then
return true
end
end
return false
end

-- Returns whether the HSM can handle the given event.
function Hsm:can(event)
for _, fsm in ipairs(self.fsms) do
if fsm[event] and fsm.can(event) then
return true
end
end
return false
end

function Hsm:cannot(event)
return not self:can(event)
end

-- Returns an array of all of the allowed transitions for the HSM.
function Hsm:transitions()
local transitions = {}
for _, fsm in ipairs(self.fsms) do
for transition in ipairs(fsm.transitions()) do
table.insert(transitions, transition)
end
end
return transitions
end

return Hsm
32 changes: 32 additions & 0 deletions lib/Logger.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
local Logger = {}

Logger.LOG_LEVEL = {
AUTO = "Auto",
TRACE = "Trace",
DEBUG = "Debug",
LOG = "Log",
WARN = "Warn",
ERROR = "Error"
}

function Logger.Raise(level, ...) --: string, ...any => void
print("[", level, "] ", ...)
end

function Logger.Trace(...) --: ...any => void
Logger.Raise("Trace", ...)
end
function Logger.Debug(...) --: ...any => void
Logger.Raise("Debug", ...)
end
function Logger.Log(...) --: ...any => void
Logger.Raise("Log", ...)
end
function Logger.Warn(...) --: ...any => void
Logger.Raise("Warn", ...)
end
function Logger.Error(...) --: ...any => void
Logger.Raise("Error", ...)
end

return Logger
113 changes: 113 additions & 0 deletions lib/ProjectileService.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
local RunService = game:GetService("RunService")
local Logger = require(script.Parent.Logger)

local function cloneFromServerStorage(projectileName)
local projectilePrefab = game.ServerStorage:FindFirstChild(projectileName)

if typeof(projectilePrefab) ~= "Instance" then
Logger.Error("Could not find projectile part " .. projectileName)
elseif projectilePrefab.ClassName ~= "Part" then
Logger.Error("Projectile " .. projectileName .. " is not a Part")
else
return projectilePrefab:Clone()
end
end

local ProjectileService = {
MAX_FLIGHT_TIME = 10
}

function ProjectileService:FireProjectile(projectileName, from, velocity, options)
options = options or {}
local position = from
local ignoreList = options.ignoreList or {}

local gravity = game.Workspace.Gravity
if typeof(options.gravityMultiplier) == "number" then
gravity = gravity * options.gravityMultiplier
end

local ignoreWater = false
if typeof(options.ignoreWater) == "boolean" then
ignoreWater = options.ignoreWater
end

local projectile = cloneFromServerStorage(projectileName)
if not projectile then
-- The projectile failed to be cloned, so exit.
return
end

local baseRotation = projectile.CFrame - projectile.Position
projectile.CFrame = CFrame.new(position, position + velocity) * baseRotation
projectile.Parent = game.Workspace

-- Remove the projectile from the control of the physics engine by anchoring it,
-- as its path will be controlled by this service.
projectile.Anchored = true
projectile.CanCollide = false

-- The connection used for the stepped update of the projectile.
local steppedUpdate
local startTime = tick()
local lastStepTime = startTime

local function updateProjectile()
local currentTime = tick()
local totalFlightTime = currentTime - startTime
if totalFlightTime > self.MAX_FLIGHT_TIME then
-- The projectile has been in flight for longer than the maximum time, so
-- something has probably gone wrong. Remove it from the control of this
-- service.
projectile.Anchored = false
steppedUpdate:Disconnect()
return
end
local timeDelta = currentTime - lastStepTime
local bulletRay = Ray.new(position, velocity * timeDelta)
local hitPart, hitPosition, hitNormal =
workspace:FindPartOnRayWithIgnoreList(bulletRay, ignoreList, false, ignoreWater)
if hitPart then
-- The projectile has hit something. Move it to the point of collision, stop this service from
-- updating it any more and fire the projectile's Hit event if it has one.
projectile.CFrame = CFrame.new(hitPosition, hitPosition + velocity) * baseRotation
steppedUpdate:Disconnect()
local hitEvent = projectile:FindFirstChild("Hit")
if typeof(hitEvent) == "Instance" and hitEvent.ClassName == "BindableEvent" then
hitEvent:Fire(hitPart, hitPosition, hitNormal, velocity)
end
else
projectile.CFrame = CFrame.new(position, position + velocity) * baseRotation
-- Apply acceleration due to gravity.
velocity = velocity - (Vector3.new(0, gravity, 0) * timeDelta)
position = position + velocity * timeDelta
end
lastStepTime = currentTime
end

updateProjectile()
steppedUpdate = RunService.Stepped:Connect(updateProjectile)

return projectile, steppedUpdate
end

function ProjectileService:ConnectToEvent(eventName)
if not eventName then
eventName = "FireProjectile"
end

local fireProjectileEvent = game.ReplicatedStorage:FindFirstChild(eventName)
if not fireProjectileEvent then
fireProjectileEvent = Instance.new("RemoteEvent")
fireProjectileEvent.Name = eventName
fireProjectileEvent.Parent = game.ReplicatedStorage
end

return fireProjectileEvent.OnServerEvent:Connect(
function(_, ...)
self:FireProjectile(...)
end
)
end

return ProjectileService
34 changes: 34 additions & 0 deletions lib/Utils.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
local Utils = {}

--[[
Creates a debounced function that delays invoking fn until after secondsDelay seconds have elapsed since the last time the debounced function was invoked.
]]
function Utils.Debounce(fn, secondsDelay)
assert(type(fn) == "function" or (type(fn) == "table" and getmetatable(fn) and getmetatable(fn).__call ~= nil))
assert(type(secondsDelay) == "number")

local lastInvocation = 0
local lastResult = nil

return function(...)
local args = {...}

lastInvocation = lastInvocation + 1

local thisInvocation = lastInvocation
delay(
secondsDelay,
function()
if thisInvocation ~= lastInvocation then
return
end

lastResult = fn(unpack(args))
end
)

return lastResult
end
end

return Utils
Empty file added lib/init.lua
Empty file.
1 change: 1 addition & 0 deletions modules/Utils
Submodule Utils added at 7e7038
1 change: 1 addition & 0 deletions modules/lemur
Submodule lemur added at fceff7
1 change: 1 addition & 0 deletions modules/lua-fsm
Submodule lua-fsm added at 4cca10
Loading