• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

vJass struct imitation in Lua

Status
Not open for further replies.
Version 1.0 an onwards can now be found here: [Lua] - vJass-style Struct


This simple library bridges a major gap in understanding of how vJass structs behave versus how Lua works with data. I'm finding myself repeating some of the same code each time I go to create a new resource, which this would help to reduce. I am writing a guide on converting from vJass to Lua, and this resource would save a lot of headache in the demo scripts that I'm writing.

Method operator overloading is definitely possible in Lua, but I don't think it's possible to "de-uglify" that kind of syntax by burying stuff within this library. I was able to do variable overloading successfully with Global Remapper, so I might be able to find a solution eventually.

As of version 0.4, vJass module-like-syntax is now supported.

Example usage of modules being used with static methods:

Code:
    s = Struct()
    m = Struct.module(function(struct)
        function struct.moduleMethod()
            struct.structMethod()
        end
    end)

    m.implement(s)
    
    function s.structMethod()
        print "structmethod"
    end
    
    m.implement(s)
    
    s.moduleMethod()

Core library:

Lua:
do Struct = {} --vJass-style Struct version 0.5.0.0 by Bribe

local mt = {__index = function(_, v) return Struct[v] end}
setmetatable(Struct, mt)
 
---Constructor: Struct([parentStruct])
---@class Struct : table
---@field allocate function
---@field deallocate function
---@field create function
---@field destroy function
---@field onDestroy function
---@field onCreate function
---@field extends function

---Constructor: Struct.module(moduleFunction)
---@class StructModule : table
---@field private init boolean
---@field public implement function

---Allocate is a static function here rather than dynamically-created per-struct.
---@param userStruct Struct
---@return Struct new_instance
local function Allocate(userStruct)
    local newInstance = {}
    setmetatable(newInstance, userStruct)
    if userStruct.onCreate then newInstance:onCreate() end
    return newInstance
end

---Deallocate is a static function here rather than dynamically-created per-struct.
---@param structInstance Struct
local function Deallocate(structInstance)
    if structInstance.onDestroy then structInstance:onDestroy() end
    for key,_ in pairs(structInstance) do structInstance[key] = nil end
end

---Acquire another struct's keys via myStruct.extends(otherStruct)
---@param struct any
---@param parentStruct any
local function Extends(struct, parentStruct)
    for key, val in pairs(parentStruct) do
        if not struct[key] then
            struct[key] = val
        end
    end
end

---Create a new "vJass"-style struct with myStruct = Struct([parentStruct]).
---@param parent? Struct
---@return Struct new_struct
function mt.__call(parent)
    local newStruct = {
        allocate    = Allocate,
        deallocate  = Deallocate,
        create      = Allocate,
        destroy     = Deallocate,
        extends     = Extends,
        super       = parent
    }
    if parent then
        setmetatable(newStruct, {__index = parent})
    else
        newStruct.__index   = newStruct
    end
    return newStruct
end

---Create a new module that can be implemented by any struct.
---@param moduleFunc StructModule
function Struct.module(moduleFunc)
    local module = {}
    module.init = {}
    module.implement = function(struct)
        if not module.init[struct] then
            module.init[struct] = true
            moduleFunc(struct)
        end
    end
    return module
end

end --end of Struct library
 
Last edited:
Status
Not open for further replies.
Top