Jump to content

Utilities Class for modder


Konijima

Recommended Posts

I share my Utilities class here, it add a variety of useful function to help make mods implementation works both in SP as in MP.

  • It contains client only functions, server only functions and shared functions that can be used by both the client and server.
  • The networking functions give the modders a way to make networking code work also in Single Player without needing extra code to handle that.
  • It also give functions to check if a player is admin and moderator that both works in single player and multiplayer.
  • For the admin function to be true in single player the game must run with debug mode enabled.


This post will be updated if I update my version of the Utilities class with future game updates.
Post suggestions, errors, fixes, refactor ideas of this class in this post to help improve this class.

Current Game Version:

41.66


Location to place the file in your mods:

media\lua\shared\Utilities.lua


How to use:

local Utilities = require("Utilities");

 

The Class:

---@class Utilities
local Utilities = {};

--- [SHARED]
--- Return a IsoPlayer from its username if found
function Utilities.GetPlayerFromUsername(username)
    if isServer() then
        local players = getOnlinePlayers();
        for i = 0, players:size() - 1 do
            local player = players:get(i);
            if player:getUsername() == username then
                return player;
            end
        end
    elseif isClient() then
        return getPlayerFromUsername(username);
    end
end

--- [SHARED]
--- Return true if game is single player
---@return boolean
function Utilities.IsSinglePlayer()
    return not isClient() and not isServer();
end

--- [SHARED]
--- Return true if game is single player with debug enabled
---@return boolean
function Utilities.IsSinglePlayerDebug()
    return Utilities.IsSinglePlayer() and isDebugEnabled();
end

--- [CLIENT]
--- Return true if the game is client or single player
function Utilities.IsClientOrSinglePlayer()
    return isClient() or Utilities.IsSinglePlayer();
end

--- [SERVER]
--- Return true if the game is server or single player
function Utilities.IsServerOrSinglePlayer()
    return isServer() or Utilities.IsSinglePlayer();
end

--- [CLIENT]
--- Return true if client is admin or single player + debug mode
---@return boolean
function Utilities.IsClientAdmin()
    return (isClient() and isAdmin()) or Utilities.IsSinglePlayerDebug();
end

--- [CLIENT]
--- Return true if the client is admin or moderator
---@return boolean
function Utilities.IsClientStaff()
    local playerObj = getPlayer();
    return Utilities.IsClientAdmin() or (instanceof(playerObj, "IsoPlayer") and playerObj:getAccessLevel() == "Moderator");
end

--- [SERVER]
--- Return true if the IsoPlayer is admin or single player + debug mode
---@param playerObjOrUsername IsoPlayer|string
---@return boolean
function Utilities.IsPlayerAdmin(playerObjOrUsername)
    if type(playerObjOrUsername) == "string" then
        playerObjOrUsername = Utilities.GetPlayerFromUsername(playerObjOrUsername);
    end
    return (instanceof(playerObjOrUsername, "IsoPlayer") and playerObjOrUsername:getAccessLevel() == "Admin") or Utilities.IsSinglePlayerDebug();
end

--- [SERVER]
--- Return true if the IsoPlayer is admin or moderator
---@param playerObjOrUsername IsoPlayer|string
---@return boolean
function Utilities.IsPlayerStaff(playerObjOrUsername)
    if type(playerObjOrUsername) == "string" then
        playerObjOrUsername = Utilities.GetPlayerFromUsername(playerObjOrUsername);
    end
    return (instanceof(playerObjOrUsername, "IsoPlayer") and (playerObjOrUsername:getAccessLevel() == "Admin" or playerObjOrUsername:getAccessLevel() == "Moderator")) or Utilities.IsSinglePlayerDebug();
end

--- [CLIENT]
--- Send a command from the client to the server
---@param _module string
---@param _command string
---@param _data table
function Utilities.SendClientCommand(_module, _command, _data)
    if Utilities.IsClientOrSinglePlayer() then
        sendClientCommand(_module, _command, _data);
    end
end

--- [SERVER]
--- Send a command from the server to a specific client
---@param _targetPlayerObj IsoPlayer
---@param _module string
---@param _command string
---@param _data table
function Utilities.SendServerCommandTo(_targetPlayerObj, _module, _command, _data)
    if Utilities.IsServerOrSinglePlayer() then
        if Utilities.IsSinglePlayer() then
            triggerEvent("OnServerCommand", _module, _command, _data);
        else
            sendServerCommand(_targetPlayerObj, _module, _command, _data);
        end
    end
end

--- [SERVER]
--- Send a command from the server to all clients
---@param _module string
---@param _command string
---@param _data table
function Utilities.SendServerCommandToAll(_module, _command, _data)
    if Utilities.IsServerOrSinglePlayer() then
        if Utilities.IsSinglePlayer() then
            triggerEvent("OnServerCommand", _module, _command, _data);
        else
            sendServerCommand(_module, _command, _data);
        end
    end
end

--- [SERVER]
--- Send a command from the server to all clients in range
---@param _x number
---@param _y number
---@param _z number
---@param _distanceMin number
---@param _distanceMax number
---@param _module string
---@param _command string
---@param _data table
function Utilities.SendServerCommandToAllInRange(_x, _y, _z, _distanceMin, _distanceMax, _module, _command, _data)
    if Utilities.IsServerOrSinglePlayer() then
        if Utilities.IsSinglePlayer() then
            if Utilities.IsPlayerInRange(getPlayer(), _x, _y, _z, _distanceMin, _distanceMax) then
                triggerEvent("OnServerCommand", _module, _command, _data);
            end
        else
            local players = getOnlinePlayers();
            if players then
                for i = 0, players:size() - 1 do
                    local targetPlayer = players:get(i);
                    if Utilities.IsPlayerInRange(targetPlayer, _x, _y, _z, _distanceMin, _distanceMax) then
                        sendServerCommand(targetPlayer, _module, _command, _data);
                    end
                end
            end
        end
    end
end

--- [SHARED]
--- Return true if the IsoPlayer is in range
---@param _x number
---@param _y number
---@param _z number
---@param _distanceMin number
---@param _distanceMax number
---@return boolean
function Utilities.IsPlayerInRange(_playerObj, _x, _y, _z, _distanceMin, _distanceMax)
    if not _playerObj then return false; end
    local x2, y2, z2 = _playerObj:getX(), _playerObj:getY(), _playerObj:getZ();
    local currentDistance = IsoUtils.DistanceTo(_x, _y, _z, x2, y2, z2);
    return (currentDistance >= _distanceMin and currentDistance <= _distanceMax);
end

--- Check if a square is powerred
function Utilities.SquareHasElectricity(square)
    return (SandboxVars.AllowExteriorGenerator and square and square:haveElectricity()) or (SandboxVars.ElecShutModifier > -1 and GameTime:getInstance():getNightsSurvived() < SandboxVars.ElecShutModifier);
end

--- Get the server name or the save file name in single player
function Utilities.GetServerName()
    if Utilities.IsSinglePlayer() then
        local world = getWorld():getWorld();
        if type(world) == "string" and world ~= "" then
            local saveInfo = getSaveInfo(world)
            if saveInfo and saveInfo.gameMode then
                return saveInfo.saveName;
            end
        end
        return "SinglePlayerGame";
    else
        return getServerOptions():getOptionByName("PublicName"):getValue();
    end
    return "Unknown";
end

function Utilities.SplitString(str, delimiter)
    local result = {}
    for match in (str..delimiter):gmatch("(.-)%"..delimiter) do
        table.insert(result, match)
    end
    return result
end

function Utilities.SquareToString(square)
    if square then
        return square:getX() .. "|" .. square:getY() .. "|" .. square:getZ();
    end
end

function Utilities.StringToSquare(string)
    local split = Utilities.SplitString(string, "|");
    if #split >= 3 then
        local x, y, z = tonumber(split[1]), tonumber(split[2]), tonumber(split[3]);
        local square = getCell():getGridSquare(x, y, z);
        if square then
            return square;
        end
    end
end

function Utilities.FindAllItemInInventoryByTag(inventory, tag)
    local foundItems = ArrayList.new()
    local validItems = getScriptManager():getItemsTag(tag)
    if validItems then
        for i=0, validItems:size()-1 do
            foundItems:addAll(inventory:getItemsFromFullType(validItems:get(i):getFullName()))
        end
    end
    return foundItems
end

function Utilities.GetMoveableDisplayName(obj)
	if not obj then return nil end
	if not obj:getSprite() then return nil end
	local props = obj:getSprite():getProperties();
	if props:Is("CustomName") then
		local name = props:Val("CustomName");
		if props:Is("GroupName") then
			name = props:Val("GroupName") .. " " .. name;
		end
		return Translator.getMoveableDisplayName(name);
	end
	return nil;
end

return Utilities;

 

Link to comment
Share on other sites

  • 9 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...