From 359ebab56a7123512c40daad3fd2fc60fbcc098f Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Tue, 18 Mar 2025 14:35:51 -0400 Subject: [PATCH] Click-to-place somewhat working. This is a 65% decent stopping point before I completely hose it trying to animate the ball. --- assets/images/GolferDown.png | Bin 0 -> 909 bytes assets/images/GolferLeft.png | Bin 0 -> 568 bytes assets/images/GolferRight.png | Bin 901 -> 569 bytes assets/images/GolferUp.png | Bin 0 -> 551 bytes generated/assets.lua | 12 + lib/inspect.lua | 367 +++++++++++++++++++++++++++++++ lib/luaunit.lua | 5 +- lib/preprocess.lua | 59 +++-- lib/tiny.lua | 9 +- main.lua | 63 ++++-- systems/collision-resolution.lua | 33 ++- systems/draw.lua | 3 +- systems/input.lua | 46 +++- systems/rounds.lua | 142 +++++++----- tiny-types.lua | 23 +- 15 files changed, 642 insertions(+), 120 deletions(-) create mode 100644 assets/images/GolferDown.png create mode 100644 assets/images/GolferLeft.png create mode 100644 assets/images/GolferUp.png create mode 100644 lib/inspect.lua diff --git a/assets/images/GolferDown.png b/assets/images/GolferDown.png new file mode 100644 index 0000000000000000000000000000000000000000..ba9aaccd9d598e03be745174cdeccec317e72cd6 GIT binary patch literal 909 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 LNkvXXu0mjfJ$!@= diff --git a/assets/images/GolferUp.png b/assets/images/GolferUp.png new file mode 100644 index 0000000000000000000000000000000000000000..7f9a68f022c07354a11b7a824653e61f174af4f5 GIT binary patch literal 551 zcmeAS@N?(olHy`uVBq!ia0vp^J|N7&1|*M957Y)yjKx9jPK-BC>eK@{Ea{HEjtmSN z`?>!lvI6-E$sR$z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD8ZKG z?e4rAc(aMx*A)!m(^`G7}=ed253D``_D5ump)rfUt5;G@KAp}F7= self.depth then + puts(buf, "{...}") + else + if self.cycles[t] > 1 then + puts(buf, fmt("<%d>", self:getId(t))) + end + + local keys, keysLen, seqLen = getKeys(t) + + puts(buf, "{") + self.level = self.level + 1 + + for i = 1, seqLen + keysLen do + if i > 1 then + puts(buf, ",") + end + if i <= seqLen then + puts(buf, " ") + self:putValue(t[i]) + else + local k = keys[i - seqLen] + tabify(self) + if isIdentifier(k) then + puts(buf, k) + else + puts(buf, "[") + self:putValue(k) + puts(buf, "]") + end + puts(buf, " = ") + self:putValue(t[k]) + end + end + + local mt = getmetatable(t) + if type(mt) == "table" then + if seqLen + keysLen > 0 then + puts(buf, ",") + end + tabify(self) + puts(buf, " = ") + self:putValue(mt) + end + + self.level = self.level - 1 + + if keysLen > 0 or type(mt) == "table" then + tabify(self) + elseif seqLen > 0 then + puts(buf, " ") + end + + puts(buf, "}") + end + else + puts(buf, fmt("<%s %d>", tv, self:getId(v))) + end +end + +function inspect.inspect(root, options) + options = options or {} + + local depth = options.depth or math.huge + local newline = options.newline or "\n" + local indent = options.indent or " " + local process = options.process + + if process then + root = processRecursive(process, root, {}, {}) + end + + local cycles = {} + countCycles(root, cycles) + + local inspector = setmetatable({ + buf = { n = 0 }, + ids = {}, + cycles = cycles, + depth = depth, + level = 0, + newline = newline, + indent = indent, + }, Inspector_mt) + + inspector:putValue(root) + + return table.concat(inspector.buf) +end + +setmetatable(inspect, { + __call = function(_, root, options) + return inspect.inspect(root, options) + end, +}) + +_G.Inspect = inspect +return inspect diff --git a/lib/luaunit.lua b/lib/luaunit.lua index fa8ed9b..ec265e8 100644 --- a/lib/luaunit.lua +++ b/lib/luaunit.lua @@ -609,9 +609,8 @@ function M.adjust_err_msg_with_iter(err_msg, iter_msg) end if - (err_msg:find(M.SKIP_PREFIX) == 1) or ( - err_msg:match("(" .. RE_FILE_LINE .. ")" .. M.SKIP_PREFIX .. ".*") ~= nil - ) + (err_msg:find(M.SKIP_PREFIX) == 1) + or (err_msg:match("(" .. RE_FILE_LINE .. ")" .. M.SKIP_PREFIX .. ".*") ~= nil) then -- substitute prefix by iteration message err_msg = err_msg:gsub(".*" .. M.SKIP_PREFIX, iter_msg, 1) diff --git a/lib/preprocess.lua b/lib/preprocess.lua index 54ca5fb..4788d33 100644 --- a/lib/preprocess.lua +++ b/lib/preprocess.lua @@ -1495,9 +1495,10 @@ local unpack = (_VERSION >= "Lua 5.2") and table.unpack or _G.unpack --[[local]] loadLuaString = ( - (_VERSION >= "Lua 5.2" or jit) and function(lua, chunkName, env) - return load(lua, chunkName, "bt", env) - end + (_VERSION >= "Lua 5.2" or jit) + and function(lua, chunkName, env) + return load(lua, chunkName, "bt", env) + end or function(lua, chunkName, env) local chunk, err = loadstring(lua, chunkName) if not chunk then @@ -2811,20 +2812,26 @@ local function doEarlyExpansions(tokensToExpand, stats) outTokens, newTokenAt({ type = "pp_entry", value = "!!", representation = "!!", double = true }, ppSymbolTok) ) - tableInsert(outTokens, newTokenAt({ - type = "punctuation", - value = "(", - representation = "(", - }, ppSymbolTok)) + tableInsert( + outTokens, + newTokenAt({ + type = "punctuation", + value = "(", + representation = "(", + }, ppSymbolTok) + ) tableInsert( outTokens, newTokenAt({ type = "identifier", value = "__EVAL", representation = "__EVAL" }, ppSymbolTok) ) - tableInsert(outTokens, newTokenAt({ - type = "punctuation", - value = "(", - representation = "(", - }, ppSymbolTok)) + tableInsert( + outTokens, + newTokenAt({ + type = "punctuation", + value = "(", + representation = "(", + }, ppSymbolTok) + ) tableInsert( outTokens, newTokenAt( @@ -2832,16 +2839,22 @@ local function doEarlyExpansions(tokensToExpand, stats) ppSymbolTok ) ) - tableInsert(outTokens, newTokenAt({ - type = "punctuation", - value = ")", - representation = ")", - }, ppSymbolTok)) - tableInsert(outTokens, newTokenAt({ - type = "punctuation", - value = ")", - representation = ")", - }, ppSymbolTok)) + tableInsert( + outTokens, + newTokenAt({ + type = "punctuation", + value = ")", + representation = ")", + }, ppSymbolTok) + ) + tableInsert( + outTokens, + newTokenAt({ + type = "punctuation", + value = ")", + representation = ")", + }, ppSymbolTok) + ) -- Anything else. else diff --git a/lib/tiny.lua b/lib/tiny.lua index 6e932fa..960920a 100644 --- a/lib/tiny.lua +++ b/lib/tiny.lua @@ -29,11 +29,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---@field index number is the System's index in the World. Lower indexed Systems are processed before higher indices. The index is a read only field; to set the index, use tiny.setSystemIndex(world, system). ---@field indices table field is a table of Entity keys to their indices in the entities list. Most Systems can ignore this. ---@field modified boolean indicator for if the System has been modified in the last update. If so, the onModify callback will be called on the System in the next update, if it has one. This is usually managed by tiny-ecs, so users should mostly ignore this, too. +---@field preProcess nil | fun(self, dt: number): nil | table +---@field postProcess nil | fun(self, dt: number) +---@field isDrawSystem nil | boolean --- @module tiny-ecs --- @author Calvin Rose --- @license MIT --- @copyright 2016 +--- @author Calvin Rose +--- @license MIT +--- @copyright 2016 local tiny = {} -- Local versions of standard lua functions diff --git a/main.lua b/main.lua index 8f64446..154dc39 100644 --- a/main.lua +++ b/main.lua @@ -1,5 +1,6 @@ require("tiny-debug") tiny = require("lib/tiny") +require("lib/inspect") require("utils") require("tiny-tools") @@ -11,22 +12,22 @@ require("generated/all-systems") local width, height = love.graphics.getWidth(), love.graphics.getHeight() -local squareSize = 80 -local tileSize = math.floor(squareSize * 1.2) +local squareSide = 80 +local tileSize = math.floor(squareSide * 1.2) local marginSize = 10 +local squareSize = { x = squareSide, y = squareSide } CursorMask = 1 BallMask = 2 local function emptyTile(unhighlightSiblings, gridPosition) - local size = { x = squareSize, y = squareSize } return { unhighlightSiblings = unhighlightSiblings, canBeCollidedBy = CursorMask, highlightOnMouseOver = T.marker, - size = size, + size = squareSize, gridPosition = gridPosition, - drawAsRectangle = { size = size }, + drawAsRectangle = { size = squareSize }, } end @@ -34,6 +35,8 @@ local function replaceAt(grid, y, x, entity) local current = grid[y][x] grid[y][x] = entity + current.highlighted = nil + entity.parentGrid = grid current.unhighlightSiblings[entity] = true current.unhighlightSiblings[current] = nil entity.unhighlightSiblings = current.unhighlightSiblings @@ -50,10 +53,15 @@ local function replaceAt(grid, y, x, entity) current.above.below = current.below current.below.above = current.above + -- print("replacement: " .. Inspect(entity, { depth = 1 })) World:removeEntity(current) World:addEntity(entity) end +function Replace(toReplace, replacement) + replaceAt(toReplace.parentGrid, toReplace.gridPosition.y, toReplace.gridPosition.x, replacement) +end + function PositionAtGridXy(x, y) return { x = 20 + ((x - 1) * tileSize), @@ -68,13 +76,14 @@ Scenarios = { World:addEntity({ size = cursorSize, moveWithCursor = T.marker, + isCursor = T.marker, canCollideWith = bit.bor(CursorMask, BallMask), position = { x = -999, y = -999 }, highlightsCollided = T.marker, - drawAsRectangle = { - size = cursorSize, - mode = "fill", - }, + -- drawAsRectangle = { + -- size = cursorSize, + -- mode = "fill", + -- }, }) World:addEntity({ position = { x = 0, y = 0 }, @@ -85,6 +94,7 @@ Scenarios = { -- Temporary storages for connecting grid items local previous local unhighlightSiblings = {} + local yxGrid = {} local xCount = 8 @@ -94,6 +104,7 @@ Scenarios = { yxGrid[y] = {} for x = 1, xCount do local current = World:addEntity(emptyTile(unhighlightSiblings, { x = x, y = y })) + current.parentGrid = yxGrid yxGrid[y][x] = current unhighlightSiblings[current] = true current.toLeft = previous @@ -132,7 +143,8 @@ Scenarios = { z = 1, effectsToApply = { endOfRound = T.marker, - } + movement = { x = 0, y = 0 }, + }, }) replaceAt(yxGrid, 2, 2, { drawAsSprite = SmallSandTrap, @@ -140,26 +152,32 @@ Scenarios = { spriteAfterEffect = SmallSandTrapActivated, effectsToApply = { slowsBy = { x = 1, y = 1 }, - movement = { x = 0, y = 0, }, + movement = { x = 0, y = 0 }, }, }) - replaceAt(yxGrid, 1, 1, { + World:addEntity({ + canBeCollidedBy = CursorMask, pickedUpOnClick = T.marker, + size = squareSize, drawAsSprite = GolferRight, z = 1, spriteAfterEffect = GolferRightActivated, effectsToApply = { - movement = { x = 6, y = 0, }, + movement = { x = 99, y = 0 }, }, + position = { x = 20, y = height - 80 }, }) - replaceAt(yxGrid, 1, 7, { + World:addEntity({ + canBeCollidedBy = CursorMask, pickedUpOnClick = T.marker, - drawAsSprite = GolferRight, + size = squareSize, + drawAsSprite = GolferDown, z = 1, spriteAfterEffect = GolferRightActivated, effectsToApply = { - movement = { x = 0, y = 3 }, + movement = { x = 0, y = 99 }, }, + position = { x = 20 + squareSide, y = height - 80 }, }) World:addEntity({ ballEffects = {}, @@ -167,10 +185,15 @@ Scenarios = { gridPosition = { x = 1, y = 1 }, z = 2, }) - -- TODO: Make the start button start + local startButtonX, startButtonY = StartButton:getDimensions() World:addEntity({ + canBeCollidedBy = CursorMask, drawAsSprite = StartButton, + addOnActivate = { + { roundState = "active" }, + }, z = 3, + size = { x = startButtonX, y = startButtonY }, position = { x = width - 120, y = height - 50, @@ -179,7 +202,8 @@ Scenarios = { end, } -Scenarios.firstLevel() +local currentLevel = Scenarios.firstLevel +currentLevel() function love.load() love.graphics.setBackgroundColor(1, 1, 1) @@ -190,8 +214,9 @@ function love.draw() local dt = love.timer.getDelta() if love.keyboard.isDown("r") then World:clearEntities() - Scenarios.firstLevel() + currentLevel() end + World:setSystemIndex(LiveForNFrames, 1) World:update(dt, function(_, system) return not system.isDrawSystem end) diff --git a/systems/collision-resolution.lua b/systems/collision-resolution.lua index 8ae0c32..3303f9d 100644 --- a/systems/collision-resolution.lua +++ b/systems/collision-resolution.lua @@ -1,3 +1,27 @@ +filteredSystem("activated", { activated = T.Entity }, function(e, _, system) + local activated = e.activated + if activated.addOnActivate then + for _, toAdd in ipairs(activated.addOnActivate) do + system.world:addEntity(toAdd) + end + end + if activated.pickedUpOnClick and #HeldByCursor.entities == 0 then + activated.placedOnClick = T.marker + activated.moveWithCursor = T.marker + activated.canBeCollidedBy = 0 + system.world:addEntity(activated) + elseif activated.gridPosition then + for _, held in pairs(HeldByCursor.entities) do + held.placedOnClick = nil + held.moveWithCursor = nil + held.highlighted = nil + held.canBeCollidedBy = CursorMask + Replace(activated, held) + end + end + system.world:removeEntity(e) +end) + Collisions = filteredSystem("collisionResolution", { collisionBetween = T.Collision }, function(e, _, system) local collidedInto, collider = e.collisionBetween[1], e.collisionBetween[2] if collider.highlightsCollided then @@ -13,10 +37,11 @@ Collisions = filteredSystem("collisionResolution", { collisionBetween = T.Collis collidedInto.canReceiveButtons = T.marker system.world:addEntity(collidedInto) end - if collidedInto.pickedUpOnClick ~= nil then -- and #HeldByCursor.entities == 0 and love.mouse.isDown(1) then - print("Click!") - collidedInto.moveWithCursor = T.marker - system.world:addEntity(collidedInto) + if collidedInto.gridPosition then + --print("ready to place " .. #HeldByCursor.entities .. " entities") + end + if MouseJustPressed(1, true) and collider.isCursor then + system.world:addEntity({ activated = collidedInto }) end end system.world:removeEntity(e) diff --git a/systems/draw.lua b/systems/draw.lua index d8cd5ef..d621b48 100644 --- a/systems/draw.lua +++ b/systems/draw.lua @@ -31,7 +31,6 @@ local spriteDrawSystem = drawSystem( if not e.drawAsSprite then return end - local width, height = e.drawAsSprite:getDimensions() gfx.draw(e.drawAsSprite, e.position.x, e.position.y) end ) @@ -63,7 +62,7 @@ drawSystem( gfx.rectangle("fill", bgLeftEdge, bgTopEdge, bgWidth, bgHeight) gfx.setColor(0, 0, 0) - gfx.drawRect("line", bgLeftEdge, bgTopEdge, bgWidth, bgHeight) + gfx.rectangle("line", bgLeftEdge, bgTopEdge, bgWidth, bgHeight) end gfx.print(e.drawAsText.text, bgLeftEdge + margin, bgTopEdge + margin) diff --git a/systems/input.lua b/systems/input.lua index 17cb0a9..cde440d 100644 --- a/systems/input.lua +++ b/systems/input.lua @@ -8,8 +8,30 @@ buttonInputSystem = filteredSystem("buttonInput", { canReceiveButtons = T.marker system.world:addEntity(e) end) +Mouse = filteredSystem("Mouse", { mouseButtonPress = { position = T.XyPair, button = T.number } }) + +function MouseJustPressed(button, clear) + for _, event in pairs(Mouse.entities) do + if event.mouseButtonPress and event.mouseButtonPress.button == button then + if clear then + event.mouseButtonPress = nil + World:removeEntity(event) + end + return true + end + end + return false +end + HeldByCursor = filteredSystem("HeldByCursor", { pickedUpOnClick = T.marker, moveWithCursor = T.marker }) +LiveForNFrames = filteredSystem("liveForNFrames", { liveForNFrames = T.number }, function(e, _, system) + e.liveForNFrames = e.liveForNFrames - 1 + if e.liveForNFrames <= 0 then + system.world:removeEntity(e) + end +end) + function buttonInputSystem:preProcess() if #self.entities == 0 then return @@ -37,6 +59,19 @@ function love.mousemoved(x, y) mouseX, mouseY = x, y end +function love.mousepressed(x, y, button) + World:addEntity({ + mouseButtonPress = { + position = { + x = x, + y = y, + }, + button = button, + }, + liveForNFrames = 1, + }) +end + local keyDebounceSec = 0.1 local delay = 0 @@ -76,7 +111,7 @@ local menuSystem = filteredSystem( if isDown("return") then pressed = true system.world:addEntity({ - round = "start", + roundState = "active", }) end @@ -94,8 +129,13 @@ local menuSystem = filteredSystem( cursorTracking = filteredSystem("cursorTracking", { moveWithCursor = T.marker, position = T.XyPair }, function(e) if mouseInControl then - e.position.x = mouseX - e.position.y = mouseY + local offsetX, offsetY = 0, 0 + if e.size then + offsetX = e.size.x / 2 + offsetY = e.size.y / 2 + end + e.position.x = mouseX - offsetX + e.position.y = mouseY - offsetY end end) diff --git a/systems/rounds.lua b/systems/rounds.lua index ef640fd..b0373c8 100644 --- a/systems/rounds.lua +++ b/systems/rounds.lua @@ -1,7 +1,5 @@ local gridElements = filteredSystem("gridElements", { gridPosition = T.XyPair, effectsToApply = T.AnyComponent }) -local roundRunning = false - filteredSystem("timers", { timerSec = T.number, callback = T.SelfFunction }, function(e, dt, system) e.timerSec = e.timerSec - dt if e.timerSec < 0 then @@ -14,72 +12,96 @@ local function sign(n) return n > 0 and 1 or n < 0 and -1 or 0 end -local roundSystem = filteredSystem("rounds", { round = T.str }) - -local activeBallEffects = filteredSystem("activeBallEffects", { ballEffects = T.AnyComponent, gridPosition = T.XyPair }, function(e, dt, system) - local roundActive = false - for _, state in pairs(roundSystem.entities) do - if state.round == "start" then - roundActive = true - end - end - if not roundActive then - return - end - local gridPosition, effects = e.gridPosition, e.ballEffects - - -- Search for new effects from the current tile - for _, gridElement in pairs(gridElements.entities) do - if - gridPosition.x == gridElement.gridPosition.x - and gridPosition.y == gridElement.gridPosition.y - then - -- More direct-mutation-y than I'd like, - -- but offers a simple way to overwrite existing effects. - -- We're "setting InRelations" :D - for key, value in pairs(gridElement.effectsToApply) do - effects[key] = value - end - if gridElement.spriteAfterEffect then - gridElement.drawAsSprite = gridElement.spriteAfterEffect - gridElement.spriteAfterEffect = nil - end - gridElement.effectsToApply = nil - system.world:addEntity(gridElement) - end - end - - -- Apply any effects currently connected to this ball - if effects.movement ~= nil then - gridPosition.x = gridPosition.x + sign(effects.movement.x) - gridPosition.y = gridPosition.y + sign(effects.movement.y) - - effects.movement.x = effects.movement.x - sign(effects.movement.x) - effects.movement.y = effects.movement.y - sign(effects.movement.y) - - if effects.movement.x == 0 and effects.movement.y == 0 then - effects.movement = nil - end - end - - -- TODO: Trigger the round end - -- for _, _ in pairs(effects) do - -- -- Return if there are any effects left - -- return - -- end - - -- system.world:addEntity({ round = "end" }) +local roundSystem = filteredSystem("rounds", { roundState = T.str }, function(e) + print("roundState: " .. e.roundState) end) -local stepTimeSec = 0.3 +function roundSystem:preProcess() + if #self.entities ~= 0 then + print("#states: " .. #self.entities) + end +end + +local activeBallEffects = filteredSystem( + "activeBallEffects", + { ballEffects = T.AnyComponent, gridPosition = T.XyPair }, + function(e, dt, system) + local gridPosition, effects = e.gridPosition, e.ballEffects + + -- Search for new effects from the current tile + for _, gridElement in pairs(gridElements.entities) do + if gridPosition.x == gridElement.gridPosition.x and gridPosition.y == gridElement.gridPosition.y then + -- More direct-mutation-y than I'd like, + -- but offers a simple way to overwrite existing effects. + -- We're "setting InRelations" :D + for key, value in pairs(gridElement.effectsToApply) do + effects[key] = value + end + if gridElement.spriteAfterEffect then + gridElement.drawAsSprite = gridElement.spriteAfterEffect + gridElement.spriteAfterEffect = nil + end + gridElement.effectsToApply = nil + system.world:addEntity(gridElement) + end + end + + -- Apply any effects currently connected to this ball + if effects.movement ~= nil then + gridPosition.x = gridPosition.x + sign(effects.movement.x) + gridPosition.y = gridPosition.y + sign(effects.movement.y) + + effects.movement.x = effects.movement.x - sign(effects.movement.x) + effects.movement.y = effects.movement.y - sign(effects.movement.y) + + if effects.movement.x == 0 and effects.movement.y == 0 then + effects.movement = nil + end + end + + if effects.endOfRound ~= nil then + effects.endOfRound = nil + system.world:addEntity({ roundState = "end" }) + system.world:removeEntity(e) + print("End of round") + return + end + + for _, _ in pairs(effects) do + -- Return if there are any effects left + print("Setting roundState to animating...") + --system.world:addEntity({ roundState = "animating" }) + --system.world:removeEntity(e) + return + end + + print("End of round") + system.world:addEntity({ roundState = "end" }) + end +) + +local stepTimeSec = 0.1 local stepTimer = stepTimeSec function activeBallEffects:preProcess(dt) stepTimer = stepTimer - dt if stepTimer <= 0 then stepTimer = stepTimeSec - return + else + return tiny.SKIP_PROCESS end + + -- for _, round in pairs(roundSystem.entities) do + -- if round.roundState == "animating" then + -- return tiny.SKIP_PROCESS + -- end + -- end + + for _, round in pairs(roundSystem.entities) do + if round.roundState == "active" then + return + end + end + return tiny.SKIP_PROCESS end - diff --git a/tiny-types.lua b/tiny-types.lua index d81e914..205f198 100644 --- a/tiny-types.lua +++ b/tiny-types.lua @@ -1,12 +1,18 @@ ----@meta +---@meta tiny-ecs ---@class World World = {} function World:add(...) end +---@generic T : Entity +---@param entity T +---@return T function World:addEntity(entity) end +---@generic T : System +---@param system T +---@return T function World:addSystem(system) end function World:remove(...) end @@ -15,17 +21,28 @@ function World:removeEntity(entity) end function World:removeSystem(system) end +--- Manages Entities and Systems marked for deletion or addition. Call this +--- before modifying Systems and Entities outside of a call to `tiny.update`. +--- Do not call this within a call to `tiny.update`. function World:refresh() end ---@param dt number -function World:update(dt) end +---@param systemFilter nil | fun(world: World, system: System): boolean +function World:update(dt, systemFilter) end +--- Removes all Entities from the World. function World:clearEntities() end +--- Removes all Systems from the World. function World:clearSystems() end +--- Gets number of Entities in the World. function World:getEntityCount() end +--- Gets number of Systems in World. function World:getSystemCount() end -function World:setSystemIndex() end +--- Sets the index of a System in the World, and returns the old index. Changes +--- the order in which they Systems processed, because lower indexed Systems are +--- processed first. Returns the old system.index. +function World:setSystemIndex(world, system, index) end