├── test ├── renderScript │ ├── badRequire.lua │ ├── resolutionCheck.lua │ ├── fontSampler.lua │ ├── strokeAlign.lua │ └── layerOperations.lua ├── exportAll.sh ├── runTests.sh ├── dumocks │ ├── AbstractTestElementWithState.lua │ ├── TestWarpDriveUnit.lua │ ├── TestAdjustorUnit.lua │ ├── AbstractTestElementWithToggle.lua │ ├── TestSystem.lua │ ├── TestPlayer.lua │ ├── TestConstruct.lua │ ├── TestElement.lua │ ├── TestWeaponUnit.lua │ ├── TestBrakeUnit.lua │ ├── TestMiningUnit.lua │ ├── TestEngineUnit.lua │ ├── TestAirfoilUnit.lua │ ├── TestSurfaceEngineUnit.lua │ ├── TestRadarUnit.lua │ ├── TestLibrary.lua │ ├── TestForceFieldUnit.lua │ ├── TestLandingGearUnit.lua │ ├── TestDoorUnit.lua │ ├── TestLaserEmitterUnit.lua │ └── TestTelemeterUnit.lua └── bundleCharacterizationTest.lua ├── .luacov ├── .github ├── renovate.json └── workflows │ ├── publish.yml │ ├── prep-release.yml │ ├── doc.yml │ └── test.yml ├── .gitignore ├── config-pts.ld ├── config.ld ├── LICENSE ├── src ├── dumocks │ ├── ElementWithState.lua │ ├── ElementWithToggle.lua │ ├── EngineUnit.lua │ ├── LaserEmitterUnit.lua │ ├── LandingGearUnit.lua │ ├── TelemeterUnit.lua │ ├── SurfaceEngineUnit.lua │ ├── ForceFieldUnit.lua │ ├── Library.lua │ ├── DoorUnit.lua │ ├── PlasmaExtractorUnit.lua │ ├── EmitterUnit.lua │ ├── CounterUnit.lua │ ├── AdjustorUnit.lua │ └── BrakeUnit.lua └── game_data_lua │ ├── database.lua │ └── rslib.lua ├── rockspecs ├── du-mocks-0.24.0-2.rockspec ├── du-mocks-0.24.1-1.rockspec ├── du-mocks-0.25.1-1.rockspec ├── du-mocks-0.26.0-1.rockspec ├── du-mocks-0.26.1-1.rockspec ├── du-mocks-0.28.0-1.rockspec ├── du-mocks-0.29.0-1.rockspec ├── du-mocks-0.29.1-1.rockspec ├── du-mocks-1.0.0-1.rockspec └── du-mocks-1.1.0-1.rockspec └── du-mocks-scm-0.rockspec /test/renderScript/badRequire.lua: -------------------------------------------------------------------------------- 1 | not a valid lua file -------------------------------------------------------------------------------- /.luacov: -------------------------------------------------------------------------------- 1 | modules = { 2 | ["dumocks.*"] = "src" 3 | } 4 | includeuntestedfiles = true 5 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "github>1337joe/.github//renovate-presets/default" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | doc/ 2 | results/ 3 | configExports/ 4 | 5 | luacov* 6 | cobertura.xml 7 | 8 | # ---> Lua 9 | # Compiled Lua sources 10 | luac.out 11 | 12 | # luarocks build files 13 | *.src.rock 14 | *.zip 15 | *.tar.gz 16 | 17 | -------------------------------------------------------------------------------- /test/exportAll.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd "$(dirname "$0")" 4 | 5 | # clear out old files 6 | rm -rf configExports 7 | mkdir -p configExports/dumocks 8 | 9 | find dumocks -name Test\*.lua -exec ./bundleCharacterizationTest.lua {} configExports/{}.txt \; 10 | -------------------------------------------------------------------------------- /test/renderScript/resolutionCheck.lua: -------------------------------------------------------------------------------- 1 | -- Display the provided input string and the screen resolution 2 | local xRes, yRes = getResolution() 3 | local input = getInput() or "" 4 | 5 | local layer = createLayer() 6 | local font = loadFont("RobotoMono", 30) 7 | 8 | addText(layer, font, input, 0, yRes / 2) 9 | addText(layer, font, string.format("%d x %d", xRes, yRes), 0, yRes) 10 | 11 | setDefaultStrokeColor(layer, Shape_Line, 1, 0, 0, 1) 12 | setDefaultStrokeWidth(layer, Shape_Line, 10) 13 | addLine(layer, 0, 0, xRes, 0) 14 | addLine(layer, xRes, 0, xRes, yRes) 15 | addLine(layer, xRes, yRes, 0, yRes) 16 | addLine(layer, 0, yRes, 0, 0) 17 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to LuaRocks 2 | 3 | on: 4 | release: 5 | types: [ published ] 6 | 7 | jobs: 8 | publish: 9 | name: Publish 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 14 | 15 | - uses: leafo/gh-actions-lua@35bcb06abec04ec87df82e08caa84d545348536e # v10.0.0 16 | 17 | - uses: leafo/gh-actions-luarocks@e65774a6386cb4f24e293dca7fc4ff89165b64c5 # v4.3.0 18 | 19 | - run: luarocks install dkjson 20 | 21 | - run: luarocks upload --api-key ${{ secrets.API_KEY }} rockspecs/du-mocks-${GITHUB_REF##*/v}-1.rockspec 22 | -------------------------------------------------------------------------------- /config-pts.ld: -------------------------------------------------------------------------------- 1 | title = "PTS DU Mocks" 2 | project = [[PTS DU Mocks]] 3 | description = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline." 4 | full_description = [[ 5 |

Note: This is the PTS version of the documentation. For current live documentation go to Web Codex or Mock Codex

6 | 7 | See this project on github for code and more details. 8 | ]] 9 | file = { 10 | "src", 11 | } 12 | sort_modules=true 13 | -------------------------------------------------------------------------------- /test/runTests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # stop for error if test returns non-0 exit code 4 | #set -e 5 | 6 | # set return code for final result 7 | exitCode=0 8 | 9 | # code coverage display on jenkins expects files to be referenced from project root 10 | cd "$(dirname "$0")/.." 11 | 12 | # set lua path to include src directory 13 | export LUA_PATH="src/?.lua;;$LUA_PATH" 14 | 15 | # clear out old results 16 | rm -rf test/results 17 | mkdir -p test/results/ 18 | 19 | # Note: not whitespace-safe 20 | for test in $(find . -name Test\*.lua) 21 | do 22 | testName=`basename $test` 23 | lua -lluacov ${test} $@ -n test/results/${testName}.xml 24 | 25 | retVal=$? 26 | if [ $retVal -ne 0 ]; then 27 | exitCode=$retVal 28 | fi 29 | done 30 | 31 | exit $exitCode 32 | -------------------------------------------------------------------------------- /config.ld: -------------------------------------------------------------------------------- 1 | title = "DU Mocks" 2 | project = "DU Mocks" 3 | description = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline." 4 | full_description = [[ 5 | See this project on github for code and more details. 6 | 7 | If you notice typos or differences between the in-game behavior and this documentation please drop me a message either on github or discord: 1337joe#6186 8 | 9 | The official NQ API mockup can be found here. 10 | 11 | This site is maintained in my free time as a public service to the community. If you find value in my work and want to toss a few quanta my way, my Dual Universe character is: W3asel 12 | 13 | The "Dual Universe" brand, the "Dual Universe" logo and all associated logos and designs are the intellectual property of Novaquark S.A.S. https://du.w3asel.com is a fansite that Novaquark S.A.S. does not endorse, and the latter is not affiliated with it in any way. 14 | ]] 15 | file = { 16 | "src", 17 | } 18 | sort_modules=true 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright © 2020 - 2022 Joe Rogers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the “Software”), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/dumocks/ElementWithState.lua: -------------------------------------------------------------------------------- 1 | --- Abstract class to define elements with a getState method. 2 | -- 3 | -- Element class: 4 | -- 5 | -- Extends: @{Element} 6 | -- 7 | -- Extended by: 8 | --
    9 | --
  • @{ElementWithToggle}
  • 10 | --
  • @{LaserDetectorUnit}
  • 11 | --
  • @{ManualButtonUnit}
  • 12 | --
  • @{PressureTileUnit}
  • 13 | --
14 | -- @module ElementWithState 15 | -- @alias M 16 | 17 | local MockElement = require "dumocks.Element" 18 | 19 | local M = MockElement:new() 20 | 21 | function M:new(o, id, elementDefinition) 22 | o = o or MockElement:new(o, id, elementDefinition) 23 | setmetatable(o, self) 24 | self.__index = self 25 | 26 | o.state = false 27 | 28 | return o 29 | end 30 | 31 | --- Deprecated: Returns the activation state of the element. 32 | -- 33 | -- This method is deprecated: element-specific methods should be used instead. 34 | -- @treturn 0/1 1 when the element is on, 0 otherwise. 35 | function M:getState() 36 | M.deprecated("getState") 37 | if self.state then 38 | return 1 39 | end 40 | return 0 41 | end 42 | 43 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 44 | -- @treturn table A table encompasing the api calls of object. 45 | -- @see Element:mockGetClosure 46 | function M:mockGetClosure() 47 | local closure = MockElement.mockGetClosure(self) 48 | closure.getState = function() return self:getState() end 49 | return closure 50 | end 51 | 52 | return M -------------------------------------------------------------------------------- /src/game_data_lua/database.lua: -------------------------------------------------------------------------------- 1 | --- The database library offers multiple useful functions to get all information 2 | -- in one object about a player, a construct, an organization or an element. 3 | -- 4 | -- The database is defined by a Lua file within your Dual Universe installation, view it at: 5 | -- ...\Dual Universe\Game\data\lua\database.lua 6 | -- @module game_data_lua.database 7 | 8 | local database = {} 9 | 10 | --- Returns all info about a given player, identified by its id. 11 | -- @tparam integer id The player ID. 12 | -- @treturn table The player structure. 13 | function database.getPlayer(id) 14 | end 15 | 16 | --- Returns all informations about the player running the script. 17 | -- @tparam table unit The unit object. 18 | -- @treturn table The player structure. 19 | function database.getMasterPlayer(unit) 20 | end 21 | 22 | --- Returns all informations about the given organization, identified by its id. 23 | -- @tparam integer id The organization id. 24 | -- @treturn table The organization structure. 25 | function database.getOrganization(id) 26 | end 27 | 28 | --- Returns all info about a given construct, identified by its id and seen from a radar. 29 | -- @tparam table radar The radar object. 30 | -- @tparam integer id The construct ID. 31 | -- @treturn table The construct structure. 32 | function database.getConstruct(radar, id) 33 | end 34 | 35 | --- Returns all info about a given element, identified by its id and coupled to a core unit. 36 | -- @tparam table core The core unit object. 37 | -- @tparam integer id The element ID. 38 | -- @treturn table The construct structure. 39 | function database.getElement(core, id) 40 | end 41 | -------------------------------------------------------------------------------- /test/dumocks/AbstractTestElementWithState.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.ElementWithState. 3 | -- @see dumocks.ElementWithState 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | local utilities = require("test.Utilities") 10 | 11 | local AbstractTestElementWithState = {} 12 | 13 | --- Factory to create an element for testing. Must be overridden for tests to work. 14 | -- @return A mock of the element to test. 15 | function AbstractTestElementWithState.getTestElement() 16 | lu.fail("getTestElement must be overridden for AbstractTestElementWithState to work.") 17 | end 18 | 19 | --- Factory to produce the non-deprecated getState function for the element. 20 | -- @tparam table closure The closure to extract the function from. 21 | -- @treturn function The correct getState function. 22 | function AbstractTestElementWithState.getStateFunction(closure) 23 | lu.fail("getStateFunction must be overridden to test getState functionality.") 24 | end 25 | 26 | --- Verify that get state retrieves the state properly. 27 | function AbstractTestElementWithState.testGetState() 28 | local mock = AbstractTestElementWithState.getTestElement() 29 | local closure = mock:mockGetClosure() 30 | local getStateOverride = AbstractTestElementWithState.getStateFunction(closure) 31 | 32 | mock.state = false 33 | lu.assertEquals(getStateOverride(), 0) 34 | lu.assertEquals(utilities.verifyDeprecated("getState", closure.getState), 0) 35 | 36 | mock.state = true 37 | lu.assertEquals(getStateOverride(), 1) 38 | lu.assertEquals(utilities.verifyDeprecated("getState", closure.getState), 1) 39 | end 40 | 41 | return AbstractTestElementWithState -------------------------------------------------------------------------------- /.github/workflows/prep-release.yml: -------------------------------------------------------------------------------- 1 | name: Prepare for publish to LuaRocks 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | version: 7 | description: 'New version number (tag name without the "v")' 8 | required: true 9 | type: string 10 | commit_and_tag: 11 | description: 'Commit the rockspec and create the new tag on success' 12 | required: true 13 | default: true 14 | type: boolean 15 | 16 | jobs: 17 | prepare_for_publish: 18 | name: Prepare for publish 19 | runs-on: ubuntu-latest 20 | 21 | env: 22 | ROCKSPEC: "rockspecs/du-mocks-${{ inputs.version }}-1.rockspec" 23 | 24 | steps: 25 | - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 26 | with: 27 | ref: main 28 | 29 | - name: Create new rockspec file 30 | run: | 31 | cp du-mocks-scm-0.rockspec $ROCKSPEC 32 | sed -i 's/scm-0/${{ inputs.version }}-1/g' $ROCKSPEC 33 | sed -i 's/branch = "main"/tag = "v${{ inputs.version }}"/g' $ROCKSPEC 34 | 35 | - uses: leafo/gh-actions-lua@35bcb06abec04ec87df82e08caa84d545348536e # v10.0.0 36 | 37 | - uses: leafo/gh-actions-luarocks@e65774a6386cb4f24e293dca7fc4ff89165b64c5 # v4.3.0 38 | 39 | - name: Verify new rockspec builds 40 | run: luarocks make $ROCKSPEC 41 | 42 | - name: Commit rockspec and tag 43 | if: ${{ inputs.commit_and_tag }} 44 | run: | 45 | git config --global user.name 'Joe Rogers' 46 | git config --global user.email '1337joe@users.noreply.github.com' 47 | git add $ROCKSPEC 48 | git commit -m "Prepare for release ${{ inputs.version }}" 49 | git tag v${{ inputs.version }} 50 | git push 51 | git push --tags 52 | -------------------------------------------------------------------------------- /.github/workflows/doc.yml: -------------------------------------------------------------------------------- 1 | name: Generate Docs 2 | 3 | on: 4 | push: 5 | branches: [ main, pts ] 6 | # pull_request: 7 | # branches: [ main ] 8 | 9 | jobs: 10 | codex: 11 | name: Generate Codex 12 | runs-on: ubuntu-latest 13 | 14 | env: 15 | LDOC_CONFIG: "${{ github.ref == 'refs/heads/pts' && 'config-pts.ld' || 'config.ld' }}" 16 | CODEX_SUFFIX: "${{ github.ref == 'refs/heads/pts' && 'codex-pts' || 'codex' }}" 17 | 18 | steps: 19 | - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 20 | 21 | - uses: leafo/gh-actions-lua@35bcb06abec04ec87df82e08caa84d545348536e # v10.0.0 22 | 23 | - uses: leafo/gh-actions-luarocks@e65774a6386cb4f24e293dca7fc4ff89165b64c5 # v4.3.0 24 | 25 | - name: Setup 26 | run: | 27 | luarocks install ldoc 28 | mkdir docs 29 | 30 | - name: Build mock codex 31 | run: | 32 | ldoc -c $LDOC_CONFIG . 33 | mv doc docs/mock-codex 34 | 35 | - name: Remove mock methods 36 | run: | 37 | find src/dumocks -name \*.lua -exec sed -i 's/--- Mock/-- Mock/g' {} + 38 | 39 | - name: Build web codex 40 | run: | 41 | ldoc -c $LDOC_CONFIG . 42 | mv doc docs/web-codex 43 | 44 | - name: Clean up CSS 45 | run: | 46 | find docs -name ldoc.css -exec sed -i 's/width: 700px;//g' {} + 47 | 48 | - name: Deploy Web Codex 49 | uses: JamesIves/github-pages-deploy-action@a96ffa23204731ec64e3e1316072197d98bfbaea # v4.6.6 50 | with: 51 | branch: codex 52 | folder: docs/web-codex 53 | target-folder: web-${{ env.CODEX_SUFFIX }} 54 | 55 | - name: Deploy Mock Codex 56 | uses: JamesIves/github-pages-deploy-action@a96ffa23204731ec64e3e1316072197d98bfbaea # v4.6.6 57 | with: 58 | branch: codex 59 | folder: docs/mock-codex 60 | target-folder: mock-${{ env.CODEX_SUFFIX }} 61 | -------------------------------------------------------------------------------- /src/dumocks/ElementWithToggle.lua: -------------------------------------------------------------------------------- 1 | --- Abstract class to define elements with activate, deactivate, toggle, and getState method. 2 | -- 3 | -- Extends: @{Element} > @{ElementWithState} 4 | -- 5 | -- Extended by: 6 | --
    7 | --
  • @{AntiGravityGeneratorUnit}
  • 8 | --
  • @{BaseShieldGeneratorUnit}
  • 9 | --
  • @{DoorUnit}
  • 10 | --
  • @{EngineUnit}
  • 11 | --
  • @{ForceFieldUnit}
  • 12 | --
  • @{GyroUnit}
  • 13 | --
  • @{LandingGearUnit}
  • 14 | --
  • @{LaserEmitterUnit}
  • 15 | --
  • @{LightUnit}
  • 16 | --
  • @{ManualSwitchUnit}
  • 17 | --
  • @{ScreenUnit}
  • 18 | --
  • @{ShieldGeneratorUnit}
  • 19 | --
  • @{TransponderUnit}
  • 20 | --
21 | -- @see Element 22 | -- @see ElementWithState 23 | -- @module ElementWithToggle 24 | -- @alias M 25 | 26 | local MockElementWithState = require "dumocks.ElementWithState" 27 | 28 | local M = MockElementWithState:new() 29 | 30 | function M:new(o, id, elementDefinition) 31 | o = o or MockElementWithState:new(o, id, elementDefinition) 32 | setmetatable(o, self) 33 | self.__index = self 34 | 35 | return o 36 | end 37 | 38 | --- Deprecated: Switches the element on/open. 39 | -- 40 | -- This method is deprecated: element-specific methods should be used instead. 41 | function M:activate() 42 | M.deprecated("activate") 43 | self.state = true 44 | end 45 | 46 | --- Deprecated: Switches the element off/open. 47 | -- 48 | -- This method is deprecated: element-specific methods should be used instead. 49 | function M:deactivate() 50 | M.deprecated("deactivate") 51 | self.state = false 52 | end 53 | 54 | --- Toggle the state of the element. 55 | function M:toggle() 56 | self.state = not self.state 57 | end 58 | 59 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 60 | -- @treturn table A table encompasing the api calls of object. 61 | -- @see Element:mockGetClosure 62 | function M:mockGetClosure() 63 | local closure = MockElementWithState.mockGetClosure(self) 64 | closure.activate = function() return self:activate() end 65 | closure.deactivate = function() return self:deactivate() end 66 | closure.toggle = function() return self:toggle() end 67 | return closure 68 | end 69 | 70 | return M -------------------------------------------------------------------------------- /test/dumocks/TestWarpDriveUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.WarpDriveUnit. 3 | -- @see dumocks.WarpDriveUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mwdu = require("dumocks.WarpDriveUnit") 11 | require("test.Utilities") 12 | 13 | TestWarpDriveUnit = {} 14 | 15 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 16 | -- in-game. 17 | -- 18 | -- Test setup: 19 | -- 1. 1x Warp Drive, connected to Programming Board on slot1 20 | -- 21 | -- Exercises: getClass, getData 22 | function _G.TestWarpDriveUnit.testGameBehavior() 23 | local mock = mwdu:new(nil, 1) 24 | local slot1 = mock:mockGetClosure() 25 | 26 | -- stub this in directly to supress print in the unit test 27 | local unit = {} 28 | unit.exit = function() 29 | end 30 | local system = {} 31 | system.print = function(_) 32 | end 33 | 34 | --------------- 35 | -- copy from here to unit.onStart() 36 | --------------- 37 | -- verify expected functions 38 | local expectedFunctions = {"initiate", "getStatus", "getDistance", "getDestination", "getDestinationName", 39 | "getContainerId", "getAvailableWarpCells", "getRequiredWarpCells"} 40 | for _, v in pairs(_G.Utilities.elementFunctions) do 41 | table.insert(expectedFunctions, v) 42 | end 43 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 44 | 45 | -- test element class and inherited methods 46 | assert(slot1.getClass() == "WarpDriveUnit") 47 | assert(string.match(string.lower(slot1.getName()), "warp drive l %[%d+%]"), slot1.getName()) 48 | assert(slot1.getItemId() == 4015850440, "Unexpected id: " .. slot1.getItemId()) 49 | 50 | local data = slot1.getWidgetData() 51 | local expectedFields = {"buttonText", "cellCount", "destination", "distance", "elementId", "showError", 52 | "helperId", "name", "type", "enableButton", "statusText"} 53 | local expectedValues = {} 54 | expectedValues["helperId"] = '"warpdrive"' 55 | expectedValues["type"] = '"warpdrive"' 56 | _G.Utilities.verifyWidgetData(data, expectedFields, expectedValues) 57 | 58 | assert(slot1.getMaxHitPoints() == 43117.0) 59 | assert(slot1.getMass() == 75000.0) 60 | _G.Utilities.verifyBasicElementFunctions(slot1, 3, "warpdrive") 61 | 62 | system.print("Success") 63 | unit.exit() 64 | --------------- 65 | -- copy to here to unit.onStart() 66 | --------------- 67 | end 68 | 69 | os.exit(lu.LuaUnit.run()) 70 | -------------------------------------------------------------------------------- /src/dumocks/EngineUnit.lua: -------------------------------------------------------------------------------- 1 | --- Engines provide the thrust to move your ship forward. Atmospheric engines only work in the atmosphere, space 2 | -- engines only work in space, and rocket engines work in both but can't be throttled. 3 | -- 4 | -- Element class: 5 | --
    6 | --
  • AtmosphericEngineXtraSmallGroup
  • 7 | --
  • AtmosphericEngineSmallGroup
  • 8 | --
  • SpaceEngineXtraSmallGroup
  • 9 | --
  • SpaceEngineSmallGroup
  • 10 | --
  • RocketEngine
  • 11 | --
12 | -- 13 | -- Extends: @{Element} > @{Engine} > @{FueledEngine} 14 | -- @module EngineUnit 15 | -- @alias M 16 | 17 | local MockElement = require "dumocks.Element" 18 | local MockFueledEngine = require "dumocks.FueledEngine" 19 | 20 | local CLASS_ATMO_XS = "AtmosphericEngineXtraSmallGroup" 21 | local CLASS_ATMO_S = "AtmosphericEngineSmallGroup" 22 | local CLASS_SPACE_XS = "SpaceEngineXtraSmallGroup" 23 | local CLASS_SPACE_S = "SpaceEngineSmallGroup" 24 | local CLASS_ROCKET = "RocketEngine" 25 | 26 | local elementDefinitions = {} 27 | elementDefinitions["basic atmospheric engine xs"] = {mass = 100.0, maxHitPoints = 50.0, itemId = 710193240, class = CLASS_ATMO_XS, maxThrust = 10000.0} 28 | elementDefinitions["basic space engine xs"] = {mass = 146.23, maxHitPoints = 100.0, itemId = 2243775376, class = CLASS_SPACE_XS, maxThrust = 15000.0} 29 | elementDefinitions["rocket engine s"] = {mass = 223.76, maxHitPoints = 113.0, itemId = 2112772336, class = CLASS_ROCKET, maxThrust = 500000.0} 30 | elementDefinitions["rocket engine m"] = {mass = 680.05, maxHitPoints = 715.0, itemId = 3623903713, class = CLASS_ROCKET, maxThrust = 3000000.0} 31 | elementDefinitions["rocket engine l"] = {mass = 3392.98, maxHitPoints = 9689.0, itemId = 359938916, class = CLASS_ROCKET, maxThrust = 18000000.0} 32 | local DEFAULT_ELEMENT = "basic atmospheric engine xs" 33 | 34 | local M = MockFueledEngine:new() 35 | 36 | function M:new(o, id, elementName) 37 | local elementDefinition = MockElement.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 38 | 39 | o = o or MockFueledEngine:new(o, id, elementDefinition) 40 | setmetatable(o, self) 41 | self.__index = self 42 | 43 | o.elementClass = elementDefinition.class 44 | 45 | o.maxThrustBase = elementDefinition.maxThrust 46 | o.currentMaxThrust = o.maxThrustBase 47 | o.currentMinThrust = 0 48 | 49 | return o 50 | end 51 | 52 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 53 | -- @treturn table A table encompasing the api calls of object. 54 | -- @see Element:mockGetClosure 55 | function M:mockGetClosure() 56 | local closure = MockFueledEngine.mockGetClosure(self) 57 | return closure 58 | end 59 | 60 | return M -------------------------------------------------------------------------------- /rockspecs/du-mocks-0.24.0-2.rockspec: -------------------------------------------------------------------------------- 1 | package = "du-mocks" 2 | version = "0.24.0-2" 3 | source = { 4 | url = "git://github.com/1337joe/du-mocks", 5 | tag = "v0.24.0", 6 | } 7 | description = { 8 | summary = "Mock objects to simulate the Dual Universe lua environment.", 9 | detailed = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline.", 10 | homepage = "https://github.com/1337joe/du-mocks", 11 | license = "MIT", 12 | } 13 | dependencies = { 14 | "lua >= 5.2", 15 | 16 | -- build/test dependencies 17 | "ldoc", 18 | "luaunit", 19 | "luacov", 20 | } 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["dumocks.AntiGravityGeneratorUnit"] = "src/dumocks/AntiGravityGeneratorUnit.lua", 25 | ["dumocks.ContainerUnit"] = "src/dumocks/ContainerUnit.lua", 26 | ["dumocks.ControlUnit"] = "src/dumocks/ControlUnit.lua", 27 | ["dumocks.CoreUnit"] = "src/dumocks/CoreUnit.lua", 28 | ["dumocks.CounterUnit"] = "src/dumocks/CounterUnit.lua", 29 | ["dumocks.DatabankUnit"] = "src/dumocks/DatabankUnit.lua", 30 | ["dumocks.DetectionZoneUnit"] = "src/dumocks/DetectionZoneUnit.lua", 31 | ["dumocks.DoorUnit"] = "src/dumocks/DoorUnit.lua", 32 | ["dumocks.Element"] = "src/dumocks/Element.lua", 33 | ["dumocks.ElementWithState"] = "src/dumocks/ElementWithState.lua", 34 | ["dumocks.ElementWithToggle"] = "src/dumocks/ElementWithToggle.lua", 35 | ["dumocks.EmitterUnit"] = "src/dumocks/EmitterUnit.lua", 36 | ["dumocks.EngineUnit"] = "src/dumocks/EngineUnit.lua", 37 | ["dumocks.FireworksUnit"] = "src/dumocks/FireworksUnit.lua", 38 | ["dumocks.ForceFieldUnit"] = "src/dumocks/ForceFieldUnit.lua", 39 | ["dumocks.GyroUnit"] = "src/dumocks/GyroUnit.lua", 40 | ["dumocks.IndustryUnit"] = "src/dumocks/IndustryUnit.lua", 41 | ["dumocks.LandingGearUnit"] = "src/dumocks/LandingGearUnit.lua", 42 | ["dumocks.LaserDetectorUnit"] = "src/dumocks/LaserDetectorUnit.lua", 43 | ["dumocks.LaserEmitterUnit"] = "src/dumocks/LaserEmitterUnit.lua", 44 | ["dumocks.Library"] = "src/dumocks/Library.lua", 45 | ["dumocks.LightUnit"] = "src/dumocks/LightUnit.lua", 46 | ["dumocks.ManualButtonUnit"] = "src/dumocks/ManualButtonUnit.lua", 47 | ["dumocks.ManualSwitchUnit"] = "src/dumocks/ManualSwitchUnit.lua", 48 | ["dumocks.PressureTileUnit"] = "src/dumocks/PressureTileUnit.lua", 49 | ["dumocks.RadarUnit"] = "src/dumocks/RadarUnit.lua", 50 | ["dumocks.ReceiverUnit"] = "src/dumocks/ReceiverUnit.lua", 51 | ["dumocks.ScreenUnit"] = "src/dumocks/ScreenUnit.lua", 52 | ["dumocks.System"] = "src/dumocks/System.lua", 53 | ["dumocks.TelemeterUnit"] = "src/dumocks/TelemeterUnit.lua", 54 | ["dumocks.WarpDriveUnit"] = "src/dumocks/WarpDriveUnit.lua", 55 | }, 56 | copy_directories = { 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /rockspecs/du-mocks-0.24.1-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "du-mocks" 2 | version = "0.24.1-1" 3 | source = { 4 | url = "git://github.com/1337joe/du-mocks", 5 | tag = "v0.24.1", 6 | } 7 | description = { 8 | summary = "Mock objects to simulate the Dual Universe lua environment.", 9 | detailed = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline.", 10 | homepage = "https://github.com/1337joe/du-mocks", 11 | license = "MIT", 12 | } 13 | dependencies = { 14 | "lua >= 5.2", 15 | 16 | -- build/test dependencies 17 | "ldoc", 18 | "luaunit", 19 | "luacov", 20 | } 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["dumocks.AntiGravityGeneratorUnit"] = "src/dumocks/AntiGravityGeneratorUnit.lua", 25 | ["dumocks.ContainerUnit"] = "src/dumocks/ContainerUnit.lua", 26 | ["dumocks.ControlUnit"] = "src/dumocks/ControlUnit.lua", 27 | ["dumocks.CoreUnit"] = "src/dumocks/CoreUnit.lua", 28 | ["dumocks.CounterUnit"] = "src/dumocks/CounterUnit.lua", 29 | ["dumocks.DatabankUnit"] = "src/dumocks/DatabankUnit.lua", 30 | ["dumocks.DetectionZoneUnit"] = "src/dumocks/DetectionZoneUnit.lua", 31 | ["dumocks.DoorUnit"] = "src/dumocks/DoorUnit.lua", 32 | ["dumocks.Element"] = "src/dumocks/Element.lua", 33 | ["dumocks.ElementWithState"] = "src/dumocks/ElementWithState.lua", 34 | ["dumocks.ElementWithToggle"] = "src/dumocks/ElementWithToggle.lua", 35 | ["dumocks.EmitterUnit"] = "src/dumocks/EmitterUnit.lua", 36 | ["dumocks.EngineUnit"] = "src/dumocks/EngineUnit.lua", 37 | ["dumocks.FireworksUnit"] = "src/dumocks/FireworksUnit.lua", 38 | ["dumocks.ForceFieldUnit"] = "src/dumocks/ForceFieldUnit.lua", 39 | ["dumocks.GyroUnit"] = "src/dumocks/GyroUnit.lua", 40 | ["dumocks.IndustryUnit"] = "src/dumocks/IndustryUnit.lua", 41 | ["dumocks.LandingGearUnit"] = "src/dumocks/LandingGearUnit.lua", 42 | ["dumocks.LaserDetectorUnit"] = "src/dumocks/LaserDetectorUnit.lua", 43 | ["dumocks.LaserEmitterUnit"] = "src/dumocks/LaserEmitterUnit.lua", 44 | ["dumocks.Library"] = "src/dumocks/Library.lua", 45 | ["dumocks.LightUnit"] = "src/dumocks/LightUnit.lua", 46 | ["dumocks.ManualButtonUnit"] = "src/dumocks/ManualButtonUnit.lua", 47 | ["dumocks.ManualSwitchUnit"] = "src/dumocks/ManualSwitchUnit.lua", 48 | ["dumocks.PressureTileUnit"] = "src/dumocks/PressureTileUnit.lua", 49 | ["dumocks.RadarUnit"] = "src/dumocks/RadarUnit.lua", 50 | ["dumocks.ReceiverUnit"] = "src/dumocks/ReceiverUnit.lua", 51 | ["dumocks.ScreenUnit"] = "src/dumocks/ScreenUnit.lua", 52 | ["dumocks.System"] = "src/dumocks/System.lua", 53 | ["dumocks.TelemeterUnit"] = "src/dumocks/TelemeterUnit.lua", 54 | ["dumocks.WarpDriveUnit"] = "src/dumocks/WarpDriveUnit.lua", 55 | }, 56 | copy_directories = { 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /rockspecs/du-mocks-0.25.1-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "du-mocks" 2 | version = "0.25.1-1" 3 | source = { 4 | url = "git://github.com/1337joe/du-mocks", 5 | tag = "v0.25.1", 6 | } 7 | description = { 8 | summary = "Mock objects to simulate the Dual Universe lua environment.", 9 | detailed = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline.", 10 | homepage = "https://github.com/1337joe/du-mocks", 11 | license = "MIT", 12 | } 13 | dependencies = { 14 | "lua >= 5.2", 15 | 16 | -- build/test dependencies 17 | "ldoc", 18 | "luaunit", 19 | "luacov", 20 | } 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["dumocks.AntiGravityGeneratorUnit"] = "src/dumocks/AntiGravityGeneratorUnit.lua", 25 | ["dumocks.ContainerUnit"] = "src/dumocks/ContainerUnit.lua", 26 | ["dumocks.ControlUnit"] = "src/dumocks/ControlUnit.lua", 27 | ["dumocks.CoreUnit"] = "src/dumocks/CoreUnit.lua", 28 | ["dumocks.CounterUnit"] = "src/dumocks/CounterUnit.lua", 29 | ["dumocks.DatabankUnit"] = "src/dumocks/DatabankUnit.lua", 30 | ["dumocks.DetectionZoneUnit"] = "src/dumocks/DetectionZoneUnit.lua", 31 | ["dumocks.DoorUnit"] = "src/dumocks/DoorUnit.lua", 32 | ["dumocks.Element"] = "src/dumocks/Element.lua", 33 | ["dumocks.ElementWithState"] = "src/dumocks/ElementWithState.lua", 34 | ["dumocks.ElementWithToggle"] = "src/dumocks/ElementWithToggle.lua", 35 | ["dumocks.EmitterUnit"] = "src/dumocks/EmitterUnit.lua", 36 | ["dumocks.EngineUnit"] = "src/dumocks/EngineUnit.lua", 37 | ["dumocks.FireworksUnit"] = "src/dumocks/FireworksUnit.lua", 38 | ["dumocks.ForceFieldUnit"] = "src/dumocks/ForceFieldUnit.lua", 39 | ["dumocks.GyroUnit"] = "src/dumocks/GyroUnit.lua", 40 | ["dumocks.IndustryUnit"] = "src/dumocks/IndustryUnit.lua", 41 | ["dumocks.LandingGearUnit"] = "src/dumocks/LandingGearUnit.lua", 42 | ["dumocks.LaserDetectorUnit"] = "src/dumocks/LaserDetectorUnit.lua", 43 | ["dumocks.LaserEmitterUnit"] = "src/dumocks/LaserEmitterUnit.lua", 44 | ["dumocks.Library"] = "src/dumocks/Library.lua", 45 | ["dumocks.LightUnit"] = "src/dumocks/LightUnit.lua", 46 | ["dumocks.ManualButtonUnit"] = "src/dumocks/ManualButtonUnit.lua", 47 | ["dumocks.ManualSwitchUnit"] = "src/dumocks/ManualSwitchUnit.lua", 48 | ["dumocks.PressureTileUnit"] = "src/dumocks/PressureTileUnit.lua", 49 | ["dumocks.RadarUnit"] = "src/dumocks/RadarUnit.lua", 50 | ["dumocks.ReceiverUnit"] = "src/dumocks/ReceiverUnit.lua", 51 | ["dumocks.ScreenUnit"] = "src/dumocks/ScreenUnit.lua", 52 | ["dumocks.System"] = "src/dumocks/System.lua", 53 | ["dumocks.TelemeterUnit"] = "src/dumocks/TelemeterUnit.lua", 54 | ["dumocks.WarpDriveUnit"] = "src/dumocks/WarpDriveUnit.lua", 55 | }, 56 | copy_directories = { 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /rockspecs/du-mocks-0.26.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "du-mocks" 2 | version = "0.26.0-1" 3 | source = { 4 | url = "git://github.com/1337joe/du-mocks", 5 | tag = "v0.26.0", 6 | } 7 | description = { 8 | summary = "Mock objects to simulate the Dual Universe lua environment.", 9 | detailed = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline.", 10 | homepage = "https://github.com/1337joe/du-mocks", 11 | license = "MIT", 12 | } 13 | dependencies = { 14 | "lua >= 5.2", 15 | 16 | -- build/test dependencies 17 | "ldoc", 18 | "luaunit", 19 | "luacov", 20 | } 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["dumocks.AntiGravityGeneratorUnit"] = "src/dumocks/AntiGravityGeneratorUnit.lua", 25 | ["dumocks.ContainerUnit"] = "src/dumocks/ContainerUnit.lua", 26 | ["dumocks.ControlUnit"] = "src/dumocks/ControlUnit.lua", 27 | ["dumocks.CoreUnit"] = "src/dumocks/CoreUnit.lua", 28 | ["dumocks.CounterUnit"] = "src/dumocks/CounterUnit.lua", 29 | ["dumocks.DatabankUnit"] = "src/dumocks/DatabankUnit.lua", 30 | ["dumocks.DetectionZoneUnit"] = "src/dumocks/DetectionZoneUnit.lua", 31 | ["dumocks.DoorUnit"] = "src/dumocks/DoorUnit.lua", 32 | ["dumocks.Element"] = "src/dumocks/Element.lua", 33 | ["dumocks.ElementWithState"] = "src/dumocks/ElementWithState.lua", 34 | ["dumocks.ElementWithToggle"] = "src/dumocks/ElementWithToggle.lua", 35 | ["dumocks.EmitterUnit"] = "src/dumocks/EmitterUnit.lua", 36 | ["dumocks.EngineUnit"] = "src/dumocks/EngineUnit.lua", 37 | ["dumocks.FireworksUnit"] = "src/dumocks/FireworksUnit.lua", 38 | ["dumocks.ForceFieldUnit"] = "src/dumocks/ForceFieldUnit.lua", 39 | ["dumocks.GyroUnit"] = "src/dumocks/GyroUnit.lua", 40 | ["dumocks.IndustryUnit"] = "src/dumocks/IndustryUnit.lua", 41 | ["dumocks.LandingGearUnit"] = "src/dumocks/LandingGearUnit.lua", 42 | ["dumocks.LaserDetectorUnit"] = "src/dumocks/LaserDetectorUnit.lua", 43 | ["dumocks.LaserEmitterUnit"] = "src/dumocks/LaserEmitterUnit.lua", 44 | ["dumocks.Library"] = "src/dumocks/Library.lua", 45 | ["dumocks.LightUnit"] = "src/dumocks/LightUnit.lua", 46 | ["dumocks.ManualButtonUnit"] = "src/dumocks/ManualButtonUnit.lua", 47 | ["dumocks.ManualSwitchUnit"] = "src/dumocks/ManualSwitchUnit.lua", 48 | ["dumocks.PressureTileUnit"] = "src/dumocks/PressureTileUnit.lua", 49 | ["dumocks.RadarUnit"] = "src/dumocks/RadarUnit.lua", 50 | ["dumocks.ReceiverUnit"] = "src/dumocks/ReceiverUnit.lua", 51 | ["dumocks.ScreenRenderer"] = "src/dumocks/ScreenRenderer.lua", 52 | ["dumocks.ScreenUnit"] = "src/dumocks/ScreenUnit.lua", 53 | ["dumocks.ShieldGeneratorUnit"] = "src/dumocks/ShieldGeneratorUnit.lua", 54 | ["dumocks.System"] = "src/dumocks/System.lua", 55 | ["dumocks.TelemeterUnit"] = "src/dumocks/TelemeterUnit.lua", 56 | ["dumocks.WarpDriveUnit"] = "src/dumocks/WarpDriveUnit.lua", 57 | ["dumocks.WeaponUnit"] = "src/dumocks/WeaponUnit.lua", 58 | }, 59 | copy_directories = { 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /rockspecs/du-mocks-0.26.1-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "du-mocks" 2 | version = "0.26.1-1" 3 | source = { 4 | url = "git://github.com/1337joe/du-mocks", 5 | tag = "v0.26.1", 6 | } 7 | description = { 8 | summary = "Mock objects to simulate the Dual Universe lua environment.", 9 | detailed = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline.", 10 | homepage = "https://github.com/1337joe/du-mocks", 11 | license = "MIT", 12 | } 13 | dependencies = { 14 | "lua >= 5.2", 15 | 16 | -- build/test dependencies 17 | "ldoc", 18 | "luaunit", 19 | "luacov", 20 | } 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["dumocks.AntiGravityGeneratorUnit"] = "src/dumocks/AntiGravityGeneratorUnit.lua", 25 | ["dumocks.ContainerUnit"] = "src/dumocks/ContainerUnit.lua", 26 | ["dumocks.ControlUnit"] = "src/dumocks/ControlUnit.lua", 27 | ["dumocks.CoreUnit"] = "src/dumocks/CoreUnit.lua", 28 | ["dumocks.CounterUnit"] = "src/dumocks/CounterUnit.lua", 29 | ["dumocks.DatabankUnit"] = "src/dumocks/DatabankUnit.lua", 30 | ["dumocks.DetectionZoneUnit"] = "src/dumocks/DetectionZoneUnit.lua", 31 | ["dumocks.DoorUnit"] = "src/dumocks/DoorUnit.lua", 32 | ["dumocks.Element"] = "src/dumocks/Element.lua", 33 | ["dumocks.ElementWithState"] = "src/dumocks/ElementWithState.lua", 34 | ["dumocks.ElementWithToggle"] = "src/dumocks/ElementWithToggle.lua", 35 | ["dumocks.EmitterUnit"] = "src/dumocks/EmitterUnit.lua", 36 | ["dumocks.EngineUnit"] = "src/dumocks/EngineUnit.lua", 37 | ["dumocks.FireworksUnit"] = "src/dumocks/FireworksUnit.lua", 38 | ["dumocks.ForceFieldUnit"] = "src/dumocks/ForceFieldUnit.lua", 39 | ["dumocks.GyroUnit"] = "src/dumocks/GyroUnit.lua", 40 | ["dumocks.IndustryUnit"] = "src/dumocks/IndustryUnit.lua", 41 | ["dumocks.LandingGearUnit"] = "src/dumocks/LandingGearUnit.lua", 42 | ["dumocks.LaserDetectorUnit"] = "src/dumocks/LaserDetectorUnit.lua", 43 | ["dumocks.LaserEmitterUnit"] = "src/dumocks/LaserEmitterUnit.lua", 44 | ["dumocks.Library"] = "src/dumocks/Library.lua", 45 | ["dumocks.LightUnit"] = "src/dumocks/LightUnit.lua", 46 | ["dumocks.ManualButtonUnit"] = "src/dumocks/ManualButtonUnit.lua", 47 | ["dumocks.ManualSwitchUnit"] = "src/dumocks/ManualSwitchUnit.lua", 48 | ["dumocks.PressureTileUnit"] = "src/dumocks/PressureTileUnit.lua", 49 | ["dumocks.RadarUnit"] = "src/dumocks/RadarUnit.lua", 50 | ["dumocks.ReceiverUnit"] = "src/dumocks/ReceiverUnit.lua", 51 | ["dumocks.ScreenRenderer"] = "src/dumocks/ScreenRenderer.lua", 52 | ["dumocks.ScreenUnit"] = "src/dumocks/ScreenUnit.lua", 53 | ["dumocks.ShieldGeneratorUnit"] = "src/dumocks/ShieldGeneratorUnit.lua", 54 | ["dumocks.System"] = "src/dumocks/System.lua", 55 | ["dumocks.TelemeterUnit"] = "src/dumocks/TelemeterUnit.lua", 56 | ["dumocks.WarpDriveUnit"] = "src/dumocks/WarpDriveUnit.lua", 57 | ["dumocks.WeaponUnit"] = "src/dumocks/WeaponUnit.lua", 58 | }, 59 | copy_directories = { 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /rockspecs/du-mocks-0.28.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "du-mocks" 2 | version = "0.28.0-1" 3 | source = { 4 | url = "git+https://github.com/1337joe/du-mocks.git", 5 | tag = "v0.28.0", 6 | } 7 | description = { 8 | summary = "Mock objects to simulate the Dual Universe lua environment.", 9 | detailed = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline.", 10 | homepage = "https://github.com/1337joe/du-mocks", 11 | license = "MIT", 12 | } 13 | dependencies = { 14 | "lua >= 5.3", 15 | 16 | -- build/test dependencies 17 | "ldoc", 18 | "luaunit", 19 | "luacov", 20 | } 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["dumocks.AntiGravityGeneratorUnit"] = "src/dumocks/AntiGravityGeneratorUnit.lua", 25 | ["dumocks.ContainerUnit"] = "src/dumocks/ContainerUnit.lua", 26 | ["dumocks.ControlUnit"] = "src/dumocks/ControlUnit.lua", 27 | ["dumocks.CoreUnit"] = "src/dumocks/CoreUnit.lua", 28 | ["dumocks.CounterUnit"] = "src/dumocks/CounterUnit.lua", 29 | ["dumocks.DatabankUnit"] = "src/dumocks/DatabankUnit.lua", 30 | ["dumocks.DetectionZoneUnit"] = "src/dumocks/DetectionZoneUnit.lua", 31 | ["dumocks.DoorUnit"] = "src/dumocks/DoorUnit.lua", 32 | ["dumocks.Element"] = "src/dumocks/Element.lua", 33 | ["dumocks.ElementWithState"] = "src/dumocks/ElementWithState.lua", 34 | ["dumocks.ElementWithToggle"] = "src/dumocks/ElementWithToggle.lua", 35 | ["dumocks.EmitterUnit"] = "src/dumocks/EmitterUnit.lua", 36 | ["dumocks.EngineUnit"] = "src/dumocks/EngineUnit.lua", 37 | ["dumocks.FireworksUnit"] = "src/dumocks/FireworksUnit.lua", 38 | ["dumocks.ForceFieldUnit"] = "src/dumocks/ForceFieldUnit.lua", 39 | ["dumocks.GyroUnit"] = "src/dumocks/GyroUnit.lua", 40 | ["dumocks.IndustryUnit"] = "src/dumocks/IndustryUnit.lua", 41 | ["dumocks.LandingGearUnit"] = "src/dumocks/LandingGearUnit.lua", 42 | ["dumocks.LaserDetectorUnit"] = "src/dumocks/LaserDetectorUnit.lua", 43 | ["dumocks.LaserEmitterUnit"] = "src/dumocks/LaserEmitterUnit.lua", 44 | ["dumocks.Library"] = "src/dumocks/Library.lua", 45 | ["dumocks.LightUnit"] = "src/dumocks/LightUnit.lua", 46 | ["dumocks.ManualButtonUnit"] = "src/dumocks/ManualButtonUnit.lua", 47 | ["dumocks.ManualSwitchUnit"] = "src/dumocks/ManualSwitchUnit.lua", 48 | ["dumocks.PressureTileUnit"] = "src/dumocks/PressureTileUnit.lua", 49 | ["dumocks.RadarUnit"] = "src/dumocks/RadarUnit.lua", 50 | ["dumocks.ReceiverUnit"] = "src/dumocks/ReceiverUnit.lua", 51 | ["dumocks.ScreenRenderer"] = "src/dumocks/ScreenRenderer.lua", 52 | ["dumocks.ScreenUnit"] = "src/dumocks/ScreenUnit.lua", 53 | ["dumocks.ShieldGeneratorUnit"] = "src/dumocks/ShieldGeneratorUnit.lua", 54 | ["dumocks.System"] = "src/dumocks/System.lua", 55 | ["dumocks.TelemeterUnit"] = "src/dumocks/TelemeterUnit.lua", 56 | ["dumocks.TransponderUnit"] = "src/dumocks/TransponderUnit.lua", 57 | ["dumocks.WarpDriveUnit"] = "src/dumocks/WarpDriveUnit.lua", 58 | ["dumocks.WeaponUnit"] = "src/dumocks/WeaponUnit.lua", 59 | }, 60 | copy_directories = { 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /test/renderScript/fontSampler.lua: -------------------------------------------------------------------------------- 1 | -- Render a range of text in each font as well as some measurements. 2 | -- persistent data, only clears when screen fully reloaded 3 | persistent = persistent or { 4 | index = 1 5 | } 6 | 7 | local MAX_FONTS_LOADED = 8 8 | 9 | local xRes, yRes = getResolution() 10 | local layer = createLayer() 11 | 12 | local fontCount = getAvailableFontCount() 13 | 14 | local yStep = yRes / MAX_FONTS_LOADED 15 | local xOff, yOff 16 | 17 | local index, fontName, font 18 | local size, ascender, descender 19 | local CHARACTER_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890" 20 | local width, height 21 | for i = 1, MAX_FONTS_LOADED do 22 | index = persistent.index + i - 1 23 | fontName = getAvailableFontName(index) 24 | font = loadFont(fontName, yStep / 2) 25 | xOff, yOff = 20, yStep * i 26 | 27 | addText(layer, font, string.format("%d: %s", index, fontName), xOff, yOff - yStep / 3) 28 | 29 | setFontSize(font, yStep / 3) 30 | addText(layer, font, "012345ABCDEFGHIjklmnop", xOff, yOff) 31 | 32 | -- characterize font data 33 | size = 20 34 | setFontSize(font, size) 35 | 36 | ascender, descender = getFontMetrics(font) 37 | ascender = ascender / size 38 | descender = descender / size 39 | 40 | local data = {} 41 | for i = 1, #CHARACTER_STRING do 42 | width, height = getTextBounds(font, CHARACTER_STRING:sub(i, i)) 43 | data[i] = {width / size, height / size} 44 | end 45 | width = { 46 | sum = 0 47 | } 48 | height = { 49 | sum = 0 50 | } 51 | for _, metrics in pairs(data) do 52 | if not width.min then 53 | width.min = metrics[1] 54 | else 55 | width.min = math.min(width.min, metrics[1]) 56 | end 57 | if not height.min then 58 | height.min = metrics[2] 59 | else 60 | height.min = math.min(height.min, metrics[2]) 61 | end 62 | 63 | if not width.max then 64 | width.max = metrics[1] 65 | else 66 | width.max = math.max(width.max, metrics[1]) 67 | end 68 | if not height.max then 69 | height.max = metrics[2] 70 | else 71 | height.max = math.max(height.max, metrics[2]) 72 | end 73 | 74 | width.sum = width.sum + metrics[1] 75 | height.sum = height.sum + metrics[2] 76 | end 77 | 78 | xOff = xRes / 2 79 | setFontSize(font, yStep / 3) 80 | addText(layer, font, "FM: " .. ascender .. "/" .. descender, xOff, yOff - yStep * 2 / 3) 81 | -- addText(layer, font, "W: " .. width.min .. "/" .. width.max .. "/" .. (width.sum / #data), xOff, yOff - yStep * 1 / 3) 82 | -- addText(layer, font, "H: " .. height.min .. "/" .. height.max .. "/" .. (height.sum / #data), xOff, yOff) 83 | addText(layer, font, "W: " .. (width.sum / #data), xOff, yOff - yStep * 1 / 3) 84 | addText(layer, font, "H: " .. (height.sum / #data), xOff, yOff) 85 | 86 | if index >= fontCount then 87 | break 88 | end 89 | end 90 | 91 | if getCursorDown() then 92 | persistent.index = persistent.index + 8 93 | if persistent.index > fontCount then 94 | persistent.index = 1 95 | end 96 | end 97 | -------------------------------------------------------------------------------- /test/dumocks/TestAdjustorUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.AdjustorUnit. 3 | -- @see dumocks.AdjustorUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mau = require("dumocks.AdjustorUnit") 11 | require("test.Utilities") 12 | 13 | TestAdjustorUnit = {} 14 | 15 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 16 | -- in-game. 17 | -- 18 | -- Test setup: 19 | -- 1. adjustor of any size, connected to Programming Board on slot1 20 | -- 21 | -- Exercises: getClass, getWidgetData 22 | function _G.TestAdjustorUnit.testGameBehavior() 23 | local mock = mau:new(nil, 1) 24 | local slot1 = mock:mockGetClosure() 25 | 26 | -- stub this in directly to supress print in the unit test 27 | local unit = {} 28 | unit.exit = function() 29 | end 30 | local system = {} 31 | system.print = function(_) 32 | end 33 | 34 | --------------- 35 | -- copy from here to unit.onStart() 36 | --------------- 37 | local expectedFunctions = {"activate", "deactivate", "isActive", "toggle", "setThrust", "getThrust", 38 | "getMaxThrust", "getThrustAxis", "getTorqueAxis", "getWorldThrustAxis", 39 | "getWorldTorqueAxis", "getSignalIn", "setSignalIn", 40 | "getObstructionFactor", "getTags", "setTags", "isIgnoringTags", 41 | "getState", "getT50", "getFuelRateEfficiency", "getDistance", "getFuelConsumption", 42 | "isOutOfFuel", "torqueAxis", "hasFunctionalFuelTank", "thrustAxis", 43 | "getCurrentFuelRate", "getMaxThrustBase"} 44 | for _, v in pairs(_G.Utilities.elementFunctions) do 45 | table.insert(expectedFunctions, v) 46 | end 47 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 48 | 49 | -- test element class and inherited methods 50 | assert(slot1.getClass() == "Adjustor") 51 | assert(string.match(string.lower(slot1.getName()), "adjustor %w+ %[%d+%]"), slot1.getName()) 52 | local expectedId = {[2648523849] = true, [47474508] = true, [3790013467] = true, [2818864930] = true} 53 | assert(expectedId[slot1.getItemId()], "Unexpected id: " .. slot1.getItemId()) 54 | assert(slot1.getMaxHitPoints() >= 50.0) 55 | assert(slot1.getMass() >= 25.0) 56 | 57 | -- test inherited methods 58 | local data = slot1.getWidgetData() 59 | local expectedFields = {"helperId", "name", "type", "currentMaxThrust", "currentThrust", "maxThrustBase"} 60 | local expectedValues = {} 61 | expectedValues["type"] = '"engine_unit"' 62 | expectedValues["helperId"] = '"engine_unit"' 63 | _G.Utilities.verifyWidgetData(data, expectedFields, expectedValues) 64 | 65 | assert(slot1.getMaxHitPoints() >= 50.0) 66 | assert(slot1.getMass() > 7.0) 67 | _G.Utilities.verifyBasicElementFunctions(slot1, 3, "engine_unit") 68 | 69 | slot1.activate() 70 | 71 | system.print("Success") 72 | unit.exit() 73 | --------------- 74 | -- copy to here to unit.onStart() 75 | --------------- 76 | end 77 | 78 | os.exit(lu.LuaUnit.run()) 79 | -------------------------------------------------------------------------------- /src/dumocks/LaserEmitterUnit.lua: -------------------------------------------------------------------------------- 1 | --- Laser emitter unit. 2 | -- Emits a laser ray that can be use to detect the passage of a player or on a laser detector unit. 3 | -- 4 | -- Element class: LaserEmitterUnit 5 | -- 6 | -- Extends: @{Element} > @{ElementWithState} > @{ElementWithToggle} 7 | -- @module LaserEmitterUnit 8 | -- @alias M 9 | 10 | local MockElement = require "dumocks.Element" 11 | local MockElementWithToggle = require "dumocks.ElementWithToggle" 12 | 13 | local elementDefinitions = {} 14 | elementDefinitions["laser emitter xs"] = {mass = 7.47, maxHitPoints = 50.0, itemId = 1784722190} 15 | elementDefinitions["infrared laser emitter xs"] = {mass = 9.93, maxHitPoints = 50.0, itemId = 609676854} 16 | local DEFAULT_ELEMENT = "laser emitter xs" 17 | 18 | local M = MockElementWithToggle:new() 19 | M.elementClass = "LaserEmitterUnit" 20 | 21 | function M:new(o, id, elementName) 22 | local elementDefinition = MockElement.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 23 | 24 | o = o or MockElementWithToggle:new(o, id, elementDefinition) 25 | setmetatable(o, self) 26 | self.__index = self 27 | 28 | o.plugIn = 0.0 29 | 30 | return o 31 | end 32 | 33 | --- Activates the laser emitter. 34 | function M:activate() 35 | self.state = true 36 | end 37 | 38 | --- Deactivates the laser emitter. 39 | function M:deactivate() 40 | self.state = false 41 | end 42 | 43 | --- Checks if the laser emitter is active. 44 | -- @treturn 0/1 1 if the laser emitter is active. 45 | function M:isActive() 46 | if self.state then 47 | return 1 48 | end 49 | return 0 50 | end 51 | 52 | --- Set the value of a signal in the specified IN plug of the element. 53 | -- 54 | -- Valid plug names are: 55 | --
    56 | --
  • "in" for the in signal (seems to have no actual effect when modified this way).
  • 57 | --
58 | -- @tparam string plug A valid plug name to set. 59 | -- @tparam 0/1 state The plug signal state 60 | function M:setSignalIn(plug, state) 61 | if plug == "in" then 62 | -- no longer responds to setSignalIn 63 | end 64 | end 65 | 66 | --- Return the value of a signal in the specified IN plug of the element. 67 | -- 68 | -- Valid plug names are: 69 | --
    70 | --
  • "in" for the in signal.
  • 71 | --
72 | -- @tparam string plug A valid plug name to query. 73 | -- @treturn 0/1 The plug signal state 74 | function M:getSignalIn(plug) 75 | if plug == "in" then 76 | return self.plugIn 77 | end 78 | return MockElement.getSignalIn(self) 79 | end 80 | 81 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 82 | -- @treturn table A table encompasing the api calls of object. 83 | -- @see Element:mockGetClosure 84 | function M:mockGetClosure() 85 | local closure = MockElementWithToggle.mockGetClosure(self) 86 | closure.activate = function() return self:activate() end 87 | closure.deactivate = function() return self:deactivate() end 88 | closure.isActive = function() return self:isActive() end 89 | 90 | closure.setSignalIn = function(plug, state) return self:setSignalIn(plug, state) end 91 | closure.getSignalIn = function(plug) return self:getSignalIn(plug) end 92 | return closure 93 | end 94 | 95 | return M -------------------------------------------------------------------------------- /test/renderScript/strokeAlign.lua: -------------------------------------------------------------------------------- 1 | -- Render a sampling of line stroke widths and text alignments. 2 | -- 3 columns: 3 | -- - line with custom stroke width/line with default stroke width 4 | -- - AlignV values 5 | -- - AlignH values 6 | 7 | local xRes, yRes = getResolution() 8 | local layer = createLayer() 9 | 10 | local xStart, xEnd 11 | 12 | -- Compare default stroke width to various sizes 13 | local values = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 50} 14 | 15 | local spacing = yRes / (#values + 1) 16 | xStart, xEnd = spacing, xRes / 2 - spacing 17 | local xJoin = (xStart + xEnd) / 2 18 | 19 | addLine(layer, 0, 0, xRes / 2, 0) 20 | addLine(layer, 0, yRes, xRes / 2, yRes) 21 | 22 | for k,v in pairs(values) do 23 | setNextStrokeWidth(layer, v) 24 | addLine(layer, xStart, spacing * k, xJoin, spacing * k) 25 | addLine(layer, xJoin, spacing * k, xEnd, spacing * k) 26 | end 27 | 28 | -- Test various font alignment values 29 | setDefaultStrokeColor(layer, Shape_Line, 0.3, 0.3, 0.3, 1) 30 | local font = loadFont("RobotoMono", 30) 31 | 32 | local x, y, yStep 33 | 34 | -- AlignV 35 | yStep = yRes / 8 36 | xStart, xEnd = xRes / 2, xRes * 3 / 4 37 | x = xRes * 9 / 16 38 | y = yStep 39 | 40 | addLine(layer, x, 0, x, yRes) 41 | 42 | addLine(layer, xStart, y, xEnd, y) 43 | addText(layer, font, "Default", x, y) 44 | y = y + yStep 45 | 46 | addLine(layer, xStart, y, xEnd, y) 47 | setNextTextAlign(layer, AlignH_Left, AlignV_Ascender) 48 | addText(layer, font, "Ascender", x, y) 49 | y = y + yStep 50 | 51 | addLine(layer, xStart, y, xEnd, y) 52 | setNextTextAlign(layer, AlignH_Left, AlignV_Top) 53 | addText(layer, font, "Top", x, y) 54 | y = y + yStep 55 | 56 | addLine(layer, xStart, y, xEnd, y) 57 | setNextTextAlign(layer, AlignH_Left, AlignV_Middle) 58 | addText(layer, font, "Middle", x, y) 59 | y = y + yStep 60 | 61 | addLine(layer, xStart, y, xEnd, y) 62 | setNextTextAlign(layer, AlignH_Left, AlignV_Baseline) 63 | addText(layer, font, "Baseline", x, y) 64 | y = y + yStep 65 | 66 | addLine(layer, xStart, y, xEnd, y) 67 | setNextTextAlign(layer, AlignH_Left, AlignV_Bottom) 68 | addText(layer, font, "Bottom", x, y) 69 | y = y + yStep 70 | 71 | addLine(layer, xStart, y, xEnd, y) 72 | setNextTextAlign(layer, AlignH_Left, AlignV_Descender) 73 | addText(layer, font, "Descender", x, y) 74 | y = y + yStep 75 | 76 | -- AlignH 77 | yStep = yRes / 6 78 | xStart, xEnd = xRes * 3 / 4, xRes 79 | x = xRes * 7 / 8 80 | y = yStep 81 | 82 | addLine(layer, x, 0, x, yRes) 83 | 84 | addLine(layer, xStart, y, xEnd, y) 85 | addText(layer, font, "Default", x, y) 86 | y = y + yStep 87 | 88 | addLine(layer, xStart, y, xEnd, y) 89 | setNextTextAlign(layer, AlignH_Left, AlignV_Baseline) 90 | addText(layer, font, "Left", x, y) 91 | y = y + yStep 92 | 93 | addLine(layer, xStart, y, xEnd, y) 94 | setNextTextAlign(layer, AlignH_Center, AlignV_Baseline) 95 | addText(layer, font, "Center", x, y) 96 | y = y + yStep 97 | 98 | addLine(layer, xStart, y, xEnd, y) 99 | setNextTextAlign(layer, AlignH_Right, AlignV_Baseline) 100 | addText(layer, font, "Right", x, y) 101 | y = y + yStep 102 | 103 | addLine(layer, xStart, y, xEnd, y) 104 | setDefaultTextAlign(layer, AlignH_Center, AlignV_Middle) 105 | addText(layer, font, "Both Center", x, y) 106 | y = y + yStep 107 | -------------------------------------------------------------------------------- /rockspecs/du-mocks-0.29.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "du-mocks" 2 | version = "0.29.0-1" 3 | source = { 4 | url = "git+https://github.com/1337joe/du-mocks.git", 5 | tag = "v0.29.0" 6 | } 7 | description = { 8 | summary = "Mock objects to simulate the Dual Universe lua environment.", 9 | detailed = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline.", 10 | homepage = "https://github.com/1337joe/du-mocks", 11 | license = "MIT", 12 | } 13 | dependencies = { 14 | "lua >= 5.3", 15 | 16 | -- build/test dependencies 17 | "ldoc", 18 | "luaunit", 19 | "luacov", 20 | } 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["dumocks.AntiGravityGeneratorUnit"] = "src/dumocks/AntiGravityGeneratorUnit.lua", 25 | ["dumocks.BaseShieldGeneratorUnit"] = "src/dumocks/BaseShieldGeneratorUnit.lua", 26 | ["dumocks.ContainerUnit"] = "src/dumocks/ContainerUnit.lua", 27 | ["dumocks.ControlUnit"] = "src/dumocks/ControlUnit.lua", 28 | ["dumocks.CoreUnit"] = "src/dumocks/CoreUnit.lua", 29 | ["dumocks.CounterUnit"] = "src/dumocks/CounterUnit.lua", 30 | ["dumocks.DatabankUnit"] = "src/dumocks/DatabankUnit.lua", 31 | ["dumocks.DetectionZoneUnit"] = "src/dumocks/DetectionZoneUnit.lua", 32 | ["dumocks.DoorUnit"] = "src/dumocks/DoorUnit.lua", 33 | ["dumocks.Element"] = "src/dumocks/Element.lua", 34 | ["dumocks.ElementWithState"] = "src/dumocks/ElementWithState.lua", 35 | ["dumocks.ElementWithToggle"] = "src/dumocks/ElementWithToggle.lua", 36 | ["dumocks.EmitterUnit"] = "src/dumocks/EmitterUnit.lua", 37 | ["dumocks.EngineUnit"] = "src/dumocks/EngineUnit.lua", 38 | ["dumocks.FireworksUnit"] = "src/dumocks/FireworksUnit.lua", 39 | ["dumocks.ForceFieldUnit"] = "src/dumocks/ForceFieldUnit.lua", 40 | ["dumocks.GyroUnit"] = "src/dumocks/GyroUnit.lua", 41 | ["dumocks.IndustryUnit"] = "src/dumocks/IndustryUnit.lua", 42 | ["dumocks.LandingGearUnit"] = "src/dumocks/LandingGearUnit.lua", 43 | ["dumocks.LaserDetectorUnit"] = "src/dumocks/LaserDetectorUnit.lua", 44 | ["dumocks.LaserEmitterUnit"] = "src/dumocks/LaserEmitterUnit.lua", 45 | ["dumocks.Library"] = "src/dumocks/Library.lua", 46 | ["dumocks.LightUnit"] = "src/dumocks/LightUnit.lua", 47 | ["dumocks.ManualButtonUnit"] = "src/dumocks/ManualButtonUnit.lua", 48 | ["dumocks.ManualSwitchUnit"] = "src/dumocks/ManualSwitchUnit.lua", 49 | ["dumocks.MiningUnit"] = "src/dumocks/MiningUnit.lua", 50 | ["dumocks.PressureTileUnit"] = "src/dumocks/PressureTileUnit.lua", 51 | ["dumocks.RadarUnit"] = "src/dumocks/RadarUnit.lua", 52 | ["dumocks.ReceiverUnit"] = "src/dumocks/ReceiverUnit.lua", 53 | ["dumocks.RenderScript"] = "src/dumocks/RenderScript.lua", 54 | ["dumocks.ScreenUnit"] = "src/dumocks/ScreenUnit.lua", 55 | ["dumocks.ShieldGeneratorUnit"] = "src/dumocks/ShieldGeneratorUnit.lua", 56 | ["dumocks.System"] = "src/dumocks/System.lua", 57 | ["dumocks.TelemeterUnit"] = "src/dumocks/TelemeterUnit.lua", 58 | ["dumocks.TransponderUnit"] = "src/dumocks/TransponderUnit.lua", 59 | ["dumocks.WarpDriveUnit"] = "src/dumocks/WarpDriveUnit.lua", 60 | ["dumocks.WeaponUnit"] = "src/dumocks/WeaponUnit.lua", 61 | }, 62 | copy_directories = { 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /rockspecs/du-mocks-0.29.1-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "du-mocks" 2 | version = "0.29.1-1" 3 | source = { 4 | url = "git+https://github.com/1337joe/du-mocks.git", 5 | tag = "v0.29.1" 6 | } 7 | description = { 8 | summary = "Mock objects to simulate the Dual Universe lua environment.", 9 | detailed = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline.", 10 | homepage = "https://github.com/1337joe/du-mocks", 11 | license = "MIT", 12 | } 13 | dependencies = { 14 | "lua >= 5.3", 15 | 16 | -- build/test dependencies 17 | "ldoc", 18 | "luaunit", 19 | "luacov", 20 | } 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["dumocks.AntiGravityGeneratorUnit"] = "src/dumocks/AntiGravityGeneratorUnit.lua", 25 | ["dumocks.BaseShieldGeneratorUnit"] = "src/dumocks/BaseShieldGeneratorUnit.lua", 26 | ["dumocks.ContainerUnit"] = "src/dumocks/ContainerUnit.lua", 27 | ["dumocks.ControlUnit"] = "src/dumocks/ControlUnit.lua", 28 | ["dumocks.CoreUnit"] = "src/dumocks/CoreUnit.lua", 29 | ["dumocks.CounterUnit"] = "src/dumocks/CounterUnit.lua", 30 | ["dumocks.DatabankUnit"] = "src/dumocks/DatabankUnit.lua", 31 | ["dumocks.DetectionZoneUnit"] = "src/dumocks/DetectionZoneUnit.lua", 32 | ["dumocks.DoorUnit"] = "src/dumocks/DoorUnit.lua", 33 | ["dumocks.Element"] = "src/dumocks/Element.lua", 34 | ["dumocks.ElementWithState"] = "src/dumocks/ElementWithState.lua", 35 | ["dumocks.ElementWithToggle"] = "src/dumocks/ElementWithToggle.lua", 36 | ["dumocks.EmitterUnit"] = "src/dumocks/EmitterUnit.lua", 37 | ["dumocks.EngineUnit"] = "src/dumocks/EngineUnit.lua", 38 | ["dumocks.FireworksUnit"] = "src/dumocks/FireworksUnit.lua", 39 | ["dumocks.ForceFieldUnit"] = "src/dumocks/ForceFieldUnit.lua", 40 | ["dumocks.GyroUnit"] = "src/dumocks/GyroUnit.lua", 41 | ["dumocks.IndustryUnit"] = "src/dumocks/IndustryUnit.lua", 42 | ["dumocks.LandingGearUnit"] = "src/dumocks/LandingGearUnit.lua", 43 | ["dumocks.LaserDetectorUnit"] = "src/dumocks/LaserDetectorUnit.lua", 44 | ["dumocks.LaserEmitterUnit"] = "src/dumocks/LaserEmitterUnit.lua", 45 | ["dumocks.Library"] = "src/dumocks/Library.lua", 46 | ["dumocks.LightUnit"] = "src/dumocks/LightUnit.lua", 47 | ["dumocks.ManualButtonUnit"] = "src/dumocks/ManualButtonUnit.lua", 48 | ["dumocks.ManualSwitchUnit"] = "src/dumocks/ManualSwitchUnit.lua", 49 | ["dumocks.MiningUnit"] = "src/dumocks/MiningUnit.lua", 50 | ["dumocks.PressureTileUnit"] = "src/dumocks/PressureTileUnit.lua", 51 | ["dumocks.RadarUnit"] = "src/dumocks/RadarUnit.lua", 52 | ["dumocks.ReceiverUnit"] = "src/dumocks/ReceiverUnit.lua", 53 | ["dumocks.RenderScript"] = "src/dumocks/RenderScript.lua", 54 | ["dumocks.ScreenUnit"] = "src/dumocks/ScreenUnit.lua", 55 | ["dumocks.ShieldGeneratorUnit"] = "src/dumocks/ShieldGeneratorUnit.lua", 56 | ["dumocks.System"] = "src/dumocks/System.lua", 57 | ["dumocks.TelemeterUnit"] = "src/dumocks/TelemeterUnit.lua", 58 | ["dumocks.TransponderUnit"] = "src/dumocks/TransponderUnit.lua", 59 | ["dumocks.WarpDriveUnit"] = "src/dumocks/WarpDriveUnit.lua", 60 | ["dumocks.WeaponUnit"] = "src/dumocks/WeaponUnit.lua", 61 | }, 62 | copy_directories = { 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/dumocks/LandingGearUnit.lua: -------------------------------------------------------------------------------- 1 | --- A landing gear that can be opened or closed. 2 | -- 3 | -- Element class: LandingGearUnit 4 | -- 5 | -- Extends: @{Element} > @{ElementWithState} > @{ElementWithToggle} 6 | -- @module LandingGearUnit 7 | -- @alias M 8 | 9 | local MockElement = require "dumocks.Element" 10 | local MockElementWithToggle = require "dumocks.ElementWithToggle" 11 | 12 | local elementDefinitions = {} 13 | elementDefinitions["landing gear xs"] = {mass = 49.88, maxHitPoints = 1250.0, itemId = 4078067869} 14 | elementDefinitions["landing gear s"] = {mass = 258.76, maxHitPoints = 5000.0, itemId = 1884031929} 15 | elementDefinitions["landing gear m"] = {mass = 1460.65, maxHitPoints = 20000.0, itemId = 1899560165} 16 | elementDefinitions["landing gear l"] = {mass = 8500.63, maxHitPoints = 80000.0, itemId = 2667697870} 17 | local DEFAULT_ELEMENT = "landing gear s" 18 | 19 | local M = MockElementWithToggle:new() 20 | M.elementClass = "LandingGearUnit" 21 | 22 | function M:new(o, id, elementName) 23 | local elementDefinition = MockElement.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 24 | 25 | o = o or MockElementWithToggle:new(o, id, elementDefinition) 26 | setmetatable(o, self) 27 | self.__index = self 28 | 29 | o.plugIn = 0.0 30 | 31 | return o 32 | end 33 | 34 | --- Deploys the landing gear. 35 | function M:deploy() 36 | self.state = true 37 | end 38 | 39 | --- Retracts the landing gear. 40 | function M:retract() 41 | self.state = false 42 | end 43 | 44 | --- Checks if the landing gear is deployed. 45 | -- @treturn 0/1 1 if the landing gear is deployed. 46 | function M:isDeployed() 47 | if self.state then 48 | return 1 49 | end 50 | return 0 51 | end 52 | 53 | --- Set the value of a signal in the specified IN plug of the element. 54 | -- 55 | -- Valid plug names are: 56 | --
    57 | --
  • "in" for the in signal (seems to have no actual effect when modified this way).
  • 58 | --
59 | -- @tparam string plug A valid plug name to set. 60 | -- @tparam 0/1 state The plug signal state 61 | function M:setSignalIn(plug, state) 62 | if plug == "in" then 63 | -- no longer responds to setSignalIn 64 | end 65 | end 66 | 67 | --- Return the value of a signal in the specified IN plug of the element. 68 | -- 69 | -- Valid plug names are: 70 | --
    71 | --
  • "in" for the in signal.
  • 72 | --
73 | -- @tparam string plug A valid plug name to query. 74 | -- @treturn 0/1 The plug signal state 75 | function M:getSignalIn(plug) 76 | if plug == "in" then 77 | return self.plugIn 78 | end 79 | return MockElement.getSignalIn(self) 80 | end 81 | 82 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 83 | -- @treturn table A table encompasing the api calls of object. 84 | -- @see Element:mockGetClosure 85 | function M:mockGetClosure() 86 | local closure = MockElementWithToggle.mockGetClosure(self) 87 | closure.deploy = function() return self:deploy() end 88 | closure.retract = function() return self:retract() end 89 | closure.isDeployed = function() return self:isDeployed() end 90 | 91 | closure.setSignalIn = function(plug, state) return self:setSignalIn(plug, state) end 92 | closure.getSignalIn = function(plug) return self:getSignalIn(plug) end return closure 93 | end 94 | 95 | return M -------------------------------------------------------------------------------- /src/game_data_lua/rslib.lua: -------------------------------------------------------------------------------- 1 | --- The renderscript library is defined by a Lua file within your Dual Universe installation, view it at: 2 | -- ...\Dual Universe\Game\data\lua\rslib.lua 3 | -- 4 | -- To use it, simply import it using: 5 | -- 6 | -- local rslib = require('rslib') 7 | -- 8 | -- then call methods as: 9 | -- 10 | -- rslib.drawQuickText("Hello World") 11 | -- 12 | -- @module game_data_lua.rslib 13 | 14 | local rslib = { version = "1.1" } 15 | 16 | --- Draw a full-screen image loaded from the given url. 17 | -- @tparam string url The url to load the image from. 18 | function rslib.drawQuickImage (url) 19 | end 20 | 21 | --- Draw a string of text with line breaks and word wrapping in the center of the screen. Options may contain any of 22 | -- the following: 23 | --
    24 | --
  • textColor (table) Four-component RGBA table; e.g. red 25 | -- is {1, 0, 0, 1}.
  • 26 | --
  • bgColor (table) Three-component RGB table for 27 | -- background color.
  • 28 | --
  • fontName (string) Name of font (see render script 29 | -- docs).
  • 30 | --
  • fontSize (int) Size of font, in vertical pixels.
  • 31 | --
  • lineSpacing (float) Spacing from one baseline to the 32 | -- next.
  • 33 | --
  • wrapWidth (float) Total width of the text region, as 34 | -- a fraction of screen width.
  • 35 | -- @tparam string text The text to display. 36 | -- @tparam table options The options to use. 37 | function rslib.drawQuickText (text, options) 38 | end 39 | 40 | --- Draw a small render cost profiler at the bottom-left of the screen to show the current render cost of the screen 41 | -- versus the maximum allowed cost. 42 | -- 43 | -- NOTE: displays render cost at the time of the function call, so you must call at the end of your script to see the 44 | -- total cost! 45 | function rslib.drawRenderCost () 46 | end 47 | 48 | --- Break the given text into a table of strings such that each element takes no more than maxWidth 49 | -- horizontal pixels when rendered with the given font. 50 | -- @tparam int font The id of the font to use. 51 | -- @tparam string text The text to split. 52 | -- @tparam float maxWidth The max number of horizontal pixels before the string is split onto another line. 53 | function rslib.getTextWrapped (font, text, maxWidth) 54 | end 55 | 56 | --- Draw a grid on the screen. 57 | -- @tparam float size The size of the grid square. 58 | -- @tparam float opacity The opacity of the grid lines [0..1]. 59 | function rslib.drawGrid (size, opacity) 60 | end 61 | 62 | --- Like Lua print, but uses @{renderScript.logMessage} to print to the in-game Lua chat window. 63 | -- 64 | -- NOTE: Only visible if 'enable logging' is on for this screen! 65 | -- @param ... The items to print. 66 | function rslib.print (...) 67 | end 68 | 69 | --- Pretty print, like @{print}, except using @{toString} to see tables. 70 | -- @param ... The items to print. 71 | function rslib.pprint (...) 72 | end 73 | 74 | --- Like Lua tostring, but recursively stringifies tables. 75 | -- @param x The item to print. 76 | function rslib.toString (x) 77 | end 78 | 79 | return rslib 80 | -------------------------------------------------------------------------------- /src/dumocks/TelemeterUnit.lua: -------------------------------------------------------------------------------- 1 | --- Measures the distance to an obstacle in front of it. 2 | -- 3 | -- Element class: TelemeterUnit 4 | -- 5 | -- Extends: @{Element} 6 | -- @module TelemeterUnit 7 | -- @alias M 8 | 9 | local MockElement = require "dumocks.Element" 10 | 11 | local elementDefinitions = {} 12 | elementDefinitions["telemeter xs"] = {mass = 40.79, maxHitPoints = 50.0, itemId = 1722901246} 13 | local DEFAULT_ELEMENT = "telemeter xs" 14 | 15 | local M = MockElement:new() 16 | M.elementClass = "TelemeterUnit" 17 | 18 | function M:new(o, id, elementName) 19 | local elementDefinition = MockElement.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 20 | 21 | o = o or MockElement:new(o, id, elementDefinition) 22 | setmetatable(o, self) 23 | self.__index = self 24 | 25 | o.distance = -1 26 | o.maxDistance = 100 -- m 27 | 28 | return o 29 | end 30 | 31 | --- Deprecated: Returns the distance to the first obstacle in front of the telemeter. 32 | -- 33 | -- This method is deprecated: raycast().distance should be used instead 34 | -- @see raycast 35 | -- @treturn meter The distance to the obstacle. Returns -1 if there are no obstacles up to getMaxDistance. 36 | function M:getDistance() 37 | M.deprecated("getDistance", "raycast().distance") 38 | return self:raycast().distance 39 | end 40 | 41 | --- Emits a raycast from the telemeter, returns a raycastHit object. 42 | -- @treturn table A table with fields: {[bool] hit, [float] distance, [vec3] point} 43 | function M:raycast() 44 | local distance = self.distance 45 | if distance > self.maxDistance or distance < 0 then 46 | distance = -1 47 | end 48 | return {hit = false, distance = distance, point = {0, 0, 0}} 49 | end 50 | 51 | --- Returns telemeter raycast origin in local construct coordinates. 52 | -- @treturn vec3 The telemeter raycast origin. 53 | function M:getRayOrigin() 54 | end 55 | 56 | --- Returns telemeter raycast origin in world coordinates. 57 | -- @treturn vec3 The telemeter raycast origin. 58 | function M:getRayWorldOrigin() 59 | end 60 | 61 | --- Returns telemeter raycast axis in local construct coordinates. 62 | -- @treturn vec3 The telemeter raycast axis. 63 | function M:getRayAxis() 64 | end 65 | 66 | --- Returns telemeter raycast axis in world coordinates. 67 | -- @treturn vec3 The telemeter raycast axis. 68 | function M:getRayWorldAxis() 69 | end 70 | 71 | --- Returns the max distance from which an obstacle can be detected (default is 100m). 72 | -- @treturn float The max distance to detectable obstacles in meters. 73 | function M:getMaxDistance() 74 | return self.maxDistance 75 | end 76 | 77 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 78 | -- @treturn table A table encompasing the api calls of object. 79 | -- @see Element:mockGetClosure 80 | function M:mockGetClosure() 81 | local closure = MockElement.mockGetClosure(self) 82 | closure.getDistance = function() return self:getDistance() end 83 | closure.raycast = function() return self:raycast() end 84 | closure.getRayOrigin = function() return self:getRayOrigin() end 85 | closure.getRayWorldOrigin = function() return self:getRayWorldOrigin() end 86 | closure.getRayAxis = function() return self:getRayAxis() end 87 | closure.getRayWorldAxis = function() return self:getRayWorldAxis() end 88 | closure.getMaxDistance = function() return self:getMaxDistance() end 89 | return closure 90 | end 91 | 92 | return M -------------------------------------------------------------------------------- /src/dumocks/SurfaceEngineUnit.lua: -------------------------------------------------------------------------------- 1 | --- Surface engines require a surface to push off from. They support movement of ships across the ground or other 2 | -- surfaces. Hover engines require an atmosphere to function, while vertical boosters provide more thrust and can 3 | -- operate in space but consume space fuel. 4 | -- 5 | -- Element class: 6 | --
      7 | --
    • HoverEngineSmallGroup
    • 8 | --
    • HoverEngineMediumGroup
    • 9 | --
    • HoverEngineLargeGroup
    • 10 | --
    • AtmosphericVerticalBoosterXtraSmallGroup
    • 11 | --
    • AtmosphericVerticalBoosterSmallGroup
    • 12 | --
    • AtmosphericVerticalBoosterMediumGroup
    • 13 | --
    • AtmosphericVerticalBoosterLargeGroup
    • 14 | --
    15 | -- 16 | -- Extends: @{Element} > @{Engine} > @{FueledEngine} 17 | -- @module SurfaceEngineUnit 18 | -- @alias M 19 | 20 | local MockElement = require "dumocks.Element" 21 | local MockFueledEngine = require "dumocks.FueledEngine" 22 | 23 | local CLASS_HOVER_S = "HoverEngineSmallGroup" 24 | local CLASS_HOVER_M = "HoverEngineMediumGroup" 25 | local CLASS_HOVER_L = "HoverEngineLargeGroup" 26 | local CLASS_VERTICAL_XS = "AtmosphericVerticalBoosterXtraSmallGroup" 27 | local CLASS_VERTICAL_S = "AtmosphericVerticalBoosterSmallGroup" 28 | local CLASS_VERTICAL_M = "AtmosphericVerticalBoosterMediumGroup" 29 | local CLASS_VERTICAL_L = "AtmosphericVerticalBoosterLargeGroup" 30 | 31 | local elementDefinitions = {} 32 | elementDefinitions["basic hover engine s"] = {mass = 56.91, maxHitPoints = 50.0, itemId = 2333052331, class = CLASS_HOVER_S, maxThrust = 50000.0, maxDistance = 30.0} 33 | elementDefinitions["basic vertical booster xs"] = {mass = 22.7, maxHitPoints = 50.0, itemId = 3775402879, class = CLASS_VERTICAL_XS, maxThrust = 15000.0, maxDistance = 30} 34 | local DEFAULT_ELEMENT = "basic hover engine s" 35 | 36 | local M = MockFueledEngine:new() 37 | 38 | function M:new(o, id, elementName) 39 | local elementDefinition = MockElement.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 40 | 41 | o = o or MockFueledEngine:new(o, id, elementDefinition) 42 | setmetatable(o, self) 43 | self.__index = self 44 | 45 | o.elementClass = elementDefinition.class 46 | 47 | o.maxThrustBase = elementDefinition.maxThrust 48 | o.currentMaxThrust = o.maxThrustBase 49 | o.currentMinThrust = 0 50 | 51 | o.maxDistance = elementDefinition.maxDistance or 0 52 | o.distance = -1 53 | 54 | return o 55 | end 56 | 57 | --- Returns the distance to the first object detected in the direction of the thrust. 58 | -- @treturn float The distance to the first obstacle in meters or -1 if nothing closer than max distance. 59 | function M:getDistance() 60 | if self.distance > self.maxDistance or self.distance < 0 then 61 | return -1 62 | end 63 | return self.distance 64 | end 65 | 66 | --- Returns the maximum functional distance from the ground. 67 | -- @treturn float The maximum functional distance in meters. 68 | function M:getMaxDistance() 69 | return self.maxDistance 70 | end 71 | 72 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 73 | -- @treturn table A table encompasing the api calls of object. 74 | -- @see Element:mockGetClosure 75 | function M:mockGetClosure() 76 | local closure = MockFueledEngine.mockGetClosure(self) 77 | closure.getDistance = function() return self:getDistance() end 78 | closure.getMaxDistance = function() return self:getMaxDistance() end 79 | return closure 80 | end 81 | 82 | return M -------------------------------------------------------------------------------- /test/dumocks/AbstractTestElementWithToggle.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.ElementWithToggle. 3 | -- @see dumocks.ElementWithToggle 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | local utilities = require("test.Utilities") 10 | local AbstractTestElementWithState = require("test.dumocks.AbstractTestElementWithState") 11 | 12 | local AbstractTestElementWithToggle = AbstractTestElementWithState 13 | 14 | --- Factory to produce the non-deprecated activate function for the element. 15 | -- @tparam table closure The closure to extract the function from. 16 | -- @treturn function The correct activate function. 17 | function AbstractTestElementWithToggle.getActivateFunction(closure) 18 | lu.fail("getActivateFunction must be overridden to test activate functionality.") 19 | end 20 | 21 | --- Factory to produce the non-deprecated deactivate function for the element. 22 | -- @tparam table closure The closure to extract the function from. 23 | -- @treturn function The correct deactivate function. 24 | function AbstractTestElementWithToggle.getDeactivateFunction(closure) 25 | lu.fail("getDeactivateFunction must be overridden to test deactivate functionality.") 26 | end 27 | 28 | --- Verify that activate leaves the element on. 29 | function AbstractTestElementWithToggle.testActivate() 30 | local mock = AbstractTestElementWithToggle.getTestElement() 31 | local closure = mock:mockGetClosure() 32 | local activateOverride = AbstractTestElementWithToggle.getActivateFunction(closure) 33 | 34 | mock.state = false 35 | activateOverride() 36 | lu.assertTrue(mock.state) 37 | 38 | if activateOverride ~= closure.activate then 39 | mock.state = false 40 | utilities.verifyDeprecated("activate", closure.activate) 41 | lu.assertTrue(mock.state) 42 | end 43 | 44 | mock.state = true 45 | activateOverride() 46 | lu.assertTrue(mock.state) 47 | 48 | if activateOverride ~= closure.activate then 49 | mock.state = true 50 | utilities.verifyDeprecated("activate", closure.activate) 51 | lu.assertTrue(mock.state) 52 | end 53 | end 54 | 55 | --- Verify that deactivate leaves the element off. 56 | function AbstractTestElementWithToggle.testDeactivate() 57 | local mock = AbstractTestElementWithToggle.getTestElement() 58 | local closure = mock:mockGetClosure() 59 | local deactivateOverride = AbstractTestElementWithToggle.getDeactivateFunction(closure) 60 | 61 | mock.state = false 62 | deactivateOverride() 63 | lu.assertFalse(mock.state) 64 | 65 | if deactivateOverride ~= closure.deactivate then 66 | mock.state = false 67 | utilities.verifyDeprecated("deactivate", closure.deactivate) 68 | lu.assertFalse(mock.state) 69 | end 70 | 71 | mock.state = true 72 | deactivateOverride() 73 | lu.assertFalse(mock.state) 74 | 75 | if deactivateOverride ~= closure.deactivate then 76 | mock.state = true 77 | utilities.verifyDeprecated("deactivate", closure.deactivate) 78 | lu.assertFalse(mock.state) 79 | end 80 | end 81 | 82 | --- Verify that toggle changes the state. 83 | function AbstractTestElementWithToggle.testToggle() 84 | local mock = AbstractTestElementWithToggle.getTestElement() 85 | local closure = mock:mockGetClosure() 86 | 87 | mock.state = false 88 | closure.toggle() 89 | lu.assertTrue(mock.state) 90 | 91 | mock.state = true 92 | closure.toggle() 93 | lu.assertFalse(mock.state) 94 | end 95 | 96 | return AbstractTestElementWithToggle 97 | -------------------------------------------------------------------------------- /test/dumocks/TestSystem.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.System. 3 | -- @see dumocks.System 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local ms = require("dumocks.System") 11 | require("test.Utilities") 12 | 13 | _G.TestSystem = {} 14 | 15 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 16 | -- in-game. 17 | -- 18 | -- Test setup: 19 | -- 1. 1x Programming Board, no connections 20 | -- 21 | -- Exercises: getScreenHeight, getScreenWidth, getFov, getLocale 22 | function _G.TestSystem.testGameBehavior() 23 | local mock = ms:new() 24 | local system = mock:mockGetClosure() 25 | 26 | -- override to prevent console output 27 | system.print = function(_) 28 | end 29 | 30 | -- stub this in directly to supress print in the unit test 31 | local unit = {} 32 | unit.exit = function() 33 | end 34 | 35 | --------------- 36 | -- copy from here to unit.onStart() 37 | --------------- 38 | -- verify expected functions 39 | local expectedFunctions = {"getActionKeyName", "showScreen", "setScreen", "createWidgetPanel", "destroyWidgetPanel", 40 | "createWidget", "destroyWidget", "createData", "destroyData", "updateData", 41 | "addDataToWidget", "removeDataFromWidget", "getMouseWheel", "getMouseDeltaX", 42 | "getMouseDeltaY", "getMousePosX", "getMousePosY", "getThrottleInputFromMouseWheel", 43 | "getControlDeviceForwardInput", "getControlDeviceYawInput", 44 | "getControlDeviceLeftRightInput", "lockView", "isViewLocked", "freeze", "isFrozen", 45 | "getTime", "getActionUpdateDeltaTime", "getPlayerName", "getPlayerWorldPos", "print", 46 | "getWaypointFromPlayerPos", "setWaypoint", "getFov", "getScreenWidth", "getScreenHeight", 47 | "load", "logInfo", "logWarning", "logError", "addMarker", "addMeasure", "showHelper", 48 | "__NQ_returnFromRunPlayerLUA", "getOrganizationTag", "getOrganizationName", 49 | "stopSound", "playSound", "getCameraRight", "getCameraWorldUp", "getCameraWorldForward", 50 | "isFirstPerson", "getCameraForward", "getCameraUp", "getCameraMode", 51 | "getCameraVerticalFov", "getCameraWorldRight", "getCameraHorizontalFov", 52 | "getCameraWorldPos", "getCameraPos", "getArkTime", "getUtcTime", "getUtcOffset", 53 | "getItem", "getMouseSensitivity", "getOrganization", "getLocale", "isPlayingSound", 54 | "clearWaypoint", "getRecipes", "getSchematic"} 55 | _G.Utilities.verifyExpectedFunctions(system, expectedFunctions) 56 | 57 | assert(system.getScreenHeight() > 0, "Screen height: " .. system.getScreenHeight()) 58 | assert(system.getScreenWidth() > 0, "Screen width: " .. system.getScreenWidth()) 59 | local fov = system.getCameraHorizontalFov() 60 | assert(fov >= 60 and fov <= 120, "Fov: " .. fov) 61 | local locales = {["en-US"] = true, ["fr-FR"] = true, ["de-DE"] = true} 62 | assert(locales[system.getLocale()], "Unexpected locale: " .. system.getLocale()) 63 | 64 | system.print("Success") 65 | unit.exit() 66 | --------------- 67 | -- copy to here to unit.onStart() 68 | --------------- 69 | end 70 | 71 | os.exit(lu.LuaUnit.run()) 72 | -------------------------------------------------------------------------------- /test/dumocks/TestPlayer.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.Player. 3 | -- @see dumocks.Player 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mp = require("dumocks.Player") 11 | require("test.Utilities") 12 | 13 | _G.TestPlayer = {} 14 | 15 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 16 | -- in-game. 17 | -- 18 | -- Test setup: 19 | -- 1. 1x Programming Board, no connections 20 | -- 21 | -- Exercises: getId, getMass, getNanopackVolume, getNanopackMaxVolume, isSeated, isSprinting, setHeadlightOn, 22 | -- isHeadlightOn, freeze, isFrozen, hasDRMAutorization 23 | function _G.TestPlayer.testGameBehavior() 24 | local mock = mp:new() 25 | local player = mock:mockGetClosure() 26 | 27 | -- stub this in directly to supress print in the unit test 28 | local unit = {} 29 | unit.exit = function() 30 | end 31 | local system = {} 32 | system.print = function(_) 33 | end 34 | 35 | --------------- 36 | -- copy from here to unit.onStart() 37 | --------------- 38 | -- verify expected functions 39 | local expectedFunctions = {"getName", "getId", "getMass", "getNanopackMass", "getNanopackVolume", 40 | "getNanopackMaxVolume", "getOrgIds", "getPosition", "getWorldPosition", 41 | "getHeadPosition", "getWorldHeadPosition", "getVelocity", "getWorldVelocity", 42 | "getAbsoluteVelocity", "getForward", "getRight", "getUp", "getWorldForward", 43 | "getWorldRight", "getWorldUp", "getPlanet", "getParent", "isSeated", "getSeatId", 44 | "isParentedTo", "isSprinting", "isJetpackOn", "isHeadlightOn", "setHeadlightOn", 45 | "freeze", "isFrozen", "hasDRMAutorization", "load"} 46 | _G.Utilities.verifyExpectedFunctions(player, expectedFunctions) 47 | 48 | assert(player.getId() > 0) 49 | assert(player.getMass() == 90.0, "Unexpected player mass: " .. player.getMass()) 50 | local nanopackMaxVolume = player.getNanopackMaxVolume() 51 | assert(nanopackMaxVolume >= 4000 and nanopackMaxVolume <= 6250, "Unexpected max nanopack volume: " .. nanopackMaxVolume) 52 | local nanopackVolume = player.getNanopackVolume() 53 | assert(nanopackVolume >= 0 and nanopackVolume <= nanopackMaxVolume) 54 | 55 | assert(player.isSeated() == 0) 56 | assert(player.isSprinting() == 0) 57 | --assert(player.isJetpackOn() == 0) returns 1 on planets? 58 | 59 | player.setHeadlightOn(false) 60 | assert(player.isHeadlightOn() == 0) 61 | player.setHeadlightOn(true) 62 | assert(player.isHeadlightOn() == 1) 63 | player.setHeadlightOn(false) 64 | assert(player.isHeadlightOn() == 0) 65 | player.setHeadlightOn(1) 66 | assert(player.isHeadlightOn() == 1) 67 | player.setHeadlightOn(0) 68 | assert(player.isHeadlightOn() == 0) 69 | 70 | -- reports state as expected but doesn't actually freeze player from a programming board? 71 | player.freeze(false) 72 | assert(player.isFrozen() == 0) 73 | player.freeze(true) 74 | assert(player.isFrozen() == 1) 75 | player.freeze(false) 76 | assert(player.isFrozen() == 0) 77 | player.freeze(1) 78 | assert(player.isFrozen() == 1) 79 | player.freeze(0) 80 | assert(player.isFrozen() == 0) 81 | 82 | assert(player.hasDRMAutorization() == 1) 83 | 84 | system.print("Success") 85 | unit.exit() 86 | --------------- 87 | -- copy to here to unit.onStart() 88 | --------------- 89 | end 90 | 91 | os.exit(lu.LuaUnit.run()) 92 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [ main, pts ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | luarocks: 11 | name: Test LuaRocks 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 16 | 17 | - uses: leafo/gh-actions-lua@35bcb06abec04ec87df82e08caa84d545348536e # v10.0.0 18 | 19 | - uses: leafo/gh-actions-luarocks@e65774a6386cb4f24e293dca7fc4ff89165b64c5 # v4.3.0 20 | 21 | - name: Setup 22 | run: | 23 | luarocks install --only-deps du-mocks-scm-0.rockspec 24 | 25 | - name: Verify LuaRocks config 26 | run: luarocks make 27 | 28 | ldoc: 29 | name: Test LDoc 30 | runs-on: ubuntu-latest 31 | 32 | steps: 33 | - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 34 | 35 | - uses: leafo/gh-actions-lua@35bcb06abec04ec87df82e08caa84d545348536e # v10.0.0 36 | 37 | - uses: leafo/gh-actions-luarocks@e65774a6386cb4f24e293dca7fc4ff89165b64c5 # v4.3.0 38 | 39 | - name: Setup 40 | run: | 41 | luarocks install --only-deps du-mocks-scm-0.rockspec 42 | luarocks install ldoc 43 | 44 | - name: Verify codex builds cleanly 45 | run: ldoc . --fatalwarnings 46 | 47 | - name: Verify PTS codex builds cleanly 48 | run: ldoc -c config-pts.ld . --fatalwarnings 49 | 50 | unit-test: 51 | name: Run Unit Tests 52 | runs-on: ubuntu-latest 53 | 54 | strategy: 55 | fail-fast: false 56 | matrix: 57 | # luaVersion: [ "5.3" ] 58 | luaVersion: [ "5.3", "5.4" ] 59 | 60 | steps: 61 | - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 62 | 63 | - uses: leafo/gh-actions-lua@35bcb06abec04ec87df82e08caa84d545348536e # v10.0.0 64 | with: 65 | luaVersion: ${{ matrix.luaVersion }} 66 | 67 | - uses: leafo/gh-actions-luarocks@e65774a6386cb4f24e293dca7fc4ff89165b64c5 # v4.3.0 68 | 69 | - name: Setup 70 | run: | 71 | luarocks install --only-deps du-mocks-scm-0.rockspec 72 | luarocks install luaunit 73 | luarocks install luacov 74 | luarocks install luafilesystem 75 | 76 | - name: Test 77 | run: ./test/runTests.sh -o junit 78 | 79 | - name: Publish Test Results 80 | uses: EnricoMi/publish-unit-test-result-action@82082dac68ad6a19d980f8ce817e108b9f496c2a # v2.17.1 81 | if: always() 82 | with: 83 | junit_files: "test/results/**/*.xml" 84 | 85 | - run: luacov 86 | 87 | - name: Upload to Codecov 88 | uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 89 | if: ${{ matrix.luaVersion == '5.3' }} 90 | 91 | - name: Export In-Game Tests 92 | run: ./test/exportAll.sh 93 | 94 | - name: Upload Test Artifacts 95 | uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 96 | if: ${{ matrix.luaVersion == '5.3' }} 97 | with: 98 | name: test_configs 99 | path: | 100 | test/configExports 101 | test/results/*.html 102 | 103 | - run: rm -f test/results/*.xml 104 | 105 | - name: Deploy Screen Renderer Output 106 | uses: JamesIves/github-pages-deploy-action@a96ffa23204731ec64e3e1316072197d98bfbaea # v4.6.6 107 | if: ${{ matrix.luaVersion == '5.3' && (github.event_name == 'push' && github.ref_name == 'main') }} 108 | with: 109 | branch: codex 110 | folder: test/results 111 | target-folder: test-results 112 | -------------------------------------------------------------------------------- /src/dumocks/ForceFieldUnit.lua: -------------------------------------------------------------------------------- 1 | --- A force field to create an uncrossable energy barrier. 2 | -- 3 | -- Element class: ForceFieldUnit 4 | -- 5 | -- Extends: @{Element} > @{ElementWithState} > @{ElementWithToggle} 6 | -- @module ForceFieldUnit 7 | -- @alias M 8 | 9 | local MockElement = require "dumocks.Element" 10 | local MockElementWithToggle = require "dumocks.ElementWithToggle" 11 | 12 | local elementDefinitions = {} 13 | elementDefinitions["force field xs"] = {mass = 110.62, maxHitPoints = 50.0, itemId = 3686074288} 14 | elementDefinitions["force field s"] = {mass = 110.62, maxHitPoints = 50.0, itemId = 3685998465} 15 | elementDefinitions["force field m"] = {mass = 110.62, maxHitPoints = 50.0, itemId = 3686006062} 16 | elementDefinitions["force field l"] = {mass = 110.62, maxHitPoints = 50.0, itemId = 3685982092} 17 | local DEFAULT_ELEMENT = "force field xs" 18 | 19 | local M = MockElementWithToggle:new() 20 | M.elementClass = "ForceFieldUnit" 21 | 22 | function M:new(o, id, elementName) 23 | local elementDefinition = MockElement.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 24 | 25 | o = o or MockElementWithToggle:new(o, id, elementDefinition) 26 | setmetatable(o, self) 27 | self.__index = self 28 | 29 | o.plugIn = 0.0 30 | 31 | return o 32 | end 33 | 34 | --- Deploys the forcefield. 35 | function M:deploy() 36 | self.state = true 37 | end 38 | 39 | --- Retracts the forcefield. 40 | function M:retract() 41 | self.state = false 42 | end 43 | 44 | --- Checks if the forcefield is deployed. 45 | -- @treturn 0/1 1 if the forcefield is deployed. 46 | function M:isDeployed() 47 | if self.state then 48 | return 1 49 | end 50 | return 0 51 | end 52 | 53 | --- Set the value of a signal in the specified IN plug of the element. 54 | -- 55 | -- Valid plug names are: 56 | --
      57 | --
    • "in" for the in signal (only appears to cause the element to refresh state to match actual input signal when it 58 | -- doesn't already).
    • 59 | --
    60 | -- @tparam string plug A valid plug name to set. 61 | -- @tparam 0/1 state The plug signal state 62 | function M:setSignalIn(plug, state) 63 | if plug == "in" then 64 | -- does not set signal but updates state to match it 65 | local value = tonumber(self.plugIn) 66 | if type(value) ~= "number" or value < 1.0 then 67 | self:retract() 68 | else 69 | self:deploy() 70 | end 71 | end 72 | end 73 | 74 | --- Return the value of a signal in the specified IN plug of the element. 75 | -- 76 | -- Valid plug names are: 77 | --
      78 | --
    • "in" for the in signal (seems to have no actual effect when modified this way).
    • 79 | --
    80 | -- @tparam string plug A valid plug name to query. 81 | -- @treturn 0/1 The plug signal state 82 | function M:getSignalIn(plug) 83 | if plug == "in" then 84 | return self.plugIn 85 | end 86 | return MockElement.getSignalIn(self) 87 | end 88 | 89 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 90 | -- @treturn table A table encompasing the api calls of object. 91 | -- @see Element:mockGetClosure 92 | function M:mockGetClosure() 93 | local closure = MockElementWithToggle.mockGetClosure(self) 94 | closure.deploy = function() return self:deploy() end 95 | closure.retract = function() return self:retract() end 96 | closure.isDeployed = function() return self:isDeployed() end 97 | 98 | closure.setSignalIn = function(plug, state) return self:setSignalIn(plug, state) end 99 | closure.getSignalIn = function(plug) return self:getSignalIn(plug) end 100 | return closure 101 | end 102 | 103 | return M -------------------------------------------------------------------------------- /src/dumocks/Library.lua: -------------------------------------------------------------------------------- 1 | --- Contains a list of useful math and helper methods that would be slow to implement in Lua, and which are given here 2 | -- as fast C++ implementation. 3 | -- @module library 4 | -- @alias M 5 | 6 | -- define class fields 7 | local M = {} 8 | 9 | function M:new(o) 10 | -- define default instance fields 11 | o = o or {} 12 | setmetatable(o, self) 13 | self.__index = self 14 | 15 | o.systemResolution3Index = 1 16 | o.systemResolution3Solutions = {} 17 | 18 | o.systemResolution2Index = 1 19 | o.systemResolution2Solutions = {} 20 | 21 | o.getPointOnScreenIndex = 1 22 | o.getPointOnScreenSolutions = {} 23 | 24 | return o 25 | end 26 | 27 | --- Solve the 3D linear system M*x=c0 where M is defined by its colum vectors c1,c2,c3. 28 | -- @tparam vec3 vec_c1 The first column of the matrix M. 29 | -- @tparam vec3 vec_c2 The second column of the matrix M. 30 | -- @tparam vec3 vec_c3 The third column of the matrix M. 31 | -- @tparam vec3 vec_c0 The target column of the matrix M. 32 | -- @treturn vec3 The vec3 solution of the above system. 33 | function M:systemResolution3(vec_c1, vec_c2, vec_c3, vec_c0) 34 | -- find the next solution in the provided sequence 35 | local result = self.systemResolution3Solutions[self.systemResolution3Index] 36 | if not result then 37 | error("Solution " .. self.systemResolution3Index .. " not loaded.") 38 | end 39 | 40 | self.systemResolution3Index = self.systemResolution3Index + 1 41 | return result 42 | end 43 | 44 | --- Solve the 2D linear system M*x=c0 where M is defined by its colum vectors c1,c2. 45 | -- @tparam vec3 vec_c1 The first column of the matrix M. 46 | -- @tparam vec3 vec_c2 The second column of the matrix M. 47 | -- @tparam vec3 vec_c0 The target column of the matrix M. 48 | -- @treturn vec2 The vec2 solution of the above system. 49 | function M:systemResolution2(vec_c1, vec_c2, vec_c0) 50 | -- find the next solution in the provided sequence and increment index 51 | local result = self.systemResolution2Solutions[self.systemResolution2Index] 52 | if not result then 53 | error("Solution " .. self.systemResolution2Index .. " not loaded.") 54 | end 55 | 56 | self.systemResolution2Index = self.systemResolution2Index + 1 57 | return result 58 | end 59 | 60 | --- Returns the position of the given point in world coordinates system, on the game screen. 61 | -- @tparam vec3 worldPos The world position of the point. 62 | -- @treturn vec3 The position in percentage (between 0 and 1) of the screen resolution as vec3 with {x, y, depth}. 63 | function M:getPointOnScreen(worldPos) 64 | -- find the next solution in the provided sequence and increment index 65 | local result = self.getPointOnScreenSolutions[self.getPointOnScreenIndex] 66 | if not result then 67 | error("Point " .. self.getPointOnScreenIndex .. " not loaded.") 68 | end 69 | 70 | self.getPointOnScreenIndex = self.getPointOnScreenIndex + 1 71 | return result 72 | end 73 | 74 | --- Unknown use. 75 | function M:load() 76 | end 77 | 78 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 79 | -- @treturn table A table encompasing the api calls of object. 80 | function M:mockGetClosure() 81 | local closure = {} 82 | closure.systemResolution3 = function(vec_c1, vec_c2, vec_c3, vec_c0) 83 | return self:systemResolution3(vec_c1, vec_c2, vec_c3, vec_c0) 84 | end 85 | closure.systemResolution2 = function(vec_c1, vec_c2, vec_c0) 86 | return self:systemResolution2(vec_c1, vec_c2, vec_c0) 87 | end 88 | closure.getPointOnScreen = function(worldPos) return self:getPointOnScreen(worldPos) end 89 | closure.load = function() return self:load() end 90 | return closure 91 | end 92 | 93 | return M 94 | -------------------------------------------------------------------------------- /du-mocks-scm-0.rockspec: -------------------------------------------------------------------------------- 1 | package = "du-mocks" 2 | version = "scm-0" 3 | source = { 4 | url = "git+https://github.com/1337joe/du-mocks.git", 5 | branch = "main", 6 | } 7 | description = { 8 | summary = "Mock objects to simulate the Dual Universe lua environment.", 9 | detailed = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline.", 10 | homepage = "https://github.com/1337joe/du-mocks", 11 | license = "MIT", 12 | } 13 | dependencies = { 14 | "lua >= 5.3", 15 | 16 | -- build/test dependencies 17 | "ldoc", 18 | "luaunit", 19 | "luacov", 20 | } 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["dumocks.AdjustorUnit"] = "src/dumocks/AdjustorUnit.lua", 25 | ["dumocks.AirfoilUnit"] = "src/dumocks/AirfoilUnit.lua", 26 | ["dumocks.AntiGravityGeneratorUnit"] = "src/dumocks/AntiGravityGeneratorUnit.lua", 27 | ["dumocks.BaseShieldGeneratorUnit"] = "src/dumocks/BaseShieldGeneratorUnit.lua", 28 | ["dumocks.BrakeUnit"] = "src/dumocks/BrakeUnit.lua", 29 | ["dumocks.Construct"] = "src/dumocks/Construct.lua", 30 | ["dumocks.ContainerUnit"] = "src/dumocks/ContainerUnit.lua", 31 | ["dumocks.ControlUnit"] = "src/dumocks/ControlUnit.lua", 32 | ["dumocks.CoreUnit"] = "src/dumocks/CoreUnit.lua", 33 | ["dumocks.CounterUnit"] = "src/dumocks/CounterUnit.lua", 34 | ["dumocks.DatabankUnit"] = "src/dumocks/DatabankUnit.lua", 35 | ["dumocks.DetectionZoneUnit"] = "src/dumocks/DetectionZoneUnit.lua", 36 | ["dumocks.DoorUnit"] = "src/dumocks/DoorUnit.lua", 37 | ["dumocks.Element"] = "src/dumocks/Element.lua", 38 | ["dumocks.ElementWithState"] = "src/dumocks/ElementWithState.lua", 39 | ["dumocks.ElementWithToggle"] = "src/dumocks/ElementWithToggle.lua", 40 | ["dumocks.EmitterUnit"] = "src/dumocks/EmitterUnit.lua", 41 | ["dumocks.Engine"] = "src/dumocks/Engine.lua", 42 | ["dumocks.EngineUnit"] = "src/dumocks/EngineUnit.lua", 43 | ["dumocks.FireworksUnit"] = "src/dumocks/FireworksUnit.lua", 44 | ["dumocks.ForceFieldUnit"] = "src/dumocks/ForceFieldUnit.lua", 45 | ["dumocks.FueledEngine"] = "src/dumocks/FueledEngine.lua", 46 | ["dumocks.GyroUnit"] = "src/dumocks/GyroUnit.lua", 47 | ["dumocks.IndustryUnit"] = "src/dumocks/IndustryUnit.lua", 48 | ["dumocks.LandingGearUnit"] = "src/dumocks/LandingGearUnit.lua", 49 | ["dumocks.LaserDetectorUnit"] = "src/dumocks/LaserDetectorUnit.lua", 50 | ["dumocks.LaserEmitterUnit"] = "src/dumocks/LaserEmitterUnit.lua", 51 | ["dumocks.Library"] = "src/dumocks/Library.lua", 52 | ["dumocks.LightUnit"] = "src/dumocks/LightUnit.lua", 53 | ["dumocks.ManualButtonUnit"] = "src/dumocks/ManualButtonUnit.lua", 54 | ["dumocks.ManualSwitchUnit"] = "src/dumocks/ManualSwitchUnit.lua", 55 | ["dumocks.MiningUnit"] = "src/dumocks/MiningUnit.lua", 56 | ["dumocks.PlasmaExtractorUnit"] = "src/dumocks/PlasmaExtractorUnit.lua", 57 | ["dumocks.Player"] = "src/dumocks/Player.lua", 58 | ["dumocks.PressureTileUnit"] = "src/dumocks/PressureTileUnit.lua", 59 | ["dumocks.RadarUnit"] = "src/dumocks/RadarUnit.lua", 60 | ["dumocks.ReceiverUnit"] = "src/dumocks/ReceiverUnit.lua", 61 | ["dumocks.RenderScript"] = "src/dumocks/RenderScript.lua", 62 | ["dumocks.ScreenUnit"] = "src/dumocks/ScreenUnit.lua", 63 | ["dumocks.ShieldGeneratorUnit"] = "src/dumocks/ShieldGeneratorUnit.lua", 64 | ["dumocks.SurfaceEngineUnit"] = "src/dumocks/SurfaceEngineUnit.lua", 65 | ["dumocks.System"] = "src/dumocks/System.lua", 66 | ["dumocks.TelemeterUnit"] = "src/dumocks/TelemeterUnit.lua", 67 | ["dumocks.TransponderUnit"] = "src/dumocks/TransponderUnit.lua", 68 | ["dumocks.WarpDriveUnit"] = "src/dumocks/WarpDriveUnit.lua", 69 | ["dumocks.WeaponUnit"] = "src/dumocks/WeaponUnit.lua", 70 | }, 71 | copy_directories = { 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /rockspecs/du-mocks-1.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "du-mocks" 2 | version = "1.0.0-1" 3 | source = { 4 | url = "git+https://github.com/1337joe/du-mocks.git", 5 | tag = "v1.0.0", 6 | } 7 | description = { 8 | summary = "Mock objects to simulate the Dual Universe lua environment.", 9 | detailed = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline.", 10 | homepage = "https://github.com/1337joe/du-mocks", 11 | license = "MIT", 12 | } 13 | dependencies = { 14 | "lua >= 5.3", 15 | 16 | -- build/test dependencies 17 | "ldoc", 18 | "luaunit", 19 | "luacov", 20 | } 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["dumocks.AdjustorUnit"] = "src/dumocks/AdjustorUnit.lua", 25 | ["dumocks.AirfoilUnit"] = "src/dumocks/AirfoilUnit.lua", 26 | ["dumocks.AntiGravityGeneratorUnit"] = "src/dumocks/AntiGravityGeneratorUnit.lua", 27 | ["dumocks.BaseShieldGeneratorUnit"] = "src/dumocks/BaseShieldGeneratorUnit.lua", 28 | ["dumocks.BrakeUnit"] = "src/dumocks/BrakeUnit.lua", 29 | ["dumocks.Construct"] = "src/dumocks/Construct.lua", 30 | ["dumocks.ContainerUnit"] = "src/dumocks/ContainerUnit.lua", 31 | ["dumocks.ControlUnit"] = "src/dumocks/ControlUnit.lua", 32 | ["dumocks.CoreUnit"] = "src/dumocks/CoreUnit.lua", 33 | ["dumocks.CounterUnit"] = "src/dumocks/CounterUnit.lua", 34 | ["dumocks.DatabankUnit"] = "src/dumocks/DatabankUnit.lua", 35 | ["dumocks.DetectionZoneUnit"] = "src/dumocks/DetectionZoneUnit.lua", 36 | ["dumocks.DoorUnit"] = "src/dumocks/DoorUnit.lua", 37 | ["dumocks.Element"] = "src/dumocks/Element.lua", 38 | ["dumocks.ElementWithState"] = "src/dumocks/ElementWithState.lua", 39 | ["dumocks.ElementWithToggle"] = "src/dumocks/ElementWithToggle.lua", 40 | ["dumocks.EmitterUnit"] = "src/dumocks/EmitterUnit.lua", 41 | ["dumocks.Engine"] = "src/dumocks/Engine.lua", 42 | ["dumocks.EngineUnit"] = "src/dumocks/EngineUnit.lua", 43 | ["dumocks.FireworksUnit"] = "src/dumocks/FireworksUnit.lua", 44 | ["dumocks.ForceFieldUnit"] = "src/dumocks/ForceFieldUnit.lua", 45 | ["dumocks.FueledEngine"] = "src/dumocks/FueledEngine.lua", 46 | ["dumocks.GyroUnit"] = "src/dumocks/GyroUnit.lua", 47 | ["dumocks.IndustryUnit"] = "src/dumocks/IndustryUnit.lua", 48 | ["dumocks.LandingGearUnit"] = "src/dumocks/LandingGearUnit.lua", 49 | ["dumocks.LaserDetectorUnit"] = "src/dumocks/LaserDetectorUnit.lua", 50 | ["dumocks.LaserEmitterUnit"] = "src/dumocks/LaserEmitterUnit.lua", 51 | ["dumocks.Library"] = "src/dumocks/Library.lua", 52 | ["dumocks.LightUnit"] = "src/dumocks/LightUnit.lua", 53 | ["dumocks.ManualButtonUnit"] = "src/dumocks/ManualButtonUnit.lua", 54 | ["dumocks.ManualSwitchUnit"] = "src/dumocks/ManualSwitchUnit.lua", 55 | ["dumocks.MiningUnit"] = "src/dumocks/MiningUnit.lua", 56 | ["dumocks.PlasmaExtractorUnit"] = "src/dumocks/PlasmaExtractorUnit.lua", 57 | ["dumocks.Player"] = "src/dumocks/Player.lua", 58 | ["dumocks.PressureTileUnit"] = "src/dumocks/PressureTileUnit.lua", 59 | ["dumocks.RadarUnit"] = "src/dumocks/RadarUnit.lua", 60 | ["dumocks.ReceiverUnit"] = "src/dumocks/ReceiverUnit.lua", 61 | ["dumocks.RenderScript"] = "src/dumocks/RenderScript.lua", 62 | ["dumocks.ScreenUnit"] = "src/dumocks/ScreenUnit.lua", 63 | ["dumocks.ShieldGeneratorUnit"] = "src/dumocks/ShieldGeneratorUnit.lua", 64 | ["dumocks.SurfaceEngineUnit"] = "src/dumocks/SurfaceEngineUnit.lua", 65 | ["dumocks.System"] = "src/dumocks/System.lua", 66 | ["dumocks.TelemeterUnit"] = "src/dumocks/TelemeterUnit.lua", 67 | ["dumocks.TransponderUnit"] = "src/dumocks/TransponderUnit.lua", 68 | ["dumocks.WarpDriveUnit"] = "src/dumocks/WarpDriveUnit.lua", 69 | ["dumocks.WeaponUnit"] = "src/dumocks/WeaponUnit.lua", 70 | }, 71 | copy_directories = { 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /rockspecs/du-mocks-1.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "du-mocks" 2 | version = "1.1.0-1" 3 | source = { 4 | url = "git+https://github.com/1337joe/du-mocks.git", 5 | tag = "v1.1.0", 6 | } 7 | description = { 8 | summary = "Mock objects to simulate the Dual Universe lua environment.", 9 | detailed = "Mock objects for generating a more useful codex and for use testing Dual Universe scripts offline.", 10 | homepage = "https://github.com/1337joe/du-mocks", 11 | license = "MIT", 12 | } 13 | dependencies = { 14 | "lua >= 5.3", 15 | 16 | -- build/test dependencies 17 | "ldoc", 18 | "luaunit", 19 | "luacov", 20 | } 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["dumocks.AdjustorUnit"] = "src/dumocks/AdjustorUnit.lua", 25 | ["dumocks.AirfoilUnit"] = "src/dumocks/AirfoilUnit.lua", 26 | ["dumocks.AntiGravityGeneratorUnit"] = "src/dumocks/AntiGravityGeneratorUnit.lua", 27 | ["dumocks.BaseShieldGeneratorUnit"] = "src/dumocks/BaseShieldGeneratorUnit.lua", 28 | ["dumocks.BrakeUnit"] = "src/dumocks/BrakeUnit.lua", 29 | ["dumocks.Construct"] = "src/dumocks/Construct.lua", 30 | ["dumocks.ContainerUnit"] = "src/dumocks/ContainerUnit.lua", 31 | ["dumocks.ControlUnit"] = "src/dumocks/ControlUnit.lua", 32 | ["dumocks.CoreUnit"] = "src/dumocks/CoreUnit.lua", 33 | ["dumocks.CounterUnit"] = "src/dumocks/CounterUnit.lua", 34 | ["dumocks.DatabankUnit"] = "src/dumocks/DatabankUnit.lua", 35 | ["dumocks.DetectionZoneUnit"] = "src/dumocks/DetectionZoneUnit.lua", 36 | ["dumocks.DoorUnit"] = "src/dumocks/DoorUnit.lua", 37 | ["dumocks.Element"] = "src/dumocks/Element.lua", 38 | ["dumocks.ElementWithState"] = "src/dumocks/ElementWithState.lua", 39 | ["dumocks.ElementWithToggle"] = "src/dumocks/ElementWithToggle.lua", 40 | ["dumocks.EmitterUnit"] = "src/dumocks/EmitterUnit.lua", 41 | ["dumocks.Engine"] = "src/dumocks/Engine.lua", 42 | ["dumocks.EngineUnit"] = "src/dumocks/EngineUnit.lua", 43 | ["dumocks.FireworksUnit"] = "src/dumocks/FireworksUnit.lua", 44 | ["dumocks.ForceFieldUnit"] = "src/dumocks/ForceFieldUnit.lua", 45 | ["dumocks.FueledEngine"] = "src/dumocks/FueledEngine.lua", 46 | ["dumocks.GyroUnit"] = "src/dumocks/GyroUnit.lua", 47 | ["dumocks.IndustryUnit"] = "src/dumocks/IndustryUnit.lua", 48 | ["dumocks.LandingGearUnit"] = "src/dumocks/LandingGearUnit.lua", 49 | ["dumocks.LaserDetectorUnit"] = "src/dumocks/LaserDetectorUnit.lua", 50 | ["dumocks.LaserEmitterUnit"] = "src/dumocks/LaserEmitterUnit.lua", 51 | ["dumocks.Library"] = "src/dumocks/Library.lua", 52 | ["dumocks.LightUnit"] = "src/dumocks/LightUnit.lua", 53 | ["dumocks.ManualButtonUnit"] = "src/dumocks/ManualButtonUnit.lua", 54 | ["dumocks.ManualSwitchUnit"] = "src/dumocks/ManualSwitchUnit.lua", 55 | ["dumocks.MiningUnit"] = "src/dumocks/MiningUnit.lua", 56 | ["dumocks.PlasmaExtractorUnit"] = "src/dumocks/PlasmaExtractorUnit.lua", 57 | ["dumocks.Player"] = "src/dumocks/Player.lua", 58 | ["dumocks.PressureTileUnit"] = "src/dumocks/PressureTileUnit.lua", 59 | ["dumocks.RadarUnit"] = "src/dumocks/RadarUnit.lua", 60 | ["dumocks.ReceiverUnit"] = "src/dumocks/ReceiverUnit.lua", 61 | ["dumocks.RenderScript"] = "src/dumocks/RenderScript.lua", 62 | ["dumocks.ScreenUnit"] = "src/dumocks/ScreenUnit.lua", 63 | ["dumocks.ShieldGeneratorUnit"] = "src/dumocks/ShieldGeneratorUnit.lua", 64 | ["dumocks.SurfaceEngineUnit"] = "src/dumocks/SurfaceEngineUnit.lua", 65 | ["dumocks.System"] = "src/dumocks/System.lua", 66 | ["dumocks.TelemeterUnit"] = "src/dumocks/TelemeterUnit.lua", 67 | ["dumocks.TransponderUnit"] = "src/dumocks/TransponderUnit.lua", 68 | ["dumocks.WarpDriveUnit"] = "src/dumocks/WarpDriveUnit.lua", 69 | ["dumocks.WeaponUnit"] = "src/dumocks/WeaponUnit.lua", 70 | }, 71 | copy_directories = { 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /test/dumocks/TestConstruct.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.Construct. 3 | -- @see dumocks.Construct 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mc = require("dumocks.Construct") 11 | require("test.Utilities") 12 | 13 | _G.TestConstruct = {} 14 | 15 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 16 | -- in-game. 17 | -- 18 | -- Test setup: 19 | -- 1. 1x Programming Board, no connections 20 | -- 21 | -- Exercises: getPvPTimer, getForward, getRight, getUp 22 | function _G.TestConstruct.testGameBehavior() 23 | local mock = mc:new() 24 | local construct = mock:mockGetClosure() 25 | 26 | -- stub this in directly to supress print in the unit test 27 | local unit = {} 28 | unit.exit = function() 29 | end 30 | local system = {} 31 | system.print = function(_) 32 | end 33 | 34 | --------------- 35 | -- copy from here to unit.onStart() 36 | --------------- 37 | -- verify expected functions 38 | local expectedFunctions = {"getName", "getId", "getOwner", "getCreator", "isWarping", "getWarpState", "isInPvPZone", 39 | "getDistanceToSafeZone", "getPvPTimer", "getMass", "getInertialMass", 40 | "getInertialTensor", "getCenterOfMass", "getWorldCenterOfMass", "getCrossSection", 41 | "getSize", "getBoundingBoxSize", "getBoundingBoxCenter", "getMaxSpeed", 42 | "getMaxAngularSpeed", "getMaxSpeedPerAxis", "getMaxThrustAlongAxis", "getCurrentBrake", 43 | "getMaxBrake", "getWorldPosition", "getVelocity", "getWorldVelocity", 44 | "getAbsoluteVelocity", "getWorldAbsoluteVelocity", "getAcceleration", 45 | "getWorldAcceleration", "getAngularVelocity", "getWorldAngularVelocity", 46 | "getAngularAcceleration", "getWorldAngularAcceleration", 47 | "getWorldAirFrictionAcceleration", "getWorldAirFrictionAngularAcceleration", 48 | "getFrictionBurnSpeed", "getForward", "getRight", "getUp", "getWorldForward", 49 | "getWorldRight", "getWorldUp", "getOrientationUnitId", "getOrientationForward", 50 | "getOrientationRight", "getOrientationUp", "getWorldOrientationForward", 51 | "getWorldOrientationRight", "getWorldOrientationUp", "getParent", "getClosestParent", 52 | "getCloseParents", "getParentPosition", "getParentWorldPosition", "getParentForward", 53 | "getParentRight", "getParentUp", "getParentWorldForward", "getParentWorldRight", 54 | "getParentWorldUp", "getPlayersOnBoard", "getPlayersOnBoardInVRStation", 55 | "isPlayerBoarded", "isPlayerBoardedInVRStation", "getBoardedPlayerMass", 56 | "getBoardedInVRStationAvatarMass", "getDockedConstructs", "isConstructDocked", 57 | "getDockedConstructMass", "setDockingMode", "getDockingMode", "dock", "undock", 58 | "forceDeboard", "forceUndock", "forceInterruptVRSession", "load"} 59 | _G.Utilities.verifyExpectedFunctions(construct, expectedFunctions) 60 | 61 | assert(construct.getPvPTimer() == 0.0) 62 | 63 | assert(_G.Utilities.assertTableEquals(construct.getForward(), {0, 1, 0})) 64 | assert(_G.Utilities.assertTableEquals(construct.getRight(), {1, 0, 0})) 65 | assert(_G.Utilities.assertTableEquals(construct.getUp(), {0, 0, 1})) 66 | 67 | system.print("Success") 68 | unit.exit() 69 | --------------- 70 | -- copy to here to unit.onStart() 71 | --------------- 72 | end 73 | 74 | os.exit(lu.LuaUnit.run()) 75 | -------------------------------------------------------------------------------- /src/dumocks/DoorUnit.lua: -------------------------------------------------------------------------------- 1 | --- A door that can be opened or closed. 2 | -- 3 | -- Applies to doors, hatches, gates, etc. 4 | -- 5 | -- Element class: DoorUnit 6 | -- 7 | -- Extends: @{Element} > @{ElementWithState} > @{ElementWithToggle} 8 | -- @module DoorUnit 9 | -- @alias M 10 | 11 | local MockElement = require "dumocks.Element" 12 | local MockElementWithToggle = require "dumocks.ElementWithToggle" 13 | 14 | local elementDefinitions = {} 15 | elementDefinitions["airlock"] = {mass = 4197.11, maxHitPoints = 663.0} 16 | elementDefinitions["fuel intake xs"] = {mass = 4.12, maxHitPoints = 50.0, itemId = 764397251} 17 | elementDefinitions["gate xs"] = {mass = 122752.84, maxHitPoints = 50029.0, itemId = 1097676949} 18 | elementDefinitions["expanded gate s"] = {mass = 122752.84, maxHitPoints = 74872.0, itemId = 581667413} 19 | elementDefinitions["gate m"] = {mass = 122752.84, maxHitPoints = 150117.0, itemId = 2858887382} 20 | elementDefinitions["expanded gate l"] = {mass = 122752.84, maxHitPoints = 199892.0, itemId = 1289884535} 21 | elementDefinitions["gate xl"] = {mass = 122752.84, maxHitPoints = 448208.0, itemId = 1256519882} 22 | elementDefinitions["hatch s"] = {mass = 98.56, maxHitPoints = 969.0, itemId = 297147615} 23 | elementDefinitions["interior door"] = {mass = 4197.11, maxHitPoints = 560.0, itemId = 3709017308} 24 | elementDefinitions["reinforced sliding door"] = {mass = 4197.11, maxHitPoints = 969.0} 25 | elementDefinitions["sliding door s"] = {mass = 749.15, maxHitPoints = 56.0, itemId = 201196316} 26 | elementDefinitions["sliding door m"] = {mass = 1006.01, maxHitPoints = 450.0, itemId = 741980535} 27 | local DEFAULT_ELEMENT = "sliding door s" 28 | 29 | local M = MockElementWithToggle:new() 30 | M.elementClass = "DoorUnit" 31 | 32 | function M:new(o, id, elementName) 33 | local elementDefinition = MockElement.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 34 | 35 | o = o or MockElementWithToggle:new(o, id, elementDefinition) 36 | setmetatable(o, self) 37 | self.__index = self 38 | 39 | o.plugIn = 0.0 40 | 41 | return o 42 | end 43 | 44 | --- Open the door. 45 | function M:open() 46 | self.state = true 47 | end 48 | 49 | --- Close the door. 50 | function M:close() 51 | self.state = false 52 | end 53 | 54 | --- Returns the opening status of the door. 55 | -- @treturn 0/1 1 if the door is open. 56 | function M:isOpen() 57 | if self.state then 58 | return 1 59 | end 60 | return 0 61 | end 62 | 63 | --- Set the value of a signal in the specified IN plug of the element. 64 | -- 65 | -- Valid plug names are: 66 | --
      67 | --
    • "in" for the in signal (seems to have no actual effect when modified this way).
    • 68 | --
    69 | -- @tparam string plug A valid plug name to set. 70 | -- @tparam 0/1 state The plug signal state 71 | function M:setSignalIn(plug, state) 72 | if plug == "in" then 73 | -- no longer responds to setSignalIn 74 | end 75 | end 76 | 77 | --- Return the value of a signal in the specified IN plug of the element. 78 | -- 79 | -- Valid plug names are: 80 | --
      81 | --
    • "in" for the in signal.
    • 82 | --
    83 | -- @tparam string plug A valid plug name to query. 84 | -- @treturn 0/1 The plug signal state 85 | function M:getSignalIn(plug) 86 | if plug == "in" then 87 | return self.plugIn 88 | end 89 | return MockElement.getSignalIn(self) 90 | end 91 | 92 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 93 | -- @treturn table A table encompasing the api calls of object. 94 | -- @see Element:mockGetClosure 95 | function M:mockGetClosure() 96 | local closure = MockElementWithToggle.mockGetClosure(self) 97 | closure.open = function() return self:open() end 98 | closure.close = function() return self:close() end 99 | closure.isOpen = function() return self:isOpen() end 100 | 101 | closure.setSignalIn = function(plug, state) return self:setSignalIn(plug, state) end 102 | closure.getSignalIn = function(plug) return self:getSignalIn(plug) end 103 | return closure 104 | end 105 | 106 | return M -------------------------------------------------------------------------------- /test/dumocks/TestElement.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.Element. 3 | -- @see Element 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local me = require("dumocks.Element") 11 | local utilities = require("test.Utilities") 12 | 13 | TestElement = {} 14 | 15 | --- Verify element definition helper method behaves properly. 16 | function TestElement.testFindElement() 17 | local expected, actual 18 | local elementDefinitions = {} 19 | elementDefinitions["container xs"] = {mass = 229.09, maxHitPoints = 124.0} 20 | elementDefinitions["container s"] = {mass = 1281.31,maxHitPoints = 999.0} 21 | elementDefinitions["container m"] = {mass = 7421.35,maxHitPoints = 7997.0} 22 | elementDefinitions["container l"] = {mass = 14842.7,maxHitPoints = 17316.0} 23 | local elementName 24 | local DEFAULT_ELEMENT = "container s" 25 | 26 | -- unset 27 | elementName = nil 28 | expected = {name = "container s", mass = 1281.31,maxHitPoints = 999.0} 29 | actual = me.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 30 | lu.assertEquals(actual, expected) 31 | 32 | -- invalid 33 | elementName = "invalid" 34 | expected = {name = "container s", mass = 1281.31,maxHitPoints = 999.0} 35 | actual = me.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 36 | lu.assertEquals(actual, expected) 37 | 38 | -- valid, not default 39 | elementName = "container xs" 40 | expected = {name = "container xs", mass = 229.09, maxHitPoints = 124.0} 41 | actual = me.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 42 | lu.assertEquals(actual, expected) 43 | 44 | -- valid, not default, capitalized 45 | elementName = "Container XS" 46 | expected = {name = "container xs", mass = 229.09, maxHitPoints = 124.0} 47 | actual = me.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 48 | lu.assertEquals(actual, expected) 49 | 50 | -- valid, default 51 | elementName = "container s" 52 | expected = {name = "container s", mass = 1281.31,maxHitPoints = 999.0} 53 | actual = me.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 54 | lu.assertEquals(actual, expected) 55 | 56 | -- default is nil 57 | elementName = nil 58 | expected = nil 59 | actual = me.findElement(elementDefinitions, elementName, nil) 60 | lu.assertEquals(actual, expected) 61 | 62 | -- elements map is empty 63 | elementName = nil 64 | expected = nil 65 | actual = me.findElement({}, elementName, DEFAULT_ELEMENT) 66 | lu.assertEquals(actual, expected) 67 | end 68 | 69 | --- Verify constructor passes ID through properly and that instances are independant. 70 | function TestElement.testGetLocalId() 71 | local element1 = me:new(nil, 1) 72 | local element2 = me:new(nil, 2) 73 | 74 | lu.assertEquals(element1:getLocalId(), 1) 75 | lu.assertEquals(element2:getLocalId(), 2) 76 | 77 | local closure1 = element1:mockGetClosure() 78 | local closure2 = element2:mockGetClosure() 79 | 80 | lu.assertEquals(closure1.getLocalId(), 1) 81 | lu.assertEquals(closure2.getLocalId(), 2) 82 | 83 | lu.assertEquals(utilities.verifyDeprecated("getId", closure1.getId), closure1.getLocalId()) 84 | lu.assertEquals(utilities.verifyDeprecated("getId", closure2.getId), closure2.getLocalId()) 85 | end 86 | 87 | --- Verify integrity math functions properly. 88 | function TestElement.testGetIntegrity() 89 | local expected, actual 90 | local element = me:new() 91 | local closure = element:mockGetClosure() 92 | element.maxHitPoints = 100 93 | 94 | element.hitPoints = 50 95 | expected = 50 96 | actual = closure.getIntegrity() 97 | lu.assertEquals(actual, expected) 98 | 99 | element.hitPoints = 30 100 | expected = 30 101 | actual = closure.getIntegrity() 102 | lu.assertEquals(actual, expected) 103 | 104 | element.hitPoints = 100 105 | expected = 100 106 | actual = closure.getIntegrity() 107 | lu.assertEquals(actual, expected) 108 | end 109 | 110 | os.exit(lu.LuaUnit.run()) -------------------------------------------------------------------------------- /test/dumocks/TestWeaponUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.WeaponUnit. 3 | -- @see dumocks.WeaponUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mwu = require("dumocks.WeaponUnit") 11 | require("test.Utilities") 12 | 13 | TestWeaponUnit = {} 14 | 15 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 16 | -- in-game. 17 | -- 18 | -- Test setup: 19 | -- 1. 1x Railgun XS, connected to Hovercraft Seat Controller on slot11 20 | -- 21 | -- Note: Must be run on a dynamic core. 22 | -- 23 | -- Exercises: getClass, getWidgetData 24 | function _G.TestWeaponUnit.testGameBehavior() 25 | local mock, closure 26 | local result, message 27 | for _, element in pairs({"railgun xs"}) do 28 | mock = mwu:new(nil, 1, element) 29 | closure = mock:mockGetClosure() 30 | 31 | result, message = pcall(_G.TestWeaponUnit.gameBehaviorHelper, mock, closure) 32 | if not result then 33 | lu.fail("Element: " .. element .. ", Error: " .. message) 34 | end 35 | end 36 | end 37 | 38 | --- Runs characterization tests on the provided element. 39 | function _G.TestWeaponUnit.gameBehaviorHelper(mock, slot11) 40 | -- stub this in directly to supress print in the unit test 41 | local unit = {} 42 | unit.exit = function() 43 | end 44 | local system = {} 45 | system.print = function(_) 46 | end 47 | 48 | --------------- 49 | -- copy from here to unit.onStart() 50 | --------------- 51 | -- verify expected functions 52 | local expectedFunctions = {"getReloadTime", "getUnloadTime", "getMaxDistance", "getTargetId", "getMaxAmmo", 53 | "getOptimalTracking", "getOperationalState", "getOptimalDistance", "getMagazineVolume", 54 | "isOperational", "isOutOfAmmo", "getContainerId", "getStatus", "getHitProbability", 55 | "getCycleTime", "getAmmoCount", "getAmmo", "getOptimalAimingCone", "getBaseDamage"} 56 | for _, v in pairs(_G.Utilities.elementFunctions) do 57 | table.insert(expectedFunctions, v) 58 | end 59 | _G.Utilities.verifyExpectedFunctions(slot11, expectedFunctions) 60 | 61 | -- test element class and inherited methods 62 | local class = slot11.getClass() 63 | assert(string.match(class, "Weapon.+"), "Unexpected class: " .. class) 64 | assert(string.match(string.lower(slot11.getName()), "railgun %w+ %[%d+%]"), slot11.getName()) 65 | local expectedIds = {[31327772] = true} 66 | assert(expectedIds[slot11.getItemId()], "Unexpected id: " .. slot11.getItemId()) 67 | 68 | local data = slot11.getWidgetData() 69 | local expectedFields = {"helperId", "name", "type", "fireCounter", "fireReady", "hitProbability", "hitResult", 70 | "operationalStatus", "outOfZone", "repeatedFire", "weaponStatus", "staticProperties", 71 | "cycleTime", "magazineVolume", "optimalAimingCone", "optimalDistance", "optimalTracking", 72 | "reloadTime", "size", "unloadTime", "targetConstruct", "elementId", "properties", 73 | "ammoMax", "ammoName", "ammoTypeId", "cycleAnimationRemainingTime", "fireBlocked", 74 | "ammoCount", "baseDamage", "constructId", "disableFire", "impactCounter", "maxDistance", 75 | "missCounter"} 76 | local expectedValues = {} 77 | local ignoreFields = {} 78 | expectedValues["helperId"] = '"weapon"' 79 | expectedValues["type"] = '"weapon"' 80 | expectedValues["size"] = '"xs"' 81 | _G.Utilities.verifyWidgetData(data, expectedFields, expectedValues, ignoreFields) 82 | 83 | assert(string.match(slot11.getWidgetDataId(), "e%d+"), "Expected dataId to match e%d pattern: " .. slot11.getWidgetDataId()) 84 | assert(slot11.getMaxHitPoints() >= 300) 85 | assert(slot11.getMass() == 232.0) 86 | _G.Utilities.verifyBasicElementFunctions(slot11, 3, "weapon") 87 | 88 | system.print("Success") 89 | --------------- 90 | -- copy to here to unit.onStart() 91 | --------------- 92 | end 93 | 94 | os.exit(lu.LuaUnit.run()) 95 | -------------------------------------------------------------------------------- /test/dumocks/TestBrakeUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.BrakeUnit. 3 | -- @see dumocks.BrakeUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mbu = require("dumocks.BrakeUnit") 11 | require("test.Utilities") 12 | 13 | TestBrakeUnit = {} 14 | 15 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 16 | -- in-game. 17 | -- 18 | -- Test setup: 19 | -- 1. brake of any size, connected to Programming Board on slot1 20 | -- 21 | -- Exercises: getClass, getWidgetData 22 | function _G.TestBrakeUnit.testGameBehavior() 23 | local mock, closure 24 | local result, message 25 | for _, element in pairs({"atmospheric airbrake s", "retro-rocket brake s"}) do 26 | mock = mbu:new(nil, 1, element) 27 | closure = mock:mockGetClosure() 28 | 29 | result, message = pcall(_G.TestBrakeUnit.gameBehaviorHelper, mock, closure) 30 | if not result then 31 | lu.fail("Element: " .. element .. ", Error: " .. message) 32 | end 33 | end 34 | end 35 | 36 | --- Runs characterization tests on the provided element. 37 | function _G.TestBrakeUnit.gameBehaviorHelper(mock, slot1) 38 | -- stub this in directly to supress print in the unit test 39 | local unit = {} 40 | unit.exit = function() 41 | end 42 | local system = {} 43 | system.print = function(_) 44 | end 45 | 46 | --------------- 47 | -- copy from here to unit.onStart() 48 | --------------- 49 | local expectedFunctions = {"activate", "deactivate", "isActive", "toggle", "setThrust", "getThrust", 50 | "getMaxThrust", "getCurrentMinThrust", "getCurrentMaxThrust", "getMaxThrustEfficiency", 51 | "getThrustAxis", "getWorldThrustAxis", 52 | "getObstructionFactor", "getTags", "setTags", "isIgnoringTags", 53 | "getMinThrust", 54 | "getSignalIn", "setSignalIn", "getState", "getT50", 55 | "getFuelRateEfficiency", "getDistance", "getFuelConsumption", "isOutOfFuel", 56 | "torqueAxis", "hasFunctionalFuelTank", "thrustAxis", "getCurrentFuelRate", 57 | "getMaxThrustBase"} 58 | for _, v in pairs(_G.Utilities.elementFunctions) do 59 | table.insert(expectedFunctions, v) 60 | end 61 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 62 | 63 | -- test element class and inherited methods 64 | local class = slot1.getClass() 65 | local expectedName, expectedIds 66 | if class == "Airbrake" then 67 | expectedName = "atmospheric airbrake" 68 | expectedIds = {[65048663] = true, [2198271703] = true, [104971834] = true} 69 | elseif class == "Spacebrake" then 70 | expectedName = "retro%-rocket brake" 71 | expectedIds = {[3039211660] = true, [3243532126] = true, [1452351552] = true} 72 | else 73 | assert(false, "Unexpected class: " .. class) 74 | end 75 | expectedName = expectedName .. " %w %[%d+%]" 76 | assert(string.match(string.lower(slot1.getName()), expectedName), slot1.getName()) 77 | assert(expectedIds[slot1.getItemId()], "Unexpected ID: " .. slot1.getItemId()) 78 | assert(slot1.getMaxHitPoints() >= 50.0) 79 | assert(slot1.getMass() >= 25.0) 80 | 81 | -- test inherited methods 82 | local data = slot1.getWidgetData() 83 | local expectedFields = {"helperId", "name", "type", "currentMaxThrust", "currentThrust", "maxThrustBase"} 84 | local expectedValues = {} 85 | expectedValues["type"] = '"engine_unit"' 86 | expectedValues["helperId"] = '"engine_unit"' 87 | _G.Utilities.verifyWidgetData(data, expectedFields, expectedValues) 88 | 89 | assert(slot1.getMaxHitPoints() >= 50.0) 90 | assert(slot1.getMass() > 7.0) 91 | _G.Utilities.verifyBasicElementFunctions(slot1, 3, "engine_unit") 92 | 93 | system.print("Success") 94 | unit.exit() 95 | --------------- 96 | -- copy to here to unit.onStart() 97 | --------------- 98 | end 99 | 100 | os.exit(lu.LuaUnit.run()) 101 | -------------------------------------------------------------------------------- /test/dumocks/TestMiningUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.MiningUnit. 3 | -- @see dumocks.MiningUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mmu = require("dumocks.MiningUnit") 11 | require("test.Utilities") 12 | 13 | _G.TestMiningUnit = {} 14 | 15 | --- Verify constructor arguments properly handled and independent between instances. 16 | function _G.TestMiningUnit.testConstructor() 17 | 18 | -- default element: 19 | -- ["basic mining unit s"] = {mass = 180.0, maxHitPoints = 2500.0, itemId = 1949562989} 20 | 21 | local miner0 = mmu:new() 22 | local miner1 = mmu:new(nil, 1, "Basic Mining Unit S") 23 | local miner2 = mmu:new(nil, 2, "invalid") 24 | local miner3 = mmu:new(nil, 3, "Basic Mining Unit L") 25 | 26 | local minerClosure0 = miner0:mockGetClosure() 27 | local minerClosure1 = miner1:mockGetClosure() 28 | local minerClosure2 = miner2:mockGetClosure() 29 | local minerClosure3 = miner3:mockGetClosure() 30 | 31 | lu.assertEquals(minerClosure0.getLocalId(), 0) 32 | lu.assertEquals(minerClosure1.getLocalId(), 1) 33 | lu.assertEquals(minerClosure2.getLocalId(), 2) 34 | lu.assertEquals(minerClosure3.getLocalId(), 3) 35 | 36 | -- prove default element is selected only where appropriate 37 | local defaultMass = 180.0 38 | lu.assertEquals(minerClosure0.getMass(), defaultMass) 39 | lu.assertEquals(minerClosure1.getMass(), defaultMass) 40 | lu.assertEquals(minerClosure2.getMass(), defaultMass) 41 | lu.assertNotEquals(minerClosure3.getMass(), defaultMass) 42 | 43 | local defaultId = 1949562989 44 | lu.assertEquals(minerClosure0.getItemId(), defaultId) 45 | lu.assertEquals(minerClosure1.getItemId(), defaultId) 46 | lu.assertEquals(minerClosure2.getItemId(), defaultId) 47 | lu.assertNotEquals(minerClosure3.getItemId(), defaultId) 48 | end 49 | 50 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 51 | -- in-game. 52 | -- 53 | -- Test setup: 54 | -- 1. 1x Basic Mining Unit S, connected to Programming Board on slot1 55 | -- 56 | -- Exercises: getClass 57 | function _G.TestMiningUnit.testGameBehavior() 58 | local mock = mmu:new(nil, 1, "basic mining unit s") 59 | local slot1 = mock:mockGetClosure() 60 | 61 | -- stub this in directly to supress print in the unit test 62 | local unit = {} 63 | unit.exit = function() 64 | end 65 | local system = {} 66 | system.print = function(_) 67 | end 68 | 69 | --------------- 70 | -- copy from here to unit.onStart() 71 | --------------- 72 | -- verify expected functions 73 | local expectedFunctions = {"getStatus", "getRemainingTime", "getActiveOre", "getOrePools", "getBaseRate", 74 | "getEfficiency", "getAdjacencyBonus", "getCalibrationRate", "getOptimalRate", 75 | "getProductionRate", "getLastExtractionPosition", "getLastExtractingPlayerId", 76 | "getLastExtractionTime", "getLastExtractedVolume", "getLastExtractedOre", "getState"} 77 | for _, v in pairs(_G.Utilities.elementFunctions) do 78 | table.insert(expectedFunctions, v) 79 | end 80 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 81 | 82 | -- test element class and inherited methods 83 | assert(slot1.getClass() == "MiningUnit") 84 | assert(string.match(string.lower(slot1.getName()), "%w+ mining unit %w %[%d+%]"), slot1.getName()) 85 | local expectedIds = {[1949562989] = true, [3204140760] = true, [3204140761] = true, [3204140766] = true, 86 | [3204140767] = true, [3204140764] = true} 87 | assert(expectedIds[slot1.getItemId()], "Unexpected id: " .. slot1.getItemId()) 88 | assert(slot1.getMaxHitPoints() == 2500.0) 89 | assert(slot1.getMass() == 180.0) 90 | _G.Utilities.verifyBasicElementFunctions(slot1, 3) 91 | 92 | -- assert(slot1.getAdjacencyBonus() <= 60.0) 93 | 94 | system.print("Success") 95 | unit.exit() 96 | --------------- 97 | -- copy to here to unit.onStart() 98 | --------------- 99 | end 100 | 101 | os.exit(lu.LuaUnit.run()) 102 | -------------------------------------------------------------------------------- /test/dumocks/TestEngineUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.EngineUnit. 3 | -- @see dumocks.EngineUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local meu = require("dumocks.EngineUnit") 11 | require("test.Utilities") 12 | 13 | TestEngineUnit = {} 14 | 15 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 16 | -- in-game. 17 | -- 18 | -- Test setup: 19 | -- 1. atmo, space, or rocket engine of any size, connected to Programming Board on slot1 20 | -- 21 | -- Exercises: getClass, getWidgetData 22 | function _G.TestEngineUnit.testGameBehavior() 23 | local mock, closure 24 | local result, message 25 | for _, element in pairs({"basic atmospheric engine xs", "basic space engine xs", "rocket engine s"}) do 26 | mock = meu:new(nil, 1, element) 27 | closure = mock:mockGetClosure() 28 | 29 | result, message = pcall(_G.TestEngineUnit.gameBehaviorHelper, mock, closure) 30 | if not result then 31 | lu.fail("Element: " .. element .. ", Error: " .. message) 32 | end 33 | end 34 | end 35 | 36 | --- Runs characterization tests on the provided element. 37 | function _G.TestEngineUnit.gameBehaviorHelper(mock, slot1) 38 | -- stub this in directly to supress print in the unit test 39 | local unit = {} 40 | unit.exit = function() 41 | end 42 | local system = {} 43 | system.print = function(_) 44 | end 45 | 46 | --------------- 47 | -- copy from here to unit.onStart() 48 | --------------- 49 | local expectedFunctions = {"isTorqueEnabled", "enableTorque", "getFuelId", "getFuelTankId", 50 | "getWarmupTime", "hasBrokenFuelTank", 51 | "activate", "deactivate", "isActive", "toggle", "setThrust", "getThrust", 52 | "getMaxThrust", "getCurrentMinThrust", "getCurrentMaxThrust", "getMaxThrustEfficiency", 53 | "getThrustAxis", "getTorqueAxis", "getWorldThrustAxis", "getWorldTorqueAxis", 54 | "getObstructionFactor", "getTags", "setTags", "isIgnoringTags", 55 | "getMinThrust", 56 | "getSignalIn", "setSignalIn", "getState", "getT50", 57 | "getFuelRateEfficiency", "getDistance", "getFuelConsumption", "isOutOfFuel", 58 | "torqueAxis", "hasFunctionalFuelTank", "thrustAxis", "getCurrentFuelRate", 59 | "getMaxThrustBase"} 60 | for _, v in pairs(_G.Utilities.elementFunctions) do 61 | table.insert(expectedFunctions, v) 62 | end 63 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 64 | 65 | -- test element class and inherited methods 66 | local class = slot1.getClass() 67 | local expectedName, expectedIds 68 | if string.match(class, "AtmosphericEngine%w+Group") then 69 | expectedName = "%w+ atmospheric engine" 70 | expectedIds = {[710193240] = true} 71 | elseif string.match(class, "SpaceEngine%w+Group") then 72 | expectedName = "%w+ space engine" 73 | expectedIds = {[2243775376] = true} 74 | elseif class == "RocketEngine" then 75 | expectedName = "rocket engine" 76 | expectedIds = {[2112772336] = true, [3623903713] = true, [359938916] = true} 77 | else 78 | assert(false, "Unexpected class: " .. class) 79 | end 80 | expectedName = expectedName .. " %w+ %[%d+%]" 81 | assert(string.match(string.lower(slot1.getName()), expectedName), slot1.getName()) 82 | assert(expectedIds[slot1.getItemId()], "Unexpected ID: " .. slot1.getItemId()) 83 | assert(slot1.getMaxHitPoints() >= 50.0) 84 | assert(slot1.getMass() >= 100.0) 85 | 86 | -- test inherited methods 87 | local data = slot1.getWidgetData() 88 | local expectedFields = {"helperId", "name", "type", "currentMaxThrust", "currentThrust", "maxThrustBase"} 89 | local expectedValues = {} 90 | expectedValues["type"] = '"engine_unit"' 91 | expectedValues["helperId"] = '"engine_unit"' 92 | _G.Utilities.verifyWidgetData(data, expectedFields, expectedValues) 93 | 94 | assert(slot1.getMaxHitPoints() >= 50.0) 95 | assert(slot1.getMass() > 7.0) 96 | _G.Utilities.verifyBasicElementFunctions(slot1, 3, "engine_unit") 97 | 98 | system.print("Success") 99 | unit.exit() 100 | --------------- 101 | -- copy to here to unit.onStart() 102 | --------------- 103 | end 104 | 105 | os.exit(lu.LuaUnit.run()) 106 | -------------------------------------------------------------------------------- /test/dumocks/TestAirfoilUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.AirfoilUnit. 3 | -- @see dumocks.AirfoilUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mau = require("dumocks.AirfoilUnit") 11 | require("test.Utilities") 12 | 13 | TestAirfoilUnit = {} 14 | 15 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 16 | -- in-game. 17 | -- 18 | -- Test setup: 19 | -- 1. airfoil of any size, connected to Programming Board on slot1 20 | -- 21 | -- Exercises: getClass, getWidgetData 22 | function _G.TestAirfoilUnit.testGameBehavior() 23 | local mock, closure 24 | local result, message 25 | for _, element in pairs({"wing xs", "compact aileron xs", "aileron xs", "stabilizer xs"}) do 26 | mock = mau:new(nil, 1, element) 27 | closure = mock:mockGetClosure() 28 | 29 | result, message = pcall(_G.TestAirfoilUnit.gameBehaviorHelper, mock, closure) 30 | if not result then 31 | lu.fail("Element: " .. element .. ", Error: " .. message) 32 | end 33 | end 34 | end 35 | 36 | --- Runs characterization tests on the provided element. 37 | function _G.TestAirfoilUnit.gameBehaviorHelper(mock, slot1) 38 | -- stub this in directly to supress print in the unit test 39 | local unit = {} 40 | unit.exit = function() 41 | end 42 | local system = {} 43 | system.print = function(_) 44 | end 45 | 46 | --------------- 47 | -- copy from here to unit.onStart() 48 | --------------- 49 | local expectedFunctions = {"getLift", "getMaxLift", "getDrag", "getDragRatio", "getCurrentMinLift", 50 | "getMaxLiftEfficiency", "getLiftAxis", "getTorqueAxis", "getWorldLiftAxis", 51 | "getWorldTorqueAxis", "isStalled", "getStallAngle", "getMinAngle", "getMaxAngle", 52 | "getCurrentMaxLift", 53 | "getObstructionFactor", "getTags", "setTags", "isIgnoringTags", 54 | "setThrust", "getThrust", "getMinThrust", "getMaxThrust", "getMaxThrustEfficiency", 55 | "getSignalIn", "setSignalIn", "activate", "deactivate", "toggle", "getState", "getT50", 56 | "getFuelRateEfficiency", "getDistance", "getFuelConsumption", "isOutOfFuel", 57 | "torqueAxis", "hasFunctionalFuelTank", "thrustAxis", "getCurrentFuelRate", 58 | "getMaxThrustBase"} 59 | for _, v in pairs(_G.Utilities.elementFunctions) do 60 | table.insert(expectedFunctions, v) 61 | end 62 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 63 | 64 | -- test element class and inherited methods 65 | local class = slot1.getClass() 66 | local expectedName, expectedIds 67 | if class == "Stabilizer" then 68 | expectedName = "stabilizer" 69 | expectedIds = {[1455311973] = true, [1234961120] = true, [3474622996] = true, [1090402453] = true} 70 | elseif class == "Aileron2" then 71 | expectedName = "aileron" 72 | expectedIds = {[2334843027] = true, [2292270972] = true, [1923840124] = true, [2737703104] = true, [4017253256] = true, [1856288931] = true} 73 | elseif class == "Wing2" then 74 | expectedName = "wing" 75 | expectedIds = {[1727614690] = true, [2532454166] = true, [404188468] = true, [4179758576] = true} 76 | else 77 | assert(false, "Unexpected class: " .. class) 78 | end 79 | expectedName = expectedName .. " %w+ %[%d+%]" 80 | assert(string.match(string.lower(slot1.getName()), expectedName), slot1.getName()) 81 | assert(expectedIds[slot1.getItemId()], "Unexpected ID: " .. slot1.getItemId()) 82 | assert(slot1.getMaxHitPoints() >= 50.0) 83 | assert(slot1.getMass() >= 25.0) 84 | 85 | -- test inherited methods 86 | local data = slot1.getWidgetData() 87 | local expectedFields = {"helperId", "name", "type", "currentMaxThrust", "currentThrust", "maxThrustBase"} 88 | local expectedValues = {} 89 | expectedValues["type"] = '"engine_unit"' 90 | expectedValues["helperId"] = '"engine_unit"' 91 | _G.Utilities.verifyWidgetData(data, expectedFields, expectedValues) 92 | 93 | assert(slot1.getMaxHitPoints() >= 50.0) 94 | assert(slot1.getMass() > 7.0) 95 | _G.Utilities.verifyBasicElementFunctions(slot1, 3, "engine_unit") 96 | 97 | system.print("Success") 98 | unit.exit() 99 | --------------- 100 | -- copy to here to unit.onStart() 101 | --------------- 102 | end 103 | 104 | os.exit(lu.LuaUnit.run()) 105 | -------------------------------------------------------------------------------- /test/dumocks/TestSurfaceEngineUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.SurfaceEngineUnit. 3 | -- @see dumocks.SurfaceEngineUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mseu = require("dumocks.SurfaceEngineUnit") 11 | require("test.Utilities") 12 | 13 | TestSurfaceEngineUnit = {} 14 | 15 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 16 | -- in-game. 17 | -- 18 | -- Test setup: 19 | -- 1. hover engine or vertical booster of any size, connected to Programming Board on slot1 20 | -- 21 | -- Exercises: getClass, getWidgetData 22 | function _G.TestSurfaceEngineUnit.testGameBehavior() 23 | local mock, closure 24 | local result, message 25 | for _, element in pairs({"basic hover engine s", "basic vertical booster xs"}) do 26 | mock = mseu:new(nil, 1, element) 27 | closure = mock:mockGetClosure() 28 | 29 | result, message = pcall(_G.TestSurfaceEngineUnit.gameBehaviorHelper, mock, closure) 30 | if not result then 31 | lu.fail("Element: " .. element .. ", Error: " .. message) 32 | end 33 | end 34 | end 35 | 36 | --- Runs characterization tests on the provided element. 37 | function _G.TestSurfaceEngineUnit.gameBehaviorHelper(mock, slot1) 38 | -- stub this in directly to supress print in the unit test 39 | local unit = {} 40 | unit.exit = function() 41 | end 42 | local system = {} 43 | system.print = function(_) 44 | end 45 | 46 | --------------- 47 | -- copy from here to unit.onStart() 48 | --------------- 49 | local expectedFunctions = {"isTorqueEnabled", "enableTorque", "getFuelId", "getFuelTankId", 50 | "getWarmupTime", "getMaxDistance", "hasBrokenFuelTank", 51 | "activate", "deactivate", "isActive", "toggle", "setThrust", "getThrust", 52 | "getMaxThrust", "getCurrentMinThrust", "getCurrentMaxThrust", "getMaxThrustEfficiency", 53 | "getThrustAxis", "getTorqueAxis", "getWorldThrustAxis", "getWorldTorqueAxis", 54 | "getObstructionFactor", "getTags", "setTags", "isIgnoringTags", 55 | "getMinThrust", 56 | "getSignalIn", "setSignalIn", "getState", "getT50", 57 | "getFuelRateEfficiency", "getDistance", "getFuelConsumption", "isOutOfFuel", 58 | "torqueAxis", "hasFunctionalFuelTank", "thrustAxis", "getCurrentFuelRate", 59 | "getMaxThrustBase"} 60 | for _, v in pairs(_G.Utilities.elementFunctions) do 61 | table.insert(expectedFunctions, v) 62 | end 63 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 64 | 65 | -- test element class and inherited methods 66 | local class = slot1.getClass() 67 | local expectedName, expectedIds 68 | if string.match(class, "HoverEngine%w+Group") then 69 | expectedName = "%w+ hover engine" 70 | expectedIds = {[2333052331] = true} 71 | elseif string.match(class, "AtmosphericVerticalBooster%w+Group") then 72 | expectedName = "%w+ vertical booster" 73 | expectedIds = {[3775402879] = true} 74 | else 75 | assert(false, "Unexpected class: " .. class) 76 | end 77 | expectedName = expectedName .. " %w+ %[%d+%]" 78 | assert(string.match(string.lower(slot1.getName()), expectedName), slot1.getName()) 79 | assert(expectedIds[slot1.getItemId()], "Unexpected ID: " .. slot1.getItemId()) 80 | assert(slot1.getMaxHitPoints() >= 50.0) 81 | assert(slot1.getMass() >= 22.7) 82 | 83 | -- test inherited methods 84 | local data = slot1.getWidgetData() 85 | local expectedFields = {"helperId", "name", "type", "currentMaxThrust", "currentThrust", "maxThrustBase"} 86 | local expectedValues = {} 87 | expectedValues["type"] = '"engine_unit"' 88 | expectedValues["helperId"] = '"engine_unit"' 89 | _G.Utilities.verifyWidgetData(data, expectedFields, expectedValues) 90 | 91 | assert(slot1.getMaxHitPoints() >= 50.0) 92 | assert(slot1.getMass() > 7.0) 93 | _G.Utilities.verifyBasicElementFunctions(slot1, 3, "engine_unit") 94 | 95 | local distance = slot1.getDistance() 96 | local maxDistance = slot1.getMaxDistance() 97 | assert(maxDistance >= 30, "Unexpectedly small maxDistance: " .. maxDistance) 98 | assert(distance <= maxDistance) 99 | 100 | system.print("Success") 101 | unit.exit() 102 | --------------- 103 | -- copy to here to unit.onStart() 104 | --------------- 105 | end 106 | 107 | os.exit(lu.LuaUnit.run()) 108 | -------------------------------------------------------------------------------- /src/dumocks/PlasmaExtractorUnit.lua: -------------------------------------------------------------------------------- 1 | --- Extracts a regular amount of plasma from the space surrounding an alien core. 2 | -- 3 | --

    Note: This is generated from patch notes and in-game codex and has not yet been tested 4 | -- against the actual element. Accuracy not guaranteed.

    5 | -- 6 | -- Element class: ??? 7 | -- 8 | -- Extends: @{Element} 9 | -- @module PlasmaExtractorUnit 10 | -- @alias M 11 | 12 | local MockElement = require "dumocks.Element" 13 | 14 | local elementDefinitions = {} 15 | elementDefinitions["relic plasma extractor l"] = {mass = 16500.0, itemId = 4024529716} 16 | local DEFAULT_ELEMENT = "relic plasma extractor l" 17 | 18 | local M = MockElement:new() 19 | M.elementClass = "???" 20 | 21 | function M:new(o, id, elementName) 22 | local elementDefinition = MockElement.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 23 | 24 | o = o or MockElement:new(o, id, elementDefinition) 25 | setmetatable(o, self) 26 | self.__index = self 27 | 28 | return o 29 | end 30 | 31 | -- Deprecated: Returns the current status of the plasma extractor. 32 | -- 33 | -- This method is deprecated: getState should be used instead 34 | -- @see getState 35 | -- @treturn string The status of the plasma extractor can be: "STOPPED", "RUNNING", "JAMMED_OUTPUT_FULL". 36 | function M:getStatus() 37 | M.deprecated("getStatus", "getState") 38 | return "STOPPED" 39 | end 40 | 41 | --- Returns the current state of the plasma extractor. 42 | -- @treturn int The state of the plasma extractor can be (Stopped = 1, Running = 2, Jammed output full = 3, Jammed no 43 | -- output container = 4) 44 | function M:getState() 45 | return 1 46 | end 47 | 48 | --- Returns the remaining time of the current batch extraction process. 49 | -- @treturn float The remaining time in seconds. 50 | function M:getRemainingTime() 51 | end 52 | 53 | --- Returns the list of available plasma pools. 54 | -- @treturn table A list of tables composed with {[int] oreId, [int] quantity}. 55 | function M:getPlasmaPools() 56 | end 57 | 58 | --- Event: Emitted when the plasma extractor started a new extraction process. 59 | -- 60 | -- Note: This is documentation on an event handler, not a callable method. 61 | function M:EVENT_onStarted() 62 | assert(false, "This is implemented for documentation purposes.") 63 | end 64 | 65 | -- Deprecated: Event: Emitted when the plasma extractor completes a batch. 66 | -- 67 | -- Note: This is documentation on an event handler, not a callable method. 68 | -- 69 | -- This event is deprecated: EVENT_onCompleted should be used instead. 70 | -- @see EVENT_onCompleted 71 | function M.EVENT_completed() 72 | M.deprecated("EVENT_completed", "EVENT_onCompleted") 73 | M.EVENT_onCompleted() 74 | end 75 | 76 | --- Event: Emitted when the plasma extractor completes a batch. 77 | -- 78 | -- Note: This is documentation on an event handler, not a callable method. 79 | function M.EVENT_onCompleted() 80 | assert(false, "This is implemented for documentation purposes.") 81 | end 82 | 83 | -- Deprecated: Event: Emitted when the plasma extractor status is changed. 84 | -- 85 | -- Note: This is documentation on an event handler, not a callable method. 86 | -- 87 | -- This event is deprecated: EVENT_onStateChanged should be used instead. 88 | -- @see EVENT_onStateChanged 89 | -- @tparam string status The new status of the plasma extractor, can be: "STOPPED", "RUNNING", "JAMMED_OUTPUT_FULL". 90 | function M.EVENT_statusChanged(status) 91 | M.deprecated("EVENT_statusChanged", "EVENT_onStateChanged") 92 | assert(false, "This is implemented for documentation purposes.") 93 | end 94 | 95 | --- Event: Emitted when the plasma extractor state is changed. 96 | -- 97 | -- Note: This is documentation on an event handler, not a callable method. 98 | -- @tparam int state The state of the plasma extractor can be (Stopped = 1, Running = 2, Jammed output full = 3, Jammed no 99 | -- output container = 4) 100 | function M.EVENT_onStateChanged(state) 101 | assert(false, "This is implemented for documentation purposes.") 102 | end 103 | 104 | --- Event: Emitted when the plasma extractor stopped the extraction process. 105 | -- 106 | -- Note: This is documentation on an event handler, not a callable method. 107 | function M:EVENT_onStopped() 108 | assert(false, "This is implemented for documentation purposes.") 109 | end 110 | 111 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 112 | -- @treturn table A table encompasing the api calls of object. 113 | -- @see Element:mockGetClosure 114 | function M:mockGetClosure() 115 | local closure = MockElement.mockGetClosure(self) 116 | closure.getState = function() return self:getState() end 117 | closure.getRemainingTime = function() return self:getRemainingTime() end 118 | closure.getPlasmaPools = function() return self:getPlasmaPools() end 119 | return closure 120 | end 121 | 122 | return M -------------------------------------------------------------------------------- /test/dumocks/TestRadarUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.RadarUnit. 3 | -- @see dumocks.RadarUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mru = require("dumocks.RadarUnit") 11 | require("test.Utilities") 12 | 13 | TestRadarUnit = {} 14 | 15 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 16 | -- in-game. 17 | -- 18 | -- Test setup: 19 | -- 1. 1x Radar S (atmo or space), connected to Programming Board on slot1 20 | -- 21 | -- Note: Must be run on a dynamic core. 22 | -- 23 | -- Exercises: getClass, getWidgetData 24 | function _G.TestRadarUnit.testGameBehavior() 25 | local mock, closure 26 | local result, message 27 | for _, element in pairs({"atmospheric radar s", "space radar s"}) do 28 | mock = mru:new(nil, 1, element) 29 | closure = mock:mockGetClosure() 30 | 31 | result, message = pcall(_G.TestRadarUnit.gameBehaviorHelper, mock, closure) 32 | if not result then 33 | lu.fail("Element: " .. element .. ", Error: " .. message) 34 | end 35 | end 36 | end 37 | 38 | --- Runs characterization tests on the provided element. 39 | function _G.TestRadarUnit.gameBehaviorHelper(mock, slot1) 40 | -- stub this in directly to supress print in the unit test 41 | local unit = {} 42 | unit.exit = function() 43 | end 44 | local system = {} 45 | system.print = function(_) 46 | end 47 | 48 | --------------- 49 | -- copy from here to unit.onStart() 50 | --------------- 51 | -- verify expected functions 52 | local expectedFunctions = {"getConstructSize", "getConstructType", "getConstructPos", 53 | "getConstructName", "getRange", "hasMatchingTransponder", "isConstructAbandoned", 54 | "isOperational", "isConstructIdentified", "getConstructIds", "getIdentifyRanges", 55 | "getConstructAngularSpeed", "getTargetId", "getConstructDistance", 56 | "getConstructCoreSize", "getConstructInfos", "getConstructRadialSpeed", 57 | "getConstructSpeed", "getIdentifiedConstructIds", "getConstructWorldVelocity", 58 | "getConstructVelocity", "getConstructOwner", "getConstructWorldPos", "getThreatFrom", 59 | "getThreatTo", "getConstructMass", "getConstructOwnerEntity", "setSortMethod", 60 | "getConstructKind", "getThreatRateTo", "getOperationalState", "getThreatRateFrom", 61 | "getSortMethod", "getConstructs"} 62 | for _, v in pairs(_G.Utilities.elementFunctions) do 63 | table.insert(expectedFunctions, v) 64 | end 65 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 66 | 67 | -- test element class and inherited methods 68 | local class = slot1.getClass() 69 | local expectedName, expectedIds 70 | local isAtmo, isSpace 71 | if string.match(class, "RadarPvPAtmospheric") then 72 | isAtmo = true 73 | expectedName = "atmospheric" 74 | expectedIds = {[4213791403] = true, [612626034] = true, [3094514782] = true} 75 | elseif string.match(class, "RadarPVPSpace") then 76 | isSpace = true 77 | expectedName = "space" 78 | expectedIds = {[4118496992] = true, [3831485995] = true, [2802863920] = true} 79 | else 80 | assert(false, "Unexpected class: " .. class) 81 | end 82 | expectedName = expectedName .. " radar %w+ %[%d+%]" 83 | assert(string.match(string.lower(slot1.getName()), expectedName), slot1.getName()) 84 | assert(expectedIds[slot1.getItemId()], "Unexpected ID: " .. slot1.getItemId()) 85 | 86 | local data = slot1.getWidgetData() 87 | local expectedFields = {"helperId", "name", "type", "constructsList", "elementId", "properties", "currentTargetId"} 88 | local expectedValues = {} 89 | local ignoreFields = {"errorMessage", "identifiedConstructs", "identifyConstructs", "radarStatus", 90 | "selectedConstruct", "worksInEnvironment", "staticProperties", "ranges", "identify16m", 91 | "identify32m", "identify64m", "identify128m", "scan", "worksInAtmosphere", "worksInSpace", 92 | "maxIdentifiedTargets", "broken", "sortMethod"} 93 | expectedValues["helperId"] = '"radar"' 94 | expectedValues["type"] = '"radar"' 95 | _G.Utilities.verifyWidgetData(data, expectedFields, expectedValues, ignoreFields) 96 | 97 | assert(slot1.getMaxHitPoints() >= 88) 98 | assert(slot1.getMass() == 486.72) 99 | _G.Utilities.verifyBasicElementFunctions(slot1, 3, "radar") 100 | 101 | system.print("Success") 102 | unit.exit() 103 | --------------- 104 | -- copy to here to unit.onStart() 105 | --------------- 106 | end 107 | 108 | os.exit(lu.LuaUnit.run()) 109 | -------------------------------------------------------------------------------- /src/dumocks/EmitterUnit.lua: -------------------------------------------------------------------------------- 1 | --- This unit is capable of emitting messages on channels. 2 | -- 3 | -- Element class: EmitterUnit 4 | -- 5 | -- Extends: @{Element} 6 | -- @module EmitterUnit 7 | -- @alias M 8 | 9 | local MockElement = require "dumocks.Element" 10 | 11 | local elementDefinitions = {} 12 | elementDefinitions["emitter xs"] = {mass = 69.31, maxHitPoints = 50.0, itemId = 1279651501} 13 | elementDefinitions["emitter s"] = {mass = 427.72, maxHitPoints = 133.0, itemId = 3287187256} 14 | elementDefinitions["emitter m"] = {mass = 2035.73, maxHitPoints = 13686.0, itemId = 2809213930} 15 | local DEFAULT_ELEMENT = "emitter xs" 16 | 17 | local M = MockElement:new() 18 | M.elementClass = "EmitterUnit" 19 | 20 | function M:new(o, id, elementName) 21 | local elementDefinition = MockElement.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 22 | 23 | o = o or MockElement:new(o, id, elementDefinition) 24 | setmetatable(o, self) 25 | self.__index = self 26 | 27 | o.defaultChannel = "" 28 | o.range = 1000 -- meters 29 | o.propagateSendErrors = false -- in-game module gets no feedback, make optional for testing purposes 30 | o.receiverCallbacks = {} 31 | 32 | o.plugIn = 0.0 33 | 34 | return o 35 | end 36 | 37 | --- Set the value of a signal in the specified IN plug of the element. 38 | -- 39 | -- Valid plug names are: 40 | --
      41 | --
    • "in" for the in signal (seems to have no actual effect when modified this way).
    • 42 | --
    43 | -- @tparam string plug A valid plug name to set. 44 | -- @tparam 0/1 state The plug signal state 45 | function M:setSignalIn(plug, state) 46 | if plug == "in" then 47 | -- no longer responds to setSignalIn 48 | end 49 | end 50 | 51 | --- Return the value of a signal in the specified IN plug of the element. 52 | -- 53 | -- Valid plug names are: 54 | --
      55 | --
    • "in" for the in signal.
    • 56 | --
    57 | -- @tparam string plug A valid plug name to query. 58 | -- @treturn 0/1 The plug signal state 59 | function M:getSignalIn(plug) 60 | if plug == "in" then 61 | return self.plugIn 62 | end 63 | return MockElement.getSignalIn(self) 64 | end 65 | 66 | local function trimString(inpString) 67 | return string.sub(inpString, 0, 512) 68 | end 69 | 70 | --- Send a message on the given channel. Note that only the last message is guaranteed to be propagated on the network, 71 | -- due to bandwidth limitations. 72 | -- 73 | -- Note: Max channel string length is 64 characters, if the channel exceeds that the message will not be sent. 74 | -- 75 | -- Note: Max message string length is 512 characters, any additional text will be truncated with a warning message displayed to the user. 76 | -- @tparam string channel The channel name. 77 | -- @tparam string message The message to transmit. 78 | function M:send(channel, message) 79 | if channel:len() > 64 then 80 | local outputMessage = "Warning: channel name cannot exceed 64 characters" 81 | if _G.system and _G.system.print and type(_G.system.print) == "function" then 82 | _G.system.print(outputMessage) 83 | else 84 | print(outputMessage) 85 | end 86 | return 87 | end 88 | 89 | message = message:sub(0, 512) 90 | 91 | -- call callbacks in order, saving exceptions until end 92 | local errors = "" 93 | for i, callback in pairs(self.receiverCallbacks) do 94 | local status, err = pcall(callback, channel, message) 95 | if not status then 96 | errors = errors .. "\nError while running callback " .. i .. ": " .. err 97 | end 98 | end 99 | 100 | -- propagate errors 101 | if self.propagateSendErrors and string.len(errors) > 0 then 102 | error("Errors raised in callbacks:" .. errors) 103 | end 104 | end 105 | 106 | --- Returns the emitter range. 107 | -- @treturn meter The range. 108 | function M:getRange() 109 | return self.range 110 | end 111 | 112 | --- Mock only, not in-game: Register a receiver of calls to send(). 113 | -- @tparam function callback The function to call (with channel and message arguments) when the send is called. 114 | -- @treturn int The index of the callback. 115 | -- @see send 116 | function M:mockRegisterReceiver(callback) 117 | local index = #self.receiverCallbacks + 1 118 | self.receiverCallbacks[index] = callback 119 | return index 120 | end 121 | 122 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 123 | -- @treturn table A table encompasing the api calls of object. 124 | -- @see Element:mockGetClosure 125 | function M:mockGetClosure() 126 | local closure = MockElement.mockGetClosure(self) 127 | closure.send = function(channel, message) return self:send(channel, message) end 128 | closure.getRange = function() return self:getRange() end 129 | 130 | closure.setSignalIn = function(plug, state) return self:setSignalIn(plug, state) end 131 | closure.getSignalIn = function(plug) return self:getSignalIn(plug) end 132 | return closure 133 | end 134 | 135 | return M 136 | -------------------------------------------------------------------------------- /test/dumocks/TestLibrary.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.Library. 3 | -- @see dumocks.Library 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local ml = require("dumocks.Library") 11 | require("test.Utilities") 12 | 13 | _G.TestLibrary = {} 14 | 15 | --- Verify results pre-load properly for systemResolution3. 16 | function _G.TestLibrary.testSystemResolution3() 17 | local library = ml:new() 18 | local closure = library:mockGetClosure() 19 | local expected, actual 20 | 21 | local resultSequence = {} 22 | resultSequence[1] = {1, 2, 3} 23 | resultSequence[2] = {2, 3, 4} 24 | 25 | -- load results in order into solutions list 26 | table.insert(library.systemResolution3Solutions, resultSequence[1]) 27 | table.insert(library.systemResolution3Solutions, resultSequence[2]) 28 | 29 | expected = resultSequence[1] 30 | actual = closure.systemResolution3({1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {0, 1, 2}) 31 | lu.assertEquals(actual, expected) 32 | 33 | expected = resultSequence[2] 34 | actual = closure.systemResolution3({1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {0, 1, 2}) 35 | lu.assertEquals(actual, expected) 36 | end 37 | 38 | --- Verify error when attempting to run without loading results. 39 | function _G.TestLibrary.testSystemResolution3Error() 40 | local library = ml:new() 41 | local closure = library:mockGetClosure() 42 | 43 | -- no results primed 44 | lu.assertErrorMsgContains("Solution 1 not loaded.", closure.systemResolution3, {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {0, 1, 2}) 45 | end 46 | 47 | --- Verify results pre-load properly for systemResolution2. 48 | function _G.TestLibrary.testSystemResolution2() 49 | local library = ml:new() 50 | local closure = library:mockGetClosure() 51 | local expected, actual 52 | 53 | local resultSequence = {} 54 | resultSequence[1] = {1, 2} 55 | resultSequence[2] = {2, 3} 56 | 57 | -- load results in order into solutions list 58 | table.insert(library.systemResolution2Solutions, resultSequence[1]) 59 | table.insert(library.systemResolution2Solutions, resultSequence[2]) 60 | 61 | expected = resultSequence[1] 62 | actual = closure.systemResolution2({1, 2, 3}, {4, 5, 6}, {7, 8, 9}) 63 | lu.assertEquals(actual, expected) 64 | 65 | expected = resultSequence[2] 66 | actual = closure.systemResolution2({1, 2, 3}, {4, 5, 6}, {7, 8, 9}) 67 | lu.assertEquals(actual, expected) 68 | end 69 | 70 | --- Verify error when attempting to run without loading results. 71 | function _G.TestLibrary.testSystemResolution2Error() 72 | local library = ml:new() 73 | local closure = library:mockGetClosure() 74 | 75 | -- no results primed 76 | lu.assertErrorMsgContains("Solution 1 not loaded.", closure.systemResolution2, {1, 2, 3}, {4, 5, 6}, {7, 8, 9}) 77 | end 78 | 79 | --- Verify results pre-load properly for getPointOnScreen. 80 | function _G.TestLibrary.testGetPointOnScreen() 81 | local library = ml:new() 82 | local closure = library:mockGetClosure() 83 | local expected, actual 84 | 85 | local resultSequence = {} 86 | resultSequence[1] = {1, 2, 3} 87 | resultSequence[2] = {2, 3, 4} 88 | 89 | -- load results in order into solutions list 90 | table.insert(library.getPointOnScreenSolutions, resultSequence[1]) 91 | table.insert(library.getPointOnScreenSolutions, resultSequence[2]) 92 | 93 | expected = resultSequence[1] 94 | actual = closure.getPointOnScreen({1, 2, 3}) 95 | lu.assertEquals(actual, expected) 96 | 97 | expected = resultSequence[2] 98 | actual = closure.getPointOnScreen({1, 2, 3}) 99 | lu.assertEquals(actual, expected) 100 | end 101 | 102 | --- Verify error when attempting to run without loading results. 103 | function _G.TestLibrary.testGetPointOnScreenError() 104 | local library = ml:new() 105 | local closure = library:mockGetClosure() 106 | 107 | -- no results primed 108 | lu.assertErrorMsgContains("Point 1 not loaded.", closure.getPointOnScreen, {1, 2, 3}) 109 | end 110 | 111 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 112 | -- in-game. 113 | -- 114 | -- Test setup: 115 | -- 1. 1x Programming Board, no connections 116 | -- 117 | -- Exercises: 118 | function _G.TestLibrary.testGameBehavior() 119 | local mock = ml:new() 120 | local library = mock:mockGetClosure() 121 | 122 | -- stub this in directly to supress print in the unit test 123 | local unit = {} 124 | unit.exit = function() end 125 | local system = {} 126 | system.print = function(_) end 127 | 128 | --------------- 129 | -- copy from here to unit.onStart() 130 | --------------- 131 | -- verify expected functions 132 | local expectedFunctions = {"systemResolution3", "systemResolution2", "getPointOnScreen", "load"} 133 | _G.Utilities.verifyExpectedFunctions(library, expectedFunctions) 134 | 135 | system.print("Success") 136 | unit.exit() 137 | --------------- 138 | -- copy to here to unit.onStart() 139 | --------------- 140 | end 141 | 142 | os.exit(lu.LuaUnit.run()) -------------------------------------------------------------------------------- /test/renderScript/layerOperations.lua: -------------------------------------------------------------------------------- 1 | -- Draw basic elements to a layer then use layer operations to manipulate it 2 | local font = loadFont("RobotoMono", 300) 3 | 4 | local count = 0 5 | local function drawLayer(layer, x, y, width, height) 6 | count = count + 1 7 | 8 | setNextFillColor(layer, 0, 0, 0, 1) 9 | setNextStrokeColor(layer, 1, 1, 1, 1) 10 | setNextStrokeWidth(layer, height / 100) 11 | addBox(layer, x, y, width, height) 12 | 13 | setNextFillColor(layer, 1, 0, 0, 1) 14 | addBox(layer, x + width / 4, y + height / 2, width / 4, height * 3 / 8) 15 | 16 | setFontSize(font, math.min(height / 6, width / 6)) 17 | setNextFillColor(layer, 0, 1, 0, 1) 18 | setNextTextAlign(layer, AlignH_Right, AlignV_Baseline) 19 | addText(layer, font, tostring(count), x + width / 4, y + height * 7 / 8) 20 | 21 | setFontSize(font, math.min(height / 2, width / 2)) 22 | setNextFillColor(layer, 0, 1, 0, 1) 23 | addText(layer, font, "Up", x + width / 2, y + height * 7 / 8) 24 | 25 | setNextFillColor(layer, 1, 0, 0, 1) 26 | addTriangle(layer, x + width / 8, y + height / 2, x + width * 3 / 8, y + height / 10, x + width * 5 / 8, 27 | y + height / 2) 28 | end 29 | 30 | local xRes, yRes = getResolution() 31 | local xC, yC = 0, 0 32 | 33 | setBackgroundColor(0.5, 0.5, 0.5) 34 | 35 | local xOff, yOff = 0, 0 36 | local width, height = xRes / 4, yRes / 4 37 | local layer 38 | 39 | -- no transform / clipped 40 | layer = createLayer() 41 | drawLayer(layer, xOff, yOff, width, height) 42 | 43 | xOff = xOff + width 44 | layer = createLayer() 45 | drawLayer(layer, xOff, yOff, width, height) 46 | setLayerClipRect(layer, xOff + width / 8, yOff + height / 8, width * 3 / 4, height * 3 / 4) 47 | 48 | -- translation / clipped 49 | xOff = 0 50 | yOff = 0 51 | layer = createLayer() 52 | drawLayer(layer, xOff, yOff, width, height) 53 | setLayerTranslation(layer, 0, height) 54 | 55 | layer = createLayer() 56 | drawLayer(layer, xOff, yOff, width, height) 57 | setLayerTranslation(layer, width, height) 58 | setLayerClipRect(layer, xOff + width / 8, yOff + height / 8, width * 3 / 4, height * 3 / 4) 59 | 60 | -- rotated (origin) / clipped 61 | xOff = height * 2 62 | yOff = -width 63 | layer = createLayer() 64 | drawLayer(layer, xOff, yOff, height, width) 65 | setLayerRotation(layer, math.pi / 2) 66 | 67 | yOff = yOff - width 68 | layer = createLayer() 69 | drawLayer(layer, xOff, yOff, height, width) 70 | setLayerRotation(layer, math.pi / 2) 71 | setLayerClipRect(layer, xOff + height / 8, yOff + width / 8, height * 3 / 4, width * 3 / 4) 72 | 73 | -- rotated (local) / clipped 74 | xOff = 0 75 | yOff = height * 3 76 | layer = createLayer() 77 | drawLayer(layer, xOff - width, yOff - height, width, height) 78 | setLayerOrigin(layer, xOff, yOff) 79 | setLayerRotation(layer, -math.pi) 80 | 81 | xOff = xOff + width 82 | layer = createLayer() 83 | drawLayer(layer, xOff - width, yOff - height, width, height) 84 | setLayerOrigin(layer, xOff, yOff) 85 | setLayerRotation(layer, -math.pi) 86 | setLayerClipRect(layer, xOff - width * 7 / 8, yOff - height * 7 / 8, width * 3 / 4, height * 3 / 4) 87 | 88 | -- scale (origin) / clipped 89 | xOff = width * 2 90 | yOff = 0 91 | layer = createLayer() 92 | drawLayer(layer, xOff * 2, yOff / 2, width * 2, height / 2) 93 | setLayerScale(layer, 0.5, 2) 94 | 95 | xOff = xOff + width 96 | layer = createLayer() 97 | drawLayer(layer, xOff * 2, yOff / 2, width * 2, height / 2) 98 | setLayerScale(layer, 0.5, 2) 99 | setLayerClipRect(layer, (xOff + width / 8) * 2, (yOff + height / 8) / 2, width * 3 / 2, height * 3 / 8) 100 | 101 | -- scale (local) / clipped 102 | xOff = width * 2 103 | yOff = height 104 | layer = createLayer() 105 | drawLayer(layer, xOff, yOff, width * 2, height / 2) 106 | setLayerOrigin(layer, xOff, yOff) 107 | setLayerScale(layer, 0.5, 2) 108 | 109 | xOff = xOff + width 110 | layer = createLayer() 111 | drawLayer(layer, xOff, yOff, width * 2, height / 2) 112 | setLayerOrigin(layer, xOff, yOff) 113 | setLayerScale(layer, 0.5, 2) 114 | setLayerClipRect(layer, xOff + width / 4, yOff + height / 8 / 2, width * 3 / 2, height * 3 / 8) 115 | 116 | -- scale-invert (local) / clipped 117 | xOff = width * 2 118 | yOff = height 119 | layer = createLayer() 120 | drawLayer(layer, xOff, yOff, width, height) 121 | setLayerScale(layer, 1, -1) 122 | setLayerOrigin(layer, xOff, yOff + height) 123 | 124 | xOff = xOff + width 125 | layer = createLayer() 126 | drawLayer(layer, xOff, yOff, width, height) 127 | setLayerScale(layer, 1, -1) 128 | setLayerOrigin(layer, xOff, yOff + height) 129 | setLayerClipRect(layer, xOff + width / 8, yOff + height / 8, width * 3 / 4, height * 3 / 4) 130 | 131 | -- scale + rotate (shared origin) + translate / clipped 132 | xOff = 0 133 | yOff = 0 134 | layer = createLayer() 135 | drawLayer(layer, xOff, yOff, width * 2, height * 2) 136 | setLayerScale(layer, -0.5, -0.5) 137 | setLayerRotation(layer, math.pi) 138 | setLayerOrigin(layer, width, height) 139 | setLayerTranslation(layer, width * 3 / 2, height * 5 / 2) 140 | 141 | layer = createLayer() 142 | drawLayer(layer, xOff, yOff, width * 2, height * 2) 143 | setLayerScale(layer, -0.5, -0.5) 144 | setLayerRotation(layer, math.pi) 145 | setLayerOrigin(layer, width, height) 146 | setLayerTranslation(layer, width * 5 / 2, height * 5 / 2) 147 | setLayerClipRect(layer, xOff + width / 4, yOff + height / 4, width * 3 / 2, height * 3 / 2) 148 | -------------------------------------------------------------------------------- /test/dumocks/TestForceFieldUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.ForceFieldUnit. 3 | -- @see dumocks.ForceFieldUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mffu = require("dumocks.ForceFieldUnit") 11 | require("test.Utilities") 12 | local AbstractTestElementWithToggle = require("test.dumocks.AbstractTestElementWithToggle") 13 | 14 | _G.TestForceFieldUnit = AbstractTestElementWithToggle 15 | 16 | function _G.TestForceFieldUnit.getTestElement() 17 | return mffu:new() 18 | end 19 | 20 | function _G.TestForceFieldUnit.getStateFunction(closure) 21 | return closure.isDeployed 22 | end 23 | 24 | function _G.TestForceFieldUnit.getActivateFunction(closure) 25 | return closure.deploy 26 | end 27 | 28 | function _G.TestForceFieldUnit.getDeactivateFunction(closure) 29 | return closure.retract 30 | end 31 | 32 | --- Verify constructor arguments properly handled and independent between instances. 33 | function _G.TestForceFieldUnit.testConstructor() 34 | 35 | -- default element: 36 | -- ["force field xs"] = {mass = 110.62, maxHitPoints = 50.0, itemId = 3686074288} 37 | 38 | local field0 = mffu:new() 39 | local field1 = mffu:new(nil, 1, "Force Field XS") 40 | local field2 = mffu:new(nil, 2, "invalid") 41 | local field3 = mffu:new(nil, 3, "force field s") 42 | 43 | local fieldClosure0 = field0:mockGetClosure() 44 | local fieldClosure1 = field1:mockGetClosure() 45 | local fieldClosure2 = field2:mockGetClosure() 46 | local fieldClosure3 = field3:mockGetClosure() 47 | 48 | lu.assertEquals(fieldClosure0.getLocalId(), 0) 49 | lu.assertEquals(fieldClosure1.getLocalId(), 1) 50 | lu.assertEquals(fieldClosure2.getLocalId(), 2) 51 | lu.assertEquals(fieldClosure3.getLocalId(), 3) 52 | 53 | local defaultId = 3686074288 54 | lu.assertEquals(fieldClosure0.getItemId(), defaultId) 55 | lu.assertEquals(fieldClosure1.getItemId(), defaultId) 56 | lu.assertEquals(fieldClosure2.getItemId(), defaultId) 57 | lu.assertNotEquals(fieldClosure3.getItemId(), defaultId) 58 | end 59 | 60 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 61 | -- in-game. 62 | -- 63 | -- Test setup: 64 | -- 1. 1x Force Field, connected to Programming Board on slot1 65 | -- 66 | -- Exercises: getClass, retract, deploy, toggle, isDeployed, setSignalIn, getSignalIn 67 | function _G.TestForceFieldUnit.testGameBehavior() 68 | local mock = mffu:new(nil, 1) 69 | local slot1 = mock:mockGetClosure() 70 | 71 | -- stub this in directly to supress print in the unit test 72 | local unit = {} 73 | unit.exit = function() 74 | end 75 | local system = {} 76 | system.print = function(_) 77 | end 78 | 79 | --------------- 80 | -- copy from here to unit.onStart() 81 | --------------- 82 | -- verify expected functions 83 | local expectedFunctions = {"deploy", "retract", "isDeployed", "setSignalIn", "getSignalIn"} 84 | for _, v in pairs(_G.Utilities.elementFunctions) do 85 | table.insert(expectedFunctions, v) 86 | end 87 | for _, v in pairs(_G.Utilities.toggleFunctions) do 88 | table.insert(expectedFunctions, v) 89 | end 90 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 91 | 92 | -- test element class and inherited methods 93 | assert(slot1.getClass() == "ForceFieldUnit") 94 | assert(string.match(string.lower(slot1.getName()), "force field %w+ %[%d+%]"), slot1.getName()) 95 | local expectedId = {[3686074288] = true, [3685998465] = true, [3686006062] = true, [3685982092] = true} 96 | assert(expectedId[slot1.getItemId()], "Unexpected id: " .. slot1.getItemId()) 97 | assert(slot1.getMaxHitPoints() == 50.0) 98 | assert(slot1.getMass() == 110.62) 99 | _G.Utilities.verifyBasicElementFunctions(slot1, 3) 100 | 101 | -- ensure initial state 102 | slot1.retract() 103 | assert(slot1.isDeployed() == 0) 104 | 105 | -- validate methods 106 | slot1.deploy() 107 | assert(slot1.isDeployed() == 1) 108 | slot1.retract() 109 | assert(slot1.isDeployed() == 0) 110 | slot1.toggle() 111 | assert(slot1.isDeployed() == 1) 112 | 113 | -- play with set signal, appears to cause the element to refresh state to match actual input signal when it doesn't already 114 | slot1.deploy() 115 | assert(slot1.isDeployed() == 1) 116 | slot1.setSignalIn("in", 0.0) 117 | assert(slot1.getSignalIn("in") == 0.0) 118 | assert(slot1.isDeployed() == 0) 119 | slot1.setSignalIn("in", 1.0) 120 | assert(slot1.getSignalIn("in") == 0.0) 121 | assert(slot1.isDeployed() == 0) 122 | 123 | slot1.deploy() 124 | slot1.setSignalIn("in", 1.0) 125 | assert(slot1.getSignalIn("in") == 0.0) 126 | assert(slot1.isDeployed() == 0) 127 | 128 | slot1.deploy() 129 | assert(slot1.isDeployed() == 1) 130 | slot1.setSignalIn("in", 0.7) 131 | assert(slot1.getSignalIn("in") == 0.0) 132 | 133 | slot1.deploy() 134 | assert(slot1.isDeployed() == 1) 135 | slot1.setSignalIn("in", "1.0") 136 | assert(slot1.getSignalIn("in") == 0.0) 137 | 138 | system.print("Success") 139 | unit.exit() 140 | --------------- 141 | -- copy to here to unit.onStart() 142 | --------------- 143 | end 144 | 145 | os.exit(lu.LuaUnit.run()) 146 | -------------------------------------------------------------------------------- /test/dumocks/TestLandingGearUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.LandingGearUnit. 3 | -- @see dumocks.LandingGearUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mlgu = require("dumocks.LandingGearUnit") 11 | require("test.Utilities") 12 | local AbstractTestElementWithToggle = require("test.dumocks.AbstractTestElementWithToggle") 13 | 14 | _G.TestLandingGearUnit = AbstractTestElementWithToggle 15 | 16 | function _G.TestLandingGearUnit.getTestElement() 17 | return mlgu:new() 18 | end 19 | 20 | function _G.TestLandingGearUnit.getStateFunction(closure) 21 | return closure.isDeployed 22 | end 23 | 24 | function _G.TestLandingGearUnit.getActivateFunction(closure) 25 | return closure.deploy 26 | end 27 | 28 | function _G.TestLandingGearUnit.getDeactivateFunction(closure) 29 | return closure.retract 30 | end 31 | 32 | --- Verify constructor arguments properly handled and independent between instances. 33 | function _G.TestLandingGearUnit.testConstructor() 34 | 35 | -- default element: 36 | -- ["landing gear s"] = {mass = 258.76, maxHitPoints = 5000.0, itemId = 1884031929} 37 | 38 | local gear0 = mlgu:new() 39 | local gear1 = mlgu:new(nil, 1, "Landing Gear S") 40 | local gear2 = mlgu:new(nil, 2, "invalid") 41 | local gear3 = mlgu:new(nil, 3, "landing gear m") 42 | 43 | local gearClosure0 = gear0:mockGetClosure() 44 | local gearClosure1 = gear1:mockGetClosure() 45 | local gearClosure2 = gear2:mockGetClosure() 46 | local gearClosure3 = gear3:mockGetClosure() 47 | 48 | lu.assertEquals(gearClosure0.getLocalId(), 0) 49 | lu.assertEquals(gearClosure1.getLocalId(), 1) 50 | lu.assertEquals(gearClosure2.getLocalId(), 2) 51 | lu.assertEquals(gearClosure3.getLocalId(), 3) 52 | 53 | -- prove default element is selected only where appropriate 54 | local defaultMass = 258.76 55 | lu.assertEquals(gearClosure0.getMass(), defaultMass) 56 | lu.assertEquals(gearClosure1.getMass(), defaultMass) 57 | lu.assertEquals(gearClosure2.getMass(), defaultMass) 58 | lu.assertNotEquals(gearClosure3.getMass(), defaultMass) 59 | 60 | local defaultId = 1884031929 61 | lu.assertEquals(gearClosure0.getItemId(), defaultId) 62 | lu.assertEquals(gearClosure1.getItemId(), defaultId) 63 | lu.assertEquals(gearClosure2.getItemId(), defaultId) 64 | lu.assertNotEquals(gearClosure3.getItemId(), defaultId) 65 | end 66 | 67 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 68 | -- in-game. 69 | -- 70 | -- Test setup: 71 | -- 1. 1x Landing Gear, connected to Programming Board on slot1 72 | -- 73 | -- Exercises: getClass, retract, deploy, toggle, isDeployed, setSignalIn, getSignalIn 74 | function _G.TestLandingGearUnit.testGameBehavior() 75 | local mock = mlgu:new(nil, 1, "landing gear xs") 76 | local slot1 = mock:mockGetClosure() 77 | 78 | -- stub this in directly to supress print in the unit test 79 | local unit = {} 80 | unit.exit = function() 81 | end 82 | local system = {} 83 | system.print = function(_) 84 | end 85 | 86 | --------------- 87 | -- copy from here to unit.onStart() 88 | --------------- 89 | -- verify expected functions 90 | local expectedFunctions = {"deploy", "retract", "isDeployed", "setSignalIn", "getSignalIn"} 91 | for _, v in pairs(_G.Utilities.elementFunctions) do 92 | table.insert(expectedFunctions, v) 93 | end 94 | for _, v in pairs(_G.Utilities.toggleFunctions) do 95 | table.insert(expectedFunctions, v) 96 | end 97 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 98 | 99 | -- test element class and inherited methods 100 | assert(slot1.getClass() == "LandingGearUnit") 101 | assert(string.match(string.lower(slot1.getName()), "landing gear %w+ %[%d+%]"), slot1.getName()) 102 | local expectedId = {[4078067869] = true, [1884031929] = true, [1899560165] = true, [2667697870] = true} 103 | assert(expectedId[slot1.getItemId()], "Unexpected id: " .. slot1.getItemId()) 104 | assert(slot1.getMaxHitPoints() == 1250.0) 105 | assert(slot1.getMass() == 49.88) 106 | _G.Utilities.verifyBasicElementFunctions(slot1, 3) 107 | 108 | -- play with set signal, has no actual effect on state when set programmatically 109 | local initialState = slot1.isDeployed() 110 | slot1.setSignalIn("in", 0.0) 111 | assert(slot1.getSignalIn("in") == 0.0) 112 | assert(slot1.isDeployed() == initialState) 113 | slot1.setSignalIn("in", 1.0) 114 | assert(slot1.getSignalIn("in") == 0.0) 115 | assert(slot1.isDeployed() == initialState) 116 | slot1.setSignalIn("in", 0.7) 117 | assert(slot1.getSignalIn("in") == 0.0) 118 | assert(slot1.isDeployed() == initialState) 119 | slot1.setSignalIn("in", "1.0") 120 | assert(slot1.getSignalIn("in") == 0.0) 121 | assert(slot1.isDeployed() == initialState) 122 | 123 | -- ensure initial state 124 | slot1.retract() 125 | assert(slot1.isDeployed() == 0) 126 | 127 | -- validate methods 128 | slot1.deploy() 129 | assert(slot1.isDeployed() == 1) 130 | slot1.retract() 131 | assert(slot1.isDeployed() == 0) 132 | slot1.toggle() 133 | assert(slot1.isDeployed() == 1) 134 | 135 | system.print("Success") 136 | unit.exit() 137 | --------------- 138 | -- copy to here to unit.onStart() 139 | --------------- 140 | end 141 | 142 | os.exit(lu.LuaUnit.run()) 143 | -------------------------------------------------------------------------------- /test/dumocks/TestDoorUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.DoorUnit. 3 | -- @see dumocks.DoorUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mdu = require("dumocks.DoorUnit") 11 | require("test.Utilities") 12 | local AbstractTestElementWithToggle = require("test.dumocks.AbstractTestElementWithToggle") 13 | 14 | _G.TestDoorUnit = AbstractTestElementWithToggle 15 | 16 | function _G.TestDoorUnit.getTestElement() 17 | return mdu:new() 18 | end 19 | 20 | function _G.TestDoorUnit.getStateFunction(closure) 21 | return closure.isOpen 22 | end 23 | 24 | function _G.TestDoorUnit.getActivateFunction(closure) 25 | return closure.open 26 | end 27 | 28 | function _G.TestDoorUnit.getDeactivateFunction(closure) 29 | return closure.close 30 | end 31 | 32 | --- Verify constructor arguments properly handled and independent between instances. 33 | function _G.TestDoorUnit.testConstructor() 34 | 35 | -- default element: 36 | -- ["sliding door s"] = {mass = 749.15, maxHitPoints = 56.0, itemId = 201196316} 37 | 38 | local door0 = mdu:new() 39 | local door1 = mdu:new(nil, 1, "Sliding Door S") 40 | local door2 = mdu:new(nil, 2, "invalid") 41 | local door3 = mdu:new(nil, 3, "reinforced sliding door") 42 | 43 | local doorClosure0 = door0:mockGetClosure() 44 | local doorClosure1 = door1:mockGetClosure() 45 | local doorClosure2 = door2:mockGetClosure() 46 | local doorClosure3 = door3:mockGetClosure() 47 | 48 | lu.assertEquals(doorClosure0.getLocalId(), 0) 49 | lu.assertEquals(doorClosure1.getLocalId(), 1) 50 | lu.assertEquals(doorClosure2.getLocalId(), 2) 51 | lu.assertEquals(doorClosure3.getLocalId(), 3) 52 | 53 | -- prove default element is selected only where appropriate 54 | local defaultMass = 749.15 55 | lu.assertEquals(doorClosure0.getMass(), defaultMass) 56 | lu.assertEquals(doorClosure1.getMass(), defaultMass) 57 | lu.assertEquals(doorClosure2.getMass(), defaultMass) 58 | lu.assertNotEquals(doorClosure3.getMass(), defaultMass) 59 | 60 | local defaultId = 201196316 61 | lu.assertEquals(doorClosure0.getItemId(), defaultId) 62 | lu.assertEquals(doorClosure1.getItemId(), defaultId) 63 | lu.assertEquals(doorClosure2.getItemId(), defaultId) 64 | lu.assertNotEquals(doorClosure3.getItemId(), defaultId) 65 | end 66 | 67 | --- Tests to verify the inherited functionality of ElementWithToggle. 68 | function _G.TestDoorUnit.testElementWithToggle() 69 | local mock = mdu:new() 70 | local closure = mock:mockGetClosure() 71 | 72 | mock.state = false 73 | closure.open() 74 | lu.assertTrue(mock.state) 75 | 76 | mock.state = true 77 | closure.open() 78 | lu.assertTrue(mock.state) 79 | end 80 | 81 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 82 | -- in-game. 83 | -- 84 | -- Test setup: 85 | -- 1. 1x Sliding Door S, connected to Programming Board on slot1 86 | -- 87 | -- Exercises: getElementClass, open, close, toggle, isOpen, setSignalIn, getSignalIn 88 | function _G.TestDoorUnit.testGameBehavior() 89 | local mock = mdu:new(nil, 1) 90 | local slot1 = mock:mockGetClosure() 91 | 92 | -- stub this in directly to supress print in the unit test 93 | local unit = {} 94 | unit.exit = function() 95 | end 96 | local system = {} 97 | system.print = function(_) 98 | end 99 | 100 | --------------- 101 | -- copy from here to unit.onStart() 102 | --------------- 103 | -- verify expected functions 104 | local expectedFunctions = {"open", "close", "isOpen", "setSignalIn", "getSignalIn"} 105 | for _, v in pairs(_G.Utilities.elementFunctions) do 106 | table.insert(expectedFunctions, v) 107 | end 108 | for _, v in pairs(_G.Utilities.toggleFunctions) do 109 | table.insert(expectedFunctions, v) 110 | end 111 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 112 | 113 | -- test element class and inherited methods 114 | assert(slot1.getClass() == "DoorUnit") 115 | assert(string.match(string.lower(slot1.getName()), "sliding door s %[%d+%]"), slot1.getName()) 116 | assert(slot1.getItemId() == 201196316, slot1.getItemId()) 117 | assert(slot1.getMaxHitPoints() == 56.0) 118 | assert(slot1.getMass() == 749.15) 119 | _G.Utilities.verifyBasicElementFunctions(slot1, 3) 120 | 121 | -- play with set signal, has no actual effect on state when set programmatically 122 | local initialState = slot1.isOpen() 123 | slot1.setSignalIn("in", 0.0) 124 | assert(slot1.getSignalIn("in") == 0.0) 125 | assert(slot1.isOpen() == initialState) 126 | slot1.setSignalIn("in", 1.0) 127 | assert(slot1.getSignalIn("in") == 0.0) 128 | assert(slot1.isOpen() == initialState) 129 | slot1.setSignalIn("in", 0.7) 130 | assert(slot1.getSignalIn("in") == 0.0) 131 | assert(slot1.isOpen() == initialState) 132 | slot1.setSignalIn("in", "1.0") 133 | assert(slot1.getSignalIn("in") == 0.0) 134 | assert(slot1.isOpen() == initialState) 135 | 136 | -- ensure initial state 137 | slot1.close() 138 | assert(slot1.isOpen() == 0) 139 | 140 | -- validate methods 141 | slot1.open() 142 | assert(slot1.isOpen() == 1) 143 | slot1.close() 144 | assert(slot1.isOpen() == 0) 145 | slot1.toggle() 146 | assert(slot1.isOpen() == 1) 147 | 148 | system.print("Success") 149 | unit.exit() 150 | --------------- 151 | -- copy to here to unit.onStart() 152 | --------------- 153 | end 154 | 155 | os.exit(lu.LuaUnit.run()) 156 | -------------------------------------------------------------------------------- /test/dumocks/TestLaserEmitterUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.LaserEmitterUnit. 3 | -- @see dumocks.LaserEmitterUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mleu = require("dumocks.LaserEmitterUnit") 11 | require("test.Utilities") 12 | local AbstractTestElementWithToggle = require("test.dumocks.AbstractTestElementWithToggle") 13 | 14 | _G.TestLaserEmitterUnit = AbstractTestElementWithToggle 15 | 16 | function _G.TestLaserEmitterUnit.getTestElement() 17 | return mleu:new() 18 | end 19 | 20 | function _G.TestLaserEmitterUnit.getStateFunction(closure) 21 | return closure.isActive 22 | end 23 | 24 | function _G.TestLaserEmitterUnit.getActivateFunction(closure) 25 | return closure.activate 26 | end 27 | 28 | function _G.TestLaserEmitterUnit.getDeactivateFunction(closure) 29 | return closure.deactivate 30 | end 31 | 32 | --- Verify constructor arguments properly handled and independent between instances. 33 | function _G.TestLaserEmitterUnit.testConstructor() 34 | 35 | -- default element: 36 | -- ["laser emitter xs"] = {mass = 7.47, maxHitPoints = 50.0, itemId = 1784722190} 37 | 38 | local emitter0 = mleu:new() 39 | local emitter1 = mleu:new(nil, 1, "Laser Emitter XS") 40 | local emitter2 = mleu:new(nil, 2, "invalid") 41 | local emitter3 = mleu:new(nil, 3, "infrared laser emitter xs") 42 | 43 | local emitterClosure0 = emitter0:mockGetClosure() 44 | local emitterClosure1 = emitter1:mockGetClosure() 45 | local emitterClosure2 = emitter2:mockGetClosure() 46 | local emitterClosure3 = emitter3:mockGetClosure() 47 | 48 | lu.assertEquals(emitterClosure0.getLocalId(), 0) 49 | lu.assertEquals(emitterClosure1.getLocalId(), 1) 50 | lu.assertEquals(emitterClosure2.getLocalId(), 2) 51 | lu.assertEquals(emitterClosure3.getLocalId(), 3) 52 | 53 | -- prove default element is selected only where appropriate 54 | local defaultMass = 7.47 55 | lu.assertEquals(emitterClosure0.getMass(), defaultMass) 56 | lu.assertEquals(emitterClosure1.getMass(), defaultMass) 57 | lu.assertEquals(emitterClosure2.getMass(), defaultMass) 58 | lu.assertNotEquals(emitterClosure3.getMass(), defaultMass) 59 | 60 | local defaultId = 1784722190 61 | lu.assertEquals(emitterClosure0.getItemId(), defaultId) 62 | lu.assertEquals(emitterClosure1.getItemId(), defaultId) 63 | lu.assertEquals(emitterClosure2.getItemId(), defaultId) 64 | lu.assertNotEquals(emitterClosure3.getItemId(), defaultId) 65 | end 66 | 67 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 68 | -- in-game. 69 | -- 70 | -- Test setup: 71 | -- 1. 1x Laser Emitter, connected to Programming Board on slot1 72 | -- 73 | -- Exercises: getClass, deactivate, activate, toggle, getState, setSignalIn, getSignalIn 74 | function _G.TestLaserEmitterUnit.testGameBehavior() 75 | local mock = mleu:new(nil, 1) 76 | local slot1 = mock:mockGetClosure() 77 | 78 | -- stub this in directly to supress print in the unit test 79 | local unit = {} 80 | unit.exit = function() 81 | end 82 | local system = {} 83 | system.print = function(_) 84 | end 85 | 86 | --------------- 87 | -- copy from here to unit.onStart() 88 | --------------- 89 | -- verify expected functions 90 | local expectedFunctions = {"isActive", "setSignalIn", "getSignalIn"} 91 | for _, v in pairs(_G.Utilities.elementFunctions) do 92 | table.insert(expectedFunctions, v) 93 | end 94 | for _, v in pairs(_G.Utilities.toggleFunctions) do 95 | table.insert(expectedFunctions, v) 96 | end 97 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 98 | 99 | -- test element class and inherited methods 100 | assert(slot1.getClass() == "LaserEmitterUnit") 101 | assert(string.match(string.lower(slot1.getName()), "[infrared ]*laser emitter xs %[%d+%]"), slot1.getName()) 102 | local expectedIds = {[1784722190] = true, [609676854] = true} 103 | assert(expectedIds[slot1.getItemId()], "Unexpected id: " .. slot1.getItemId()) 104 | assert(slot1.getMaxHitPoints() == 50.0) 105 | assert(slot1.getMass() == 7.47 or slot1.getMass() == 9.93) 106 | _G.Utilities.verifyBasicElementFunctions(slot1, 3) 107 | 108 | -- play with set signal, has no actual effect on state when set programmatically 109 | local initialState = slot1.isActive() 110 | slot1.setSignalIn("in", 0.0) 111 | assert(slot1.getSignalIn("in") == 0.0) 112 | assert(slot1.isActive() == initialState) 113 | slot1.setSignalIn("in", 1.0) 114 | assert(slot1.getSignalIn("in") == 0.0) 115 | assert(slot1.isActive() == initialState) 116 | slot1.setSignalIn("in", 0.7) 117 | assert(slot1.getSignalIn("in") == 0.0) 118 | assert(slot1.isActive() == initialState) 119 | slot1.setSignalIn("in", "1.0") 120 | assert(slot1.getSignalIn("in") == 0.0) 121 | assert(slot1.isActive() == initialState) 122 | 123 | -- ensure initial state 124 | slot1.deactivate() 125 | assert(slot1.isActive() == 0) 126 | 127 | -- validate methods 128 | slot1.activate() 129 | assert(slot1.isActive() == 1) 130 | slot1.deactivate() 131 | assert(slot1.isActive() == 0) 132 | slot1.toggle() 133 | assert(slot1.isActive() == 1) 134 | 135 | -- ensure final state 136 | slot1.deactivate() 137 | assert(slot1.isActive() == 0) 138 | 139 | system.print("Success") 140 | unit.exit() 141 | --------------- 142 | -- copy to here to unit.onStart() 143 | --------------- 144 | end 145 | 146 | os.exit(lu.LuaUnit.run()) 147 | -------------------------------------------------------------------------------- /test/bundleCharacterizationTest.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Reads in a lua unit tests file and extracts the characterization test pieces from it, then bundles them for direct 3 | -- pasting into an in-game control unit. 4 | 5 | -- parse arguments 6 | if not arg[1] or arg[1] == "--help" or arg[1] == "-h" then 7 | print("Expected arguments: inputFile [outputFile]") 8 | print("If outputFile is not provided will stream results to stdout.") 9 | -- TODO better help display, more detailed argument handling 10 | return 11 | end 12 | 13 | local testDirPath = string.match(arg[0], "(.*[/\\])%a+%.lua") 14 | local inputFile = arg[1] 15 | 16 | local blocks = {} 17 | 18 | -- look for inputFile in current working directory and in directory containing script 19 | local function fileExists(file) 20 | local f = io.open(file, "rb") 21 | if f then f:close() end 22 | return f ~= nil 23 | end 24 | 25 | local SKIP_LINE_PATTERN = "[ -]+%c" 26 | local BLOCK_PATTERN = "--- copy from here to (.-)%c(.-)%c%s--- copy to here to (.-)%c" 27 | 28 | local function loadFileToBlocks(file) 29 | if not fileExists(file) then 30 | if fileExists(testDirPath..file) then 31 | file = testDirPath..file 32 | else 33 | error("File not found: "..file) 34 | end 35 | end 36 | 37 | -- read content 38 | local inputHandle = io.open(file, "rb") 39 | local fileContents = io.input(inputHandle):read("*all") 40 | inputHandle:close() 41 | 42 | -- parse content into blocks 43 | fileContents = string.gsub(fileContents, SKIP_LINE_PATTERN, "") 44 | for target,code,target2 in string.gmatch(fileContents, BLOCK_PATTERN) do 45 | if target ~= target2 then 46 | print("WARNING: Non-matching labels: "..target.." ~= "..target2) 47 | end 48 | table.insert(blocks, {target=target, code=code}) 49 | end 50 | end 51 | 52 | loadFileToBlocks(inputFile) 53 | loadFileToBlocks("Utilities.lua") 54 | 55 | -- bail early if no code blocks 56 | if #blocks == 0 then 57 | return 58 | end 59 | 60 | -- prepare output 61 | local TARGET_PATTERN = "([a-zA-Z0-9]+)%.([a-zA-Z()*,]+)(.*)" 62 | local ARGS_PATTERN = "([a-zA-Z0-9_*]+)" 63 | local BOILERPLATE_START = [[ 64 | { 65 | "slots":{ 66 | "0":{"name":"slot1","type":{"events":[],"methods":[]}}, 67 | "1":{"name":"slot2","type":{"events":[],"methods":[]}}, 68 | "2":{"name":"slot3","type":{"events":[],"methods":[]}}, 69 | "3":{"name":"slot4","type":{"events":[],"methods":[]}}, 70 | "4":{"name":"slot5","type":{"events":[],"methods":[]}}, 71 | "5":{"name":"slot6","type":{"events":[],"methods":[]}}, 72 | "6":{"name":"slot7","type":{"events":[],"methods":[]}}, 73 | "7":{"name":"slot8","type":{"events":[],"methods":[]}}, 74 | "8":{"name":"slot9","type":{"events":[],"methods":[]}}, 75 | "9":{"name":"slot10","type":{"events":[],"methods":[]}}, 76 | "-1":{"name":"unit","type":{"events":[],"methods":[]}}, 77 | "-2":{"name":"construct","type":{"events":[],"methods":[]}}, 78 | "-3":{"name":"player","type":{"events":[],"methods":[]}}, 79 | "-4":{"name":"system","type":{"events":[],"methods":[]}}, 80 | "-5":{"name":"library","type":{"events":[],"methods":[]}} 81 | }, 82 | "handlers":[]] 83 | local BOILERPLATE_END = [[ 84 | ], 85 | "methods":[], 86 | "events":[] 87 | }]] 88 | -- fill with: sanitized code, formatted arguments, method signature, slot number, key number 89 | local CODE_FORMAT = '{"code":"%s","filter":{"args":[%s],"signature":"%s","slotKey":"%d"},"key":"%d"}' 90 | local ARGS_FORMAT = '{"%s":"%s"}' 91 | 92 | -- sanitize a block of code 93 | local function sanitize(code) 94 | local sanitized = code 95 | sanitized = string.gsub(sanitized, "\\", "\\\\") 96 | sanitized = string.gsub(sanitized, "\"", "\\\"") 97 | sanitized = string.gsub(sanitized, "%c", "\\n") 98 | sanitized = string.gsub(sanitized, "^ ", "") -- collapse initial indent 99 | sanitized = string.gsub(sanitized, "\\n ", "\\n") -- collapse each line first indent 100 | return sanitized 101 | end 102 | 103 | -- build output 104 | local output = BOILERPLATE_START 105 | local key = 0 106 | local first = true 107 | for _,block in pairs(blocks) do 108 | if not first then 109 | output = output.."," 110 | end 111 | first = false 112 | 113 | local slot,signature,args = string.match(block.target, TARGET_PATTERN) 114 | 115 | local sanitizedCode = sanitize(block.code) 116 | local formattedArgs = "" 117 | for argValue in string.gmatch(args, ARGS_PATTERN) do 118 | if string.len(formattedArgs) > 0 then 119 | formattedArgs = formattedArgs.."," 120 | end 121 | local argLabel = "value" 122 | if argValue == "*" then 123 | argLabel = "variable" 124 | end 125 | formattedArgs = formattedArgs..string.format(ARGS_FORMAT, argLabel, argValue) 126 | end 127 | local slotKey 128 | if slot == "unit" then 129 | slotKey = -1 130 | elseif slot == "system" then 131 | slotKey = -4 132 | elseif slot == "library" then 133 | slotKey = -5 134 | else 135 | slotKey = tonumber(string.sub(slot, 5)) - 1 136 | end 137 | 138 | output = output..string.format(CODE_FORMAT, sanitizedCode, formattedArgs, signature, slotKey, key) 139 | 140 | key = key + 1 141 | end 142 | output = output..BOILERPLATE_END 143 | 144 | -- output to file if specified, stdout otherwise 145 | if arg[2] and arg[2] ~= "" then 146 | local outputHandle = io.open(arg[2], "w") 147 | io.output(outputHandle):write(output) 148 | outputHandle:close() 149 | else 150 | print(output) 151 | end 152 | -------------------------------------------------------------------------------- /test/dumocks/TestTelemeterUnit.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --- Tests on dumocks.TelemeterUnit. 3 | -- @see dumocks.TelemeterUnit 4 | 5 | -- set search path to include src directory 6 | package.path = "src/?.lua;" .. package.path 7 | 8 | local lu = require("luaunit") 9 | 10 | local mtu = require("dumocks.TelemeterUnit") 11 | local utilities = require("test.Utilities") 12 | 13 | _G.TestTelemeterUnit = {} 14 | 15 | --- Verify constructor arguments properly handled. 16 | function _G.TestTelemeterUnit.testConstructor() 17 | 18 | -- default element: 19 | -- ["telemeter xs"] = {mass = 40.79, maxHitPoints = 50.0, itemId = 1722901246} 20 | 21 | local telemeter0 = mtu:new() 22 | local telemeter1 = mtu:new(nil, 1, "Telemeter XS") 23 | local telemeter2 = mtu:new(nil, 2, "invalid") 24 | 25 | local telemeterClosure0 = telemeter0:mockGetClosure() 26 | local telemeterClosure1 = telemeter1:mockGetClosure() 27 | local telemeterClosure2 = telemeter2:mockGetClosure() 28 | 29 | lu.assertEquals(telemeterClosure0.getLocalId(), 0) 30 | lu.assertEquals(telemeterClosure1.getLocalId(), 1) 31 | lu.assertEquals(telemeterClosure2.getLocalId(), 2) 32 | 33 | local defaultMass = 40.79 34 | lu.assertEquals(telemeterClosure0.getMass(), defaultMass) 35 | lu.assertEquals(telemeterClosure1.getMass(), defaultMass) 36 | lu.assertEquals(telemeterClosure2.getMass(), defaultMass) 37 | 38 | local defaultId = 1722901246 39 | lu.assertEquals(telemeterClosure0.getItemId(), defaultId) 40 | lu.assertEquals(telemeterClosure1.getItemId(), defaultId) 41 | lu.assertEquals(telemeterClosure2.getItemId(), defaultId) 42 | end 43 | 44 | -- Verify get distance works and respects max range. 45 | function _G.TestTelemeterUnit.testGetDistance() 46 | local mock = mtu:new() 47 | local closure = mock:mockGetClosure() 48 | 49 | -- default 50 | lu.assertEquals(closure.raycast().distance, -1) 51 | lu.assertEquals(utilities.verifyDeprecated("getDistance", closure.getDistance), -1) 52 | 53 | mock.maxDistance = 100 54 | 55 | -- in range 56 | mock.distance = 20 57 | lu.assertEquals(closure.raycast().distance, 20) 58 | 59 | -- out of range 60 | mock.distance = 200 61 | lu.assertEquals(closure.raycast().distance, -1) 62 | 63 | -- invalid 64 | mock.distance = -10 65 | lu.assertEquals(closure.raycast().distance, -1) 66 | end 67 | 68 | -- Verify get max distance works. 69 | function _G.TestTelemeterUnit.testGetMaxDistance() 70 | local mock = mtu:new() 71 | local closure = mock:mockGetClosure() 72 | 73 | -- default 74 | lu.assertEquals(closure.getMaxDistance(), 100) 75 | 76 | mock.maxDistance = 20 77 | lu.assertEquals(closure.getMaxDistance(), 20) 78 | end 79 | 80 | --- Characterization test to determine in-game behavior, can run on mock and uses assert instead of luaunit to run 81 | -- in-game. 82 | -- 83 | -- Test setup: 84 | -- 1. 3x Telemeter, connected to Programming Board on slot1, slot2, and slot3 85 | -- 2. slot1 telemeter is pointed into open space 86 | -- 3. slot2 telemeter is pointed at the floor mounted on the third voxel above it 87 | -- 4. slot3 telemeter is pointed at an industry unit as close as it can be mounted pointing at it 88 | -- 89 | -- Exercises: getElementClass, getDistance, getMaxDistance 90 | function _G.TestTelemeterUnit.testGameBehavior() 91 | local mock1 = mtu:new(nil, 1) 92 | local slot1 = mock1:mockGetClosure() 93 | local mock2 = mtu:new() 94 | local slot2 = mock2:mockGetClosure() 95 | local mock3 = mtu:new() 96 | local slot3 = mock3:mockGetClosure() 97 | 98 | -- stub this in directly to supress print in the unit test 99 | local unit = {} 100 | unit.exit = function() 101 | end 102 | local system = {} 103 | system.print = function(_) 104 | end 105 | 106 | -- set ranges measured in test setup 107 | mock1.distance = -1 108 | mock2.distance = 0.5432398362334 109 | mock3.distance = 0.35531205231629 110 | 111 | --------------- 112 | -- copy from here to unit.onStart() 113 | --------------- 114 | -- verify expected functions 115 | local expectedFunctions = {"getMaxDistance", "getDistance", "raycast", "getRayWorldAxis", "getRayAxis", 116 | "getRayOrigin", "getRayWorldOrigin"} 117 | for _, v in pairs(_G.Utilities.elementFunctions) do 118 | table.insert(expectedFunctions, v) 119 | end 120 | _G.Utilities.verifyExpectedFunctions(slot1, expectedFunctions) 121 | 122 | -- test element class and inherited methods 123 | assert(slot1.getClass() == "TelemeterUnit") 124 | assert(slot2.getClass() == "TelemeterUnit") 125 | assert(slot3.getClass() == "TelemeterUnit") 126 | assert(string.match(string.lower(slot1.getName()), "telemeter xs %[%d+%]"), slot1.getName()) 127 | assert(slot1.getItemId() == 1722901246, "Unexpected id: " .. slot1.getItemId()) 128 | assert(slot1.getMaxHitPoints() == 50.0) 129 | assert(slot1.getMass() == 40.79) 130 | _G.Utilities.verifyBasicElementFunctions(slot1, 3) 131 | 132 | assert(slot1.getMaxDistance() == 100, "Telemeter 1 max distance: " .. slot1.getMaxDistance()) 133 | 134 | local UNDEF_DISTANCE = -1 135 | 136 | local slot1Distance = slot1.raycast().distance 137 | assert(slot1Distance == UNDEF_DISTANCE, "Telemeter 1 distance: " .. slot1Distance) 138 | local slot2Distance = slot2.raycast().distance 139 | assert(slot2Distance > 0.5 and slot2Distance < 1.0, "Telemeter 2 distance: " .. slot2Distance) 140 | local slot3Distance = slot3.raycast().distance 141 | assert(slot3Distance > 0 and slot3Distance < 0.5, "Telemeter 3 distance: " .. slot3Distance) 142 | 143 | system.print("Success") 144 | unit.exit() 145 | --------------- 146 | -- copy to here to unit.onStart() 147 | --------------- 148 | end 149 | 150 | os.exit(lu.LuaUnit.run()) 151 | -------------------------------------------------------------------------------- /src/dumocks/CounterUnit.lua: -------------------------------------------------------------------------------- 1 | --- Cycle its output signal over a set of n-plugs, incrementing the activate plug by one step at each impulse received 2 | -- on its IN plug. 3 | -- 4 | -- Element class: CounterUnit 5 | -- 6 | -- Extends: @{Element} 7 | -- @module CounterUnit 8 | -- @alias M 9 | 10 | local MockElement = require "dumocks.Element" 11 | 12 | local elementDefinitions = {} 13 | elementDefinitions["2 counter xs"] = {mass = 9.93, maxHitPoints = 50.0, itemId = 888062905, maxCount = 2} 14 | elementDefinitions["3 counter xs"] = {mass = 9.93, maxHitPoints = 50.0, itemId = 888062906, maxCount = 3} 15 | elementDefinitions["5 counter xs"] = {mass = 9.93, maxHitPoints = 50.0, itemId = 888062908, maxCount = 5} 16 | elementDefinitions["7 counter xs"] = {mass = 9.93, maxHitPoints = 50.0, itemId = 888062910, maxCount = 7} 17 | elementDefinitions["10 counter xs"] = {mass = 9.93, maxHitPoints = 50.0, itemId = 888063487, maxCount = 10} 18 | local DEFAULT_ELEMENT = "2 counter xs" 19 | 20 | local M = MockElement:new() 21 | M.elementClass = "CounterUnit" 22 | 23 | function M:new(o, id, elementName) 24 | local elementDefinition = MockElement.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 25 | 26 | o = o or MockElement:new(o, id, elementDefinition) 27 | setmetatable(o, self) 28 | self.__index = self 29 | 30 | o.activeOut = 0 -- indexed at 0 31 | o.maxCount = elementDefinition.maxCount 32 | 33 | o.plugIn = 0.0 34 | 35 | return o 36 | end 37 | 38 | --- Deprecated: Returns the rank of the currently active OUT plug. 39 | -- 40 | -- This method is deprecated: getIndex should be used instead 41 | -- @see getIndex 42 | -- @return The index of the active plug. 43 | function M:getCounterState() 44 | M.deprecated("getCounterState", "getIndex") 45 | return self:getIndex() 46 | end 47 | 48 | --- Returns the index of the current active output plug. 49 | -- @treturn int The index of the active plug (1-indexed, so a 2 counter can return 1 or 2). 50 | function M:getIndex() 51 | return self.activeOut % self.maxCount + 1 52 | end 53 | 54 | --- Returns the maximum index of the counter. 55 | -- @treturn int The maximum index (0-indexed, so a 2 counter returns 1). 56 | function M:getMaxIndex() 57 | return self.maxCount - 1 -- 0-indexed 58 | end 59 | 60 | --- Deprecated: Moves the counter one step further (equivalent to signal received on the IN plug). 61 | -- 62 | -- This method is deprecated: nextIndex should be used instead 63 | -- @see nextIndex 64 | function M:next() 65 | M.deprecated("next", "nextIndex") 66 | self:nextIndex() 67 | end 68 | 69 | --- Moves the next counter index. 70 | function M:nextIndex() 71 | self.activeOut = (self.activeOut + 1) % self.maxCount 72 | end 73 | 74 | --- Sets the counter index. 75 | -- @tparam int index The index of the plug to activate (1-indexed, so valid inputs for a 2 counter are 1 and 2). 76 | function M:setIndex(index) 77 | index = index - 1 -- shift to 0-indexed 78 | if index >= self.maxCount then 79 | index = self.maxCount - 1 80 | elseif index < 0 then 81 | index = 0 82 | end 83 | self.activeOut = index 84 | end 85 | 86 | --- Set the value of a signal in the specified IN plug of the element. 87 | -- 88 | -- Valid plug names are: 89 | --
      90 | --
    • "in" for the in signal (seems to have no actual effect when modified this way).
    • 91 | --
    92 | -- @tparam string plug A valid plug name to set. 93 | -- @tparam 0/1 state The plug signal state 94 | function M:setSignalIn(plug, state) 95 | if plug == "in" then 96 | -- no longer responds to setSignalIn 97 | end 98 | end 99 | 100 | --- Return the value of a signal in the specified IN plug of the element. 101 | -- 102 | -- Valid plug names are: 103 | --
      104 | --
    • "in" for the in signal.
    • 105 | --
    106 | -- @tparam string plug A valid plug name to query. 107 | -- @treturn 0/1 The plug signal state 108 | function M:getSignalIn(plug) 109 | if plug == "in" then 110 | return self.plugIn 111 | end 112 | return MockElement.getSignalIn(self) 113 | end 114 | 115 | local OUT_SIGNAL_PATTERN = "OUT%-signal%-(%d+)" 116 | --- Return the value of a signal in the specified OUT plug of the element. 117 | -- 118 | -- Valid plug names are: 119 | --
      120 | --
    • "OUT-signal-<i>" where <i> is replaced by a number from 0 to the counter number minus 1 (so range of [0,4] for a 5 Counter).
    • 121 | --
    122 | -- @tparam string plug A valid plug name to query. 123 | -- @treturn 0/1 The plug signal state 124 | function M:getSignalOut(plug) 125 | local plugIndex = tonumber(string.match(plug, OUT_SIGNAL_PATTERN)) 126 | if plugIndex ~= nil and plugIndex >= 0 and plugIndex < self.maxCount then 127 | if plugIndex == self.activeOut then 128 | return 1.0 129 | else 130 | return 0.0 131 | end 132 | end 133 | return MockElement.getSignalOut(self, plug) 134 | end 135 | 136 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 137 | -- @treturn table A table encompasing the api calls of object. 138 | -- @see Element:mockGetClosure 139 | function M:mockGetClosure() 140 | local closure = MockElement.mockGetClosure(self) 141 | closure.getCounterState = function() return self:getCounterState() end 142 | closure.getIndex = function() return self:getIndex() end 143 | closure.getMaxIndex = function() return self:getMaxIndex() end 144 | closure.next = function() return self:next() end 145 | closure.nextIndex = function() return self:nextIndex() end 146 | closure.setIndex = function(index) return self:setIndex(index) end 147 | 148 | closure.setSignalIn = function(plug, state) return self:setSignalIn(plug, state) end 149 | closure.getSignalIn = function(plug) return self:getSignalIn(plug) end 150 | closure.getSignalOut = function(plug) return self:getSignalOut(plug) end 151 | return closure 152 | end 153 | 154 | return M -------------------------------------------------------------------------------- /src/dumocks/AdjustorUnit.lua: -------------------------------------------------------------------------------- 1 | --- Adjustors are specific motors that expel gas to generate torque on your construct. 2 | -- 3 | -- Element class: Adjustor 4 | -- 5 | -- Extends: @{Element} > @{Engine} 6 | -- @module AdjustorUnit 7 | -- @alias M 8 | 9 | local MockElement = require "dumocks.Element" 10 | local MockEngine = require "dumocks.Engine" 11 | 12 | local elementDefinitions = {} 13 | elementDefinitions["adjustor xs"] = {mass = 25.0, maxHitPoints = 50.0, itemId = 2648523849, maxThrust = 2000.0} 14 | elementDefinitions["adjustor s"] = {mass = 100.0, maxHitPoints = 50.0, itemId = 47474508, maxThrust = 8000.0} 15 | elementDefinitions["adjustor m"] = {mass = 450.0, maxHitPoints = 50.0, itemId = 3790013467, maxThrust = 32000.0} 16 | elementDefinitions["adjustor l"] = {mass = 1550.0, maxHitPoints = 298.0, itemId = 2818864930, maxThrust = 128000.0} 17 | local DEFAULT_ELEMENT = "adjustor xs" 18 | 19 | local M = MockEngine:new() 20 | M.elementClass = "Adjustor" 21 | 22 | function M:new(o, id, elementName) 23 | local elementDefinition = MockElement.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 24 | 25 | o = o or MockEngine:new(o, id, elementDefinition) 26 | setmetatable(o, self) 27 | self.__index = self 28 | 29 | o.maxThrustBase = elementDefinition.maxThrust 30 | o.currentMaxThrust = o.maxThrustBase 31 | 32 | o.plugIn = 0.0 33 | 34 | return o 35 | end 36 | 37 | --- Start the adjustor at full power (works only when run inside a cockpit or under remote control). 38 | function M:activate() 39 | end 40 | 41 | --- Stops the adjustor (works only when run inside a cockpit or under remote control). 42 | function M:deactivate() 43 | end 44 | 45 | --- Checks if the adjustor is active. 46 | -- @treturn 0/1 1 when the adjustor is on. 47 | function M:isActive() 48 | end 49 | 50 | --- Deprecated: Returns the activation state of the engine. 51 | -- 52 | -- This method is deprecated: isActive should be used instead 53 | -- @see isActive 54 | -- @treturn 0/1 1 when the engine is on, 0 otherwise. 55 | function M:getState() 56 | M.deprecated("getState", "isActive") 57 | return M:isActive() 58 | end 59 | 60 | --- Toggle the state of the adjustor. 61 | function M:toggle() 62 | end 63 | 64 | --- Set the exhaust thrust of the adjustor. 65 | -- @tparam float thrust The adjustor thrust in newtons (limited by the maximum thrust). 66 | function M:setThrust(thrust) 67 | self.currentThrust = math.max(self.currentMaxThrust, thrust) 68 | end 69 | 70 | --- Returns the current exhaust thrust of the adjustor. 71 | -- @treturn float The current exhaust thrust of the adjustor in newtons. 72 | function M:getThrust() 73 | return self.currentThrust 74 | end 75 | 76 | --- Returns the maximal exhaust thrust the adjustor can deliver. 77 | -- @treturn float The maximum exhaust thrust of the adjustor in newtons. 78 | function M:getMaxThrust() 79 | return self.maxThrustBase 80 | end 81 | 82 | --- Returns the adjustor exhaust thrust direction in construct local coordinates. 83 | -- @treturn vec3 The adjustor exhaust thrust direction vector in construct local coordinates. 84 | function M:getThrustAxis() 85 | end 86 | 87 | --- Returns the adjustor torque axis in construct local coordinates. 88 | -- @treturn vec3 The torque axis vector in construct local coordinates. 89 | function M:getTorqueAxis() 90 | end 91 | 92 | --- Returns the adjustor exhaust thrust direction in world coordinates. 93 | -- @treturn vec3 The adjustor exhaust thrust direction vector in world coordinates. 94 | function M:getWorldThrustAxis() 95 | end 96 | 97 | --- Returns the adjustor torque axis in world coordinates. 98 | -- @treturn vec3 The torque axis vector in world coordinates. 99 | function M:getWorldTorqueAxis() 100 | end 101 | 102 | --- Set the value of a signal in the specified IN plug of the element. 103 | -- 104 | -- Valid plug names are: 105 | --
      106 | --
    • "in" for the in signal (seems to have no actual effect when modified this way).
    • 107 | --
    108 | -- 109 | -- @tparam string plug A valid plug name to set. 110 | -- @tparam 0/1 state The plug signal state 111 | function M:setSignalIn(plug, state) 112 | if plug == "in" then 113 | -- testing found no response to setSignalIn 114 | end 115 | end 116 | 117 | --- Return the value of a signal in the specified IN plug of the element. 118 | -- 119 | -- Valid plug names are: 120 | --
      121 | --
    • "in" for the in signal.
    • 122 | --
    123 | -- 124 | -- @tparam string plug A valid plug name to query. 125 | -- @treturn 0/1 The plug signal state 126 | function M:getSignalIn(plug) 127 | if plug == "in" then 128 | return self.plugIn 129 | end 130 | return MockElement.getSignalIn(self) 131 | end 132 | 133 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 134 | -- @treturn table A table encompasing the api calls of object. 135 | -- @see Element:mockGetClosure 136 | function M:mockGetClosure() 137 | local closure = MockEngine.mockGetClosure(self) 138 | closure.activate = function() return self:activate() end 139 | closure.deactivate = function() return self:deactivate() end 140 | closure.isActive = function() return self:isActive() end 141 | closure.toggle = function() return self:toggle() end 142 | closure.setThrust = function(thrust) return self:setThrust(thrust) end 143 | closure.getThrust = function() return self:getThrust() end 144 | closure.getMaxThrust = function() return self:getMaxThrust() end 145 | closure.getThrustAxis = function() return self:getThrustAxis() end 146 | closure.getTorqueAxis = function() return self:getTorqueAxis() end 147 | closure.getWorldThrustAxis = function() return self:getWorldThrustAxis() end 148 | closure.getWorldTorqueAxis = function() return self:getWorldTorqueAxis() end 149 | 150 | closure.setSignalIn = function(plug, state) return self:setSignalIn(plug, state) end 151 | closure.getSignalIn = function(plug) return self:getSignalIn(plug) end 152 | 153 | -- remove missing deprecated functions 154 | closure.getMaxThrustEfficiency = nil 155 | closure.getMinThrust = nil 156 | return closure 157 | end 158 | 159 | return M -------------------------------------------------------------------------------- /src/dumocks/BrakeUnit.lua: -------------------------------------------------------------------------------- 1 | --- Brakes are elements designed to produce thrust opposite to the movement of a construct. They can be used to slow 2 | -- down your construct. 3 | -- 4 | -- Element class: 5 | --
      6 | --
    • Airbrake
    • 7 | --
    • Spacebrake
    • 8 | --
    9 | -- 10 | -- Extends: @{Element} > @{Engine} 11 | -- @module BrakeUnit 12 | -- @alias M 13 | 14 | local MockElement = require "dumocks.Element" 15 | local MockEngine = require "dumocks.Engine" 16 | 17 | local CLASS_ATMO = "Airbrake" 18 | local CLASS_SPACE = "Spacebrake" 19 | 20 | local elementDefinitions = {} 21 | elementDefinitions["atmospheric airbrake s"] = {mass = 55.55, maxHitPoints = 50.0, itemId = 65048663, class = CLASS_ATMO, maxThrust = 50000.0} 22 | elementDefinitions["atmospheric airbrake m"] = {mass = 285.25, maxHitPoints = 50.0, itemId = 2198271703, class = CLASS_ATMO, maxThrust = 500000.0} 23 | elementDefinitions["atmospheric airbrake l"] = {mass = 1501.55, maxHitPoints = 767.0, itemId = 104971834, class = CLASS_ATMO, maxThrust = 5000000.0} 24 | elementDefinitions["retro-rocket brake s"] = {mass = 137.55, maxHitPoints = 50.0, itemId = 3039211660, class = CLASS_SPACE, maxThrust = 100000.0} 25 | elementDefinitions["retro-rocket brake m"] = {mass = 714.0, maxHitPoints = 199.0, itemId = 3243532126, class = CLASS_SPACE, maxThrust = 600000.0} 26 | elementDefinitions["retro-rocket brake l"] = {mass = 3770.9, maxHitPoints = 1422.0, itemId = 1452351552, class = CLASS_SPACE, maxThrust = 3600000.0} 27 | local DEFAULT_ELEMENT = "atmospheric airbrake s" 28 | 29 | local M = MockEngine:new() 30 | 31 | function M:new(o, id, elementName) 32 | local elementDefinition = MockElement.findElement(elementDefinitions, elementName, DEFAULT_ELEMENT) 33 | 34 | o = o or MockEngine:new(o, id, elementDefinition) 35 | setmetatable(o, self) 36 | self.__index = self 37 | 38 | o.elementClass = elementDefinition.class 39 | 40 | o.maxThrustBase = elementDefinition.maxThrust 41 | o.currentMaxThrust = o.maxThrustBase 42 | 43 | return o 44 | end 45 | 46 | --- Start the brake at full power (works only when run inside a cockpit or under remote control). 47 | function M:activate() 48 | end 49 | 50 | --- Stops the brake (works only when run inside a cockpit or under remote control). 51 | function M:deactivate() 52 | end 53 | 54 | --- Checks if the brake is active. 55 | -- @treturn 0/1 1 when the brake is on. 56 | function M:isActive() 57 | end 58 | 59 | --- Deprecated: Returns the activation state of the brake. 60 | -- 61 | -- This method is deprecated: isActive should be used instead 62 | -- @see isActive 63 | -- @treturn 0/1 1 when the brake is on, 0 otherwise. 64 | function M:getState() 65 | M.deprecated("getState", "isActive") 66 | return M:isActive() 67 | end 68 | 69 | --- Toggle the state of the brake. 70 | function M:toggle() 71 | end 72 | 73 | --- Set the thrust of the brake. Note that brakes can generate a force only in the movement opposite direction. 74 | -- @tparam float thrust The brake thrust in newtons (limited by the maximum thrust). 75 | function M:setThrust(thrust) 76 | self.currentThrust = math.max(self.currentMaxThrust, thrust) 77 | end 78 | 79 | --- Returns the current thrust of the brake. 80 | -- @treturn float The thrust the brake is currently delivering in newtons. 81 | function M:getThrust() 82 | return self.currentThrust 83 | end 84 | 85 | --- Returns the maximal thrust the brake can deliver in principle, under optimal conditions. Note that the actual 86 | -- current max thrust will most of the time be less than the max thrust. 87 | -- @treturn float The base max thrust of the brake in newtons. 88 | function M:getMaxThrust() 89 | return self.maxThrustBase 90 | end 91 | 92 | --- Returns the minimal thrust the brake can deliver at the moment (can be more than zero), which will depend on 93 | -- various conditions like atmospheric density, obstruction, orientataion, etc. Most of the time, this will be 0 but it 94 | -- can be greater than 0. 95 | -- @treturn float The current min brake thrust in newtons. 96 | function M:getCurrentMinThrust() 97 | return self.currentMinThrust 98 | end 99 | 100 | --- Returns the maximal thrust the brake can deliver at the moment, which might depend on various conditions like 101 | -- atmospheric density, obstruction, orientataion, etc. The actual thrust will be anything below this maxThrust, which 102 | -- defines the current max capability of the brake. 103 | -- @treturn float The current max brake thrust in newtons. 104 | function M:getCurrentMaxThrust() 105 | return self.currentMaxThrust 106 | end 107 | 108 | --- Returns the ratio between the current maximum thrust and the optimal maximum thrust. 109 | -- @treturn float Usually 1 but can be lower for certain brakes. 110 | function M:getMaxThrustEfficiency() 111 | end 112 | 113 | --- Returns the brake thrust direction in construct local coordinates. 114 | -- @treturn vec3 The brake thrust direction vector in construct local coordinates. 115 | function M:getThrustAxis() 116 | end 117 | 118 | --- Returns the brake thrust direction in world coordinates. 119 | -- @treturn vec3 The brake thrust direction vector in world coordinates. 120 | function M:getWorldThrustAxis() 121 | end 122 | 123 | --- Mock only, not in-game: Bundles the object into a closure so functions can be called with "." instead of ":". 124 | -- @treturn table A table encompasing the api calls of object. 125 | -- @see Element:mockGetClosure 126 | function M:mockGetClosure() 127 | local closure = MockEngine.mockGetClosure(self) 128 | closure.activate = function() return self:activate() end 129 | closure.deactivate = function() return self:deactivate() end 130 | closure.isActive = function() return self:isActive() end 131 | closure.toggle = function() return self:toggle() end 132 | closure.setThrust = function(thrust) return self:setThrust(thrust) end 133 | closure.getThrust = function() return self:getThrust() end 134 | closure.getMaxThrust = function() return self:getMaxThrust() end 135 | closure.getCurrentMinThrust = function() return self:getCurrentMinThrust() end 136 | closure.getCurrentMaxThrust = function() return self:getCurrentMaxThrust() end 137 | closure.getMaxThrustEfficiency = function() return self:getMaxThrustEfficiency() end 138 | closure.getThrustAxis = function() return self:getThrustAxis() end 139 | closure.getWorldThrustAxis = function() return self:getWorldThrustAxis() end 140 | return closure 141 | end 142 | 143 | return M --------------------------------------------------------------------------------