• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • Create a faction for Warcraft 3 and enter Hive's 19th Techtree Contest: Co-Op Commanders! Click here to enter!
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 21st Texturing Contest: Upgrade is now concluded, time to vote for your favourite set of icons! Click here to vote!

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