ZEN - Minimal Server Core (v0.1.0)

ZEN - Zero Extra Nonsense

ZEN is intentionally minimal.
If you want a full city out of the box, this isn’t it.
If you want a stable foundation to build your own, welcome aboard.

GitHub

Documentation


TL;DR

ZEN is a minimal, modular server core built to give each player a clean, isolated Lua object.
No extra bloat, no forced features, just a solid foundation you fully control.

  • Class-based player objects with private state
  • Extensions for modular features
  • Explicit data replication to clients
  • No built-in jobs or inventory—build only what you need

Perfect if you want full control and a lightweight, memory-safe core.


Overview

ZEN is a minimal server core.
It’s not a roleplay kit, it’s not a city template, and it’s not a collection of thrown together bloat.

It’s a core built around one principle: Only build what you need.

  • No hardcoded jobs.
  • No baked-in inventories.
  • No spaghetti dependencies to untangle.

Just a clean, memory-safe core that gives every player their own scoped Lua object, created on join, destroyed on leave, and isolated the entire time.

You get full control.
You write the extensions.
You decide what loads.
You don’t fight the core.
ZEN lets you start clean and stay clean.


Why This Exists

Because sometimes you just want to build what you need and nothing else.
Every other core ships with someone else’s idea of what a server should be.

ZEN was built to fix that.

If you want a full RP city, you can build it.
If you want a lightweight minigame server with just names and ranks, you can build that too.
The only limit here is you.


Core Concepts

Class-Based Player Objects

Every player gets their own Player object, created with Player.new(source).
It exists for the entire sessions and handles:

  • Private state: internal memory, fully encapsulated
  • Public data: accessible, dynamic, and optionally replicated
  • Extensions: modular logic injected per player
  • Lifecycle: load, save, and unload events
  • Runtime methods: logic attached at runtime

No shared buckets. No mystery data. Just a clean object per player.

Weak-Keyed Private Memory

Internal state is stored using:

Private = setmetatable({}, { __mode = "k" })

Which means:

  • Memory cleans itself up when the object is gone
  • Private data stays private not exposed or leaked
  • You never have to think about manual cleanup

No ghosts. No leaks. No surprises.

Modular Extensions

Extensions are fully optional components that hook into each player.

They can:

  • Register lifecycle logic (on_load, on_save, on_unload)
  • Inject new methods
  • Store their own isolated data

Extensions don’t talk to each other.
They don’t break each other.
And they don’t require some central config file from 2019.

Load one. Load five. Or load nothing. It still works.


Lifecycle

Function Description
Player.new(source) Creates a new player object for a source
:load() Triggers all extension on_load hooks and syncs data
:save() Triggers all on_save hooks and fires save event
:unload() Triggers all on_unload hooks and cleans up memory
:has_loaded() Returns whether the player has completed :load()

Data

Function Description
:add_data(key, value, replicate) Adds new data under a category (optionally replicated)
:get_data(key) Gets a specific category or all data
:set_data(key, updates, sync) Updates an existing data table and optionally syncs
:remove_data(key) Deletes a category and syncs its removal
:has_data(key) Checks if the category exists
:sync_data(key?) Sends replicated data to the client
:update_user_data(tbl) Updates persistent graft user data safely

Extensions

Function Description
:add_extension(name, ext) Attaches a new extension instance to the player
:get_extension(name) Returns an attached extension
:has_extension(name) Checks if an extension is present
:list_extensions() Returns a list of loaded extension names

Lifecycle hooks that extensions can define:

  • on_load(self)
  • on_save(self)
  • on_unload(self)

All are triggered automatically via lifecycle events.


Methods

Function Description
:add_method(name, fn) Adds a named method callable on this player object
:remove_method(name) Removes a method by name
:run_method(name, ...) Runs a method if it exists, passing the player as first arg
:has_method(name) Returns whether a method exists
:get_method(name) Returns the function reference if defined

Extensions use this to inject flexible logic without needing to touch the core files.


Debug

Function Description
:dump_data() Logs the player’s full public dataset

Design Principles

  • Each player gets a real Lua object (Player.new(source)), not a shared table
  • All player state is encapsulated no external table mutation allowed
  • Private memory is weak-keyed and auto-released on disconnect
  • Systems are written as extensions, not crammed into the core
  • You choose what data to replicate clients only get what you send
  • Globals are intentional, static, and scoped. No bleed, no magic

Summary

ZEN is a clean, class-based server core.

It doesn’t decide what your server is, it just gives you a secure, scalable foundation to build on.

You control what gets added.
You control what gets saved.
You control what gets synced.

ZEN just handles the structure.
You handle the systems.


Screenshots

Nothing really to screenshot? It’s just a core so have some code shots?

Folder Structure


Example Module


Support

Need help or found a bug?

Join the PIT Discord and shout your issues: https://discord.gg/MUckUyS5Kq

Support Hours: Mon–Fri, 10AM–10PM GMT
Bring your config file. And a shovel.

10 Likes

Can you finish your moneywash script?

It has not been fixed since the release. What version of boii_utils I need to use the script?

First im hearing of it not working? :sweat_smile:
Drop a post in discord support section or a ticket with whats not working and if its not ill get a fix out. Working through all the old boii stuff and moving to pit and my new lib currently anyway.

And it should be on 2.0+ utils i think? been a while (again will be moved to my new one asap)

I can bet 100$ you have the worse discord support. It times me out if I tag you? Are you there to provide support or be arrogant enough to timeout someone for asking for help. (you = your bot which you hide behind).

You “think”?
Is it rational thing to say to someone who purchased your script?

This was told me more than 60 days ago. I was told to use “fivem_utils” (which does not exist anymore?)

I am just realizing I might be the only one who purchased it LOL. Must be easy to find who it belongs to because you have not updated it since March.

So fivem_utils to boi_utils (which does not work.) to now a new lib which I need to wait.

Great support 10/10. (sarcasm ofc.)

Nvm, dont bother fixing it. I just happened to wonder upon your name and felt bad I wasted like 100EUR or something in broken scripts. Even the petty crimes were having issues.

2 Likes

So much anger for no reason :sweat_smile:

The bot timing out for @'ing staff members has been a thing since 2023? It’s there because discord helpers are voluntary, they help out as and when they can, people ping them out mainly for sup with free resources, this was annoying some of them, so it was added, its also one of the server rules, theres channels for everything plus tickets, there’s no need to be pinging anyone unless its necessary – Patience goes a long way.

Huh? It’s a honest answer :sweat_smile:
It was on my old lib, it was then moved to 2.0? i answered without checking? so yeh at the time of answering i did “think” 2.0?

Does exist? Still works, just was never continued with, for a variety of reasons.

Nah 20+ people have it, weirdly it works for them? Or at least I’ve not heard anything to the contrary (yet… source available, people fix things instead of reporting, common for people not to report something)

fivem_utils – works? always did was just moved back from keystone to boii as utils 2.0, which strangly… also works.
New libs already out (GRAFT) and half my catalogue has been moved over to it?

I mean? it is if you actually follow the correct procedure? Support posts / tickets do exist.
Sounds like you’ve joined @'ed someone got a time out then got mad about it tbh :sweat_smile:

And like I’ve said… raise any issues with any script in the correct channels and it will be dealt with? That’s how this works… you report a bug, I fix it :rofl:


Anyway, I’ll answer your random a-- rants even though this really is not the place for it… and ill just wait for you to actually put in a support post/ticket (you wont).

1 Like

The entitlement is WILD

Throwing you a star on git!

1 Like