switch to mirin-esque require semantics; don't include all stdlib modules by default

This commit is contained in:
Jill 2022-09-19 22:47:00 +03:00
parent dfb89ab405
commit dbe85cb5d1
9 changed files with 115 additions and 162 deletions

View File

@ -32,4 +32,4 @@ During distribution, there are a couple of files that should be left out:
Everything related to the core functionality - loading actors, callbacks - goes in `template/main.xml`. It's not the most convinient, but I want to eventually move this out to its own Lua file.
Everything related to the standard library should go into `template/stdlib/` - all files there are manually required in `template/stdlib/index.lua`.
Everything related to the standard library should go into `template/stdlib/` - all files there are required by the user, so be mindful of filenames

214
main.xml
View File

@ -1,6 +1,7 @@
<Layer Type="ActorFrame" InitCommand="%function(self)
_G.oat = {}
oat._main = self
oat.dir = GAMESTATE:GetCurrentSong():GetSongDir()
setmetatable(oat, {
-- if something isn't found in the table, fall back to a global lookup
@ -12,6 +13,70 @@
return f
end
})
-- make require work
-- stolen from mirin template
-- https://github.com/XeroOl/notitg-mirin/blob/0fbff2ee93d905feeb58c4aac4fe7f5f9ebc9647/template/std.lua#L17
oat.package = {
-- uranium template loader path
path = 'src/?.lua;src/?/init.lua;template/?.lua',
preload = {},
loaded = {},
loaders = {
function(modname)
local preload = oat.package.preload[modname]
return preload or 'no field oat.package.preload[\''..modname..'\']'
end,
function(modname)
local errors = {}
-- get the filename
local filename = string.gsub(modname, '%.', '/')
for path in (string.gfind or string.gmatch)(oat.package.path, '[^;]+') do
-- get the file path
local filepath = oat.dir .. string.gsub(path, '%?', filename)
-- check if file exists
if not GAMESTATE:GetFileStructure(filepath) then
table.insert(errors, 'no file \''..filepath..'\'')
else
local loader, err = loadfile(filepath)
-- check if file loads properly
if err then
error(err, 3)
elseif loader then
return oat(loader)
end
end
end
return table.concat(errors, '\n')
end,
},
}
function oat.require(modname)
local loaded = oat.package.loaded
if not loaded[modname] then
local errors = {'module \''..modname..'\' not found:'}
local chunk
for _, loader in ipairs(oat.package.loaders) do
local result = loader(modname)
if type(result) == 'string' then
table.insert(errors, result)
elseif type(result) == 'function' then
chunk = result
break
end
end
if not chunk then
error(table.concat(errors, '\n'), 2)
end
loaded[modname] = chunk()
if loaded[modname] == nil then
loaded[modname] = true
end
end
return loaded[modname]
end
oat()
local function copy(src)
@ -186,115 +251,6 @@
GAMESTATE:ApplyModifiers('clearall')
local function formatError(file, e)
local _, _, err = string.find(e, 'error loading package `[^`\']+\' %((.+)%)')
return (file and err) and ('error loading \'' .. file .. '\':\n' .. err) or e
end
local songName = GAMESTATE:GetCurrentSong():GetSongDir()
local additionalSongFolders = PREFSMAN:GetPreference('AdditionalSongFolders')
local additionalFolders = PREFSMAN:GetPreference('AdditionalFolders')
local function attemptload(f, filename) -- not to be confused with tryload
local err = ''
local lasterr = ''
local func
local s = '.' .. songName .. f
func, lasterr = loadfile(s)
if func then return func end
if not string.find(lasterr, '\' from path `') then return nil, formatError(filename, lasterr), nil end
err = err .. s .. '\n'
s = f
func, lasterr = loadfile(s)
if func then return func end
if not string.find(lasterr, '\' from path `') then return nil, formatError(filename, lasterr), nil end
err = err .. s .. '\n'
-- cut off 'Songs/' from the path
local _,index = string.find(songName,'Songs/')
local songLoc = string.sub(songName,index)
-- for every songfolder in the additionalsongfolders
if additionalSongFolders and additionalSongFolders ~= '' then
for songFolder in string.gfind(additionalSongFolders,'[^,]+') do
s = songFolder .. songLoc .. f
func, lasterr = loadfile(s)
if func then return func end
err = err .. s .. '\n'
end
end
if additionalFolders and additionalFolders ~= '' then
for folder in string.gfind(additionalFolders,'[^,]+') do
s = folder .. songName .. f
func, lasterr = loadfile(s)
if func then return func end
err = err .. s .. '\n'
end
end
return nil, lasterr, string.sub(err, 0, -2)
end
oat._loadPath = ''
function tryload(f)
local func, err, trace = attemptload(oat._loadPath .. f, f)
if not func then
if trace then
backToSongWheel('finding \'' .. f .. '\' failed, check log for more details')
error('uranium: finding \'' .. f .. '\' failed! tried these paths: ' .. '\n' .. trace, 2)
Trace(trace)
else
error(err, 2)
Trace('loading \'' .. f .. '\' failed!' .. '\n' .. err)
end
else
return oat(func)
end
end
local function getFolderStructure(path)
local folders = {}
for folder in string.gfind(path, '[^/]+') do
table.insert(folders, folder)
end
table.remove(folders, #folders)
return table.concat(folders, '/')
end
oat._requirePath = ''
function require(f)
-- . -> /
f = string.gsub(f, '%.', '/')
-- add .lua
f = f .. '.lua'
local oldpath = oat._requirePath
local folder = getFolderStructure(f)
if folder ~= '' then
oat._requirePath = oat._requirePath .. folder .. '/'
end
local res, c = pcall(tryload, oldpath .. f)
if not res then
error(c, 2)
else
local success, s = pcall(c)
if success then
return s
else
error('uranium: error loading \'' .. f .. '\':\n' .. s, 2)
end
end
oat._requirePath = oldpath
end
-- actors
local actorQueue = {}
@ -447,7 +403,7 @@
if not file then type = 'Sprite' end
table.insert(actorQueue, {
type = type,
file = file and '../src/' .. oat._requirePath .. file,
file = file and oat.dir .. file,
init = function(a)
actor.__lock(a)
end
@ -461,7 +417,7 @@
local actor = createProxyActor('Model')
table.insert(actorQueue, {
type = nil,
file = '../src/' .. oat._requirePath .. file,
file = file and oat.dir .. file,
init = function(a)
actor.__lock(a)
end
@ -474,7 +430,7 @@
local actor = createProxyActor('BitmapText')
table.insert(actorQueue, {
type = 'BitmapText',
font = font and ('../src/' .. oat._requirePath .. font) or 'common',
font = font and (oat.dir .. font) or 'common',
init = function(a)
if text then a:settext(text) end
actor.__lock(a)
@ -489,7 +445,7 @@
local actor = createProxyActor('ActorSound')
table.insert(actorQueue, {
type = 'ActorSound',
file = '../src/' .. oat._requirePath .. file,
file = oat.dir .. file,
init = function(a)
actor.__lock(a)
end
@ -497,29 +453,21 @@
return actor
end
oat._loadPath = 'template/stdlib/'
oat.tryload('index')()
oat._loadPath = 'src/'
lua = oat.tryload('main')
local success, result = pcall(function()
require('main')
end)
if lua then
local success, result = pcall(lua)
if success then
luaobj = result
if success then
luaobj = result
self:addcommand('On', onCommand)
self:addcommand('Ready', screen_ready_command)
self:queuecommand('Ready')
else
Trace('got an error loading main.lua!')
Trace(result)
backToSongWheel('loading .lua file failed, check log for details')
error('uranium: loading main.lua file failed:\n' .. result)
end
self:addcommand('On', onCommand)
self:addcommand('Ready', screen_ready_command)
self:queuecommand('Ready')
else
Trace('luaobj doesnt exist despite passing checks. thats VERY odd')
backToSongWheel('uranium: loading .lua file failed, check log for details')
error('loading main.lua file failed: \'lua\' variable doesn\'t exist despite passing checks')
Trace('got an error loading main.lua!')
Trace(result)
backToSongWheel('loading .lua file failed, check log for details')
error('uranium: loading main.lua file failed:\n' .. result)
end
-- NotITG and OpenITG have a long standing bug where the InitCommand on an actor can run twice in certain cases.

View File

@ -1,11 +1,13 @@
function sprite(self)
local self = {}
function self.sprite(self)
self:basezoomx(sw / dw)
self:basezoomy(-sh / dh)
self:x(scx)
self:y(scy)
end
function aft(self)
function self.aft(self)
self:SetWidth(dw)
self:SetHeight(dh)
self:EnableDepthBuffer(false)
@ -13,4 +15,6 @@ function aft(self)
self:EnableFloat(false)
self:EnablePreserveTexture(true)
self:Create()
end
end
return self

View File

@ -1,3 +1,5 @@
-- TODO: tons of this is commented out because of '...'. FIX. IT.
local M = {_TYPE='module', _NAME='bitop.funcs', _VERSION='1.0-0'}
local floor = math.floor

View File

@ -64,7 +64,7 @@ end
---@param default number
---@return easable
function easable(default)
return function(default)
default = default or 0
return setmetatable({a = default, toa = default}, easmeta)
end

View File

@ -1,11 +0,0 @@
require('input')
require('scheduler')
bitop = require('bitop') -- TODO: tons of this is commented out because of '...'. FIX. IT.
require('rng')
require('easable')
require('color')
require('vector2D')
require('ease')
uwuify = require('uwuify')
require('util')
require('aft')

View File

@ -1,17 +1,19 @@
inputs = { -- -1 for not pressed, time for time of press
local self = {}
self.inputs = { -- -1 for not pressed, time for time of press
Left = -1,
Down = -1,
Up = -1,
Right = -1
}
rawInputs = {
self.rawInputs = {
Left = -1,
Down = -1,
Up = -1,
Right = -1
}
directions = {
self.directions = {
Left = {-1, 0},
Down = {0, 1},
Up = {0, -1},
@ -25,15 +27,17 @@ function uranium.init()
local j = j
_main:addcommand('StepP' .. pn .. j .. 'PressMessage', function()
rawInputs[j] = t
self.rawInputs[j] = t
if uranium:call('press', j) then return end
inputs[j] = t
self.inputs[j] = t
end)
_main:addcommand('StepP' .. pn .. j .. 'LiftMessage', function()
if uranium:call('release', j) then return end
inputs[j] = -1
rawInputs[j] = -1
self.inputs[j] = -1
self.rawInputs[j] = -1
end)
end
end
end
end
return self

View File

@ -2,6 +2,8 @@
-- Lua implementation by Jill "oatmealine" Monoids
-- Licensed under CC-BY-SA
local bitop = require('stdlib.bitop')
local RAND_MAX = 4294967295
---@param x int

View File

@ -1,3 +1,5 @@
local self = {}
local scheduled = {
}
local scheduledTicks = {
@ -11,19 +13,19 @@ local function getHighestKey(t)
return s
end
function schedule(when, func)
function self:schedule(when, func)
local index = getHighestKey(scheduled) + 1
scheduled[index] = {when, func}
return index
end
function scheduleInTicks(when, func)
function self:scheduleInTicks(when, func)
local index = getHighestKey(scheduledTicks) + 1
scheduledTicks[index] = {when, func}
return index
end
function unschedule(i)
function self:unschedule(i)
if not i then
print('warning: trying to unschedule a non-existent event')
return
@ -31,7 +33,7 @@ function unschedule(i)
scheduled[i] = nil
end
function unscheduleInTicks(i)
function self:unscheduleInTicks(i)
if not i then
print('warning: trying to unschedule a non-existent event')
end
@ -54,4 +56,6 @@ function uranium.update(dt)
scheduled[k] = nil
end
end
end
end
return self