Zen's Utilities - ZenarchistCode/ZenModPack GitHub Wiki

What Is This?

This is not really a gameplay mod, just a handful of quality-of-life functions and features to assist in my own mod functionality.

For example there are some advanced logging features that allows me to log text with timestamps to various files in folders organized by date based on their gameplay category, and some custom functions to assist with various things like moving inventories between objects etc.

It's mainly for mod developers who want to build on my mod base/modpack code - to see the utility functions check ZenModPack/scripts/4_world/classes/ZenMods/ZenFunctions/ZenFunctions.c

It does come with some basic config however, so this wiki will explain what the various config does.

Logger

My modpack generates a whole bunch of logs in the profiles folder for debugging and moderating the server.

Check the Logs folder in %server_profiles%/Zenarchist/Logs for the log text files.

ZenUtilities.json Config

This modpack will create a default ZenUtilities config file in your profiles folder %server_root/profiles/Zenarchist/ZenUtilities.json

Here is a description of what each setting does:

{
    "CONFIG_VERSION": "1",
    "CountServerFPS": 1, // Turns on/off server FPS monitoring
    "FpsChatCommand": "fps", // In-game text chat command for sending current FPS stats to players (usage: !fps)
    "ServerFPSWarningMsg": "PERFORMANCE WARNING: Server FPS is currently %1. This is low and very bad for vehicle desync. Be careful if driving!",
    "ServerFPSWarning": 20, // Triggers above warning message to be sent to players in cars
    "ServerActionFPSDropWarningPct": 10, // If an action causes server FPS to drop below this number it prints an Error log flagging the action, might need optimizing
    "ShouldLogLootCyclers": 1, // Not used yet but in future updates will log potential loot cyclers if enabled
    "ShouldLogPVP": 1, // If enabled, the mod will log PVP activities to the PVP text file
    "ShouldLogDeathGear": 1, // If enabled, the mod will log all of a player's inventory items upon death
    "ShouldDeleteGhostItems": 1, // If enabled, the mod will delete any items spawned at coords 0 0 0
    "ShouldLogItemCount": 1, // If enabled, the mod will log the number of items on your server listed in the below cfg
    "ItemTextContains": 1, // If disabled, the items below must match their item classnames EXACTLY or they won't be counted
    "LogItemTypes": [
        "Plastic_Explosive", // List of items to log the count of (saved into the profile/Zenarchist/Logs folder)
        "ExpansionSatchel"
    ],
    "ShouldLogRaids": 0, // If enabled, the mod will log player raid activity when ammo damage is detected on a Basebuilding object
    "RaidAmmo": [
        "ExpansionC4_Ammo", // A list of 'ammo types' to trigger the base raid logs
        "Plastic_Explosive_Ammo"
    ]
}

'Ghost Items' can occur when some mods don't handle hologram placement correctly. It's rare, but I've seen situations where sometimes there are dozens if not hundreds of objects spawned at 0 0 0 (vector.Zero) coordinates on my server due to bad hologram placement checks. Enabling ShouldDeleteGhostItems will delete any objects found at 0 0 0 and log them into the text logs for further investigation.

Performance Tracking

Setting CountServerFPS in ZenUtilities.json to 1 will enable performance tracking. Whenever the server's FPS dips below ServerFPSWarning any players driving cars will be notified of the increased risk of desync.

If CountServerFPS is set to zero performance analysis will be disabled.

If ServerFPSWarning is set to zero warnings will be disabled.

If performance monitoring is enabled and certain actions caused the server's FPS to drop X% according to ServerActionFPSDropWarningPct setting, an Error log will be printed flagging the action that caused the FPS drop. This is useful for optimizing actions which have a large negative impact on server performance (eg. too many GetObjectsAt() calls or excessive for loops etc).

PlayerMessageConfig.json

In the folder %server_profile/Zenarchist/Utilities/PlayerReportConfig.json you will find a file where you can send messages to players in-game when they login. You can also spawn items on them with this method. This file is reloaded every time a player logs in to keep it fresh and updated between server restarts.

This is a great way to communicate with players and compensate items for them/spawn event gear on them etc without needing to be online as an admin. All you need is their Bohemia UID or SteamID and a list of items to spawn. A default config is generated in this folder so you can see how to spawn items.

A Bohemia ID looks something like this: 4s_12UDE-PKYemc7adlZyKGVSrwzIMW0T69Q39CerkE=

It's basically a private encrypted version of a player's SteamID and BattlEye ID and whenever a player logs in to the server their UID will be printed to the server logs along with their steam profile name. It's recommended to use this wherever possible to ensure the player's privacy, but if you can't find their UID or the player gives you their SteamID you can use that as the BohemiaID as well and it will work the same way.

If you have server logs enabled, whenever a player dies their entire inventory will also be printed to the server logs in such a way that they can be copy & pasted directly into this config. It helps with compensating players who died to bugs, hackers, server crashes/lag etc much faster than spawning in their gear one by one. It also tracks each item's health and quantity to keep the compensation fair.

You can find the PVP/player death logs in %server_profile/Zenarchist/Logs/TODAYS_DATE/ZenMod_pvp.log. You can use a tool like Agent Ransack to search this file for the player's name or UID if needed as often there will be a lot of info logged there.

The config for spawning items is simple, just add them to the SpawnItems list (check the example config) - there are 3 options:

"Classname" "Classname(quantity)" "Classname(health/quantity)"

If it's an item like a gun you can just use the "Classname" option, if you want to spawn a pristine item with quantity set you can just use "Classname(23)" to spawn 23x the item, to spawn an item with health and quantity set use "Classname(health/quantity)".

Here is an example config:

{
    "PlayerReplies": [
        {
            "BohemiaID": "4s_12UDE-PKYemc7adlZyKGVSrwzIMW0T69Q39CerkE=",
            "Message": "Sorry for that last server crash deleting your stash of 69 nails and fully geared SVD. You'll find them respawned underneath you.",
            "SpawnItems": [
                "Nail(69)",
                "SVD",
                "Mag_SVD_10Rnd(100)",
                "PSO11Optic",
                "Battery9V(100)"
            ]
        }
    ]
}

Poll.json Config

This mod comes with a rudimentary poll feature where you can ask players up to select up to 6 options and submit them.

There is limited GUI functionality, all of the data is saved to JSON and you have to interpret the results there as an admin.

The config is located in %profiles%/Zenarchist/Utilities/Poll.json

If you enable a poll it will popup whenever a player logs in, until they select and submit an option, and then it will no longer display to that player. The players cannot see the results, only the admin can by viewing the JSON file.

Here is the default config:

{
    "CONFIG_VERSION": "1", // Don't touch
    "PollID": -1, // Set to -1 to disable, 1 = new poll, 2 = new poll and reset old poll data etc.
    "PollTitle": "This is an example poll", // Poll GUI title
    "PollSubtitle": "More explanation in the smaller subtitle", // Poll explanation
    "OnlyOneOption": 1, // Set to 0 to enable multiple selections, otherwise 1 means only 1 option allowed
    "Option1": "Test poll", // Option 1, 2, 3 etc
    "Option2": "Two options",
    "Option3": "Three options",
    "Option4": "",
    "Option5": "",
    "Option6": "",
    "XXXXXXX": "POLL RESULTS:", // Purely for admin reading purposes 
    "TotalVotes": 0, // Vote count
    "RESULTS": [], // This will display the winning vote option(s)
    "PlayerChoices": {}, // Saves/stores player selections for the current poll
    "LastPollID": -1 // Don't touch - for the mod to detect a new poll change and wipe data
}

ZenFunctions.c

For you modders out there who want to build on this modpack, there are some useful functions located in ZenFunctions.c under ZenModPack/scripts/4_World/Classes/ZenMods/ZenFunctions.

There's some brief explanations included in that file of what the functions in there do - such as orientating an entity to face a vector position (thanks ChatGPT), sending chat messages via server and/or client for debugging, getting the camera angle, aligning entities to the terrain beneath them and a few other features.

There is also a sneaky feature under ActionBase.c which allows you to set a display priority for actions. For example, on my server you can skin zombies and also search their inventory. The skin action was given priority over the search action since it's a vanilla action (skinning), which was annoying because most players search zombies far more often than skinning them.

So use the override int Zen_GetDisplayPriority() function on Actions and return an int higher than 0 to force that action to display first. The action with the highest priority value will always display first.

Miscellaneous Info

There are a bunch of random miscellaneous tools spread throughout the mod, many of which I'm sure I'll forget to mention so poke around if you're curious.

One useful feature that comes to mind is the persistent Player UID system.

PlayerBase.c| int GetZenPlayerUID()

PlayerBase.c| PlayerBase GetPlayerByZenUID(int id)

My mod syncs a unique player ID to all players on the server both client-side and server-side which makes it possible to track which player did what between the client and server. The UID is unique to each player and is "cached" so that if the player disconnects and reconnects they retain the same UID.

For example, I use my int GetZenPlayerUID() function in PlayerBase.c on my PVE server to prevent players from picking up an item within 2 minutes of dropping it unless their UID matches the player which dropped the item (ie. they are the one who dropped it).

This stops players stealing items from other players if someone drops an item briefly, and if a player drops an item and logs out and back in then their UID will sync to the client so they can still pick up their own dropped items before the 2-minute time-out.

This UID is also used in the functionality of my Anti-Combat Logout mod.

Master Config

To disable my custom server logs set "ZenModLogger": 0 in %server_profile/Zenarchist/ZenModPackConfig.json

⚠️ **GitHub.com Fallback** ⚠️