Skip to content

Releases: Nextinel/Roblox_Framework

Nextinel Builder & Type Safety

Choose a tag to compare

@Nextinel Nextinel released this 19 Oct 14:24
f8131bf

Added

  • Nextinel Builder Plugin: Auto-generates folder structure and typed boilerplate modules. Download here
  • Full Type Support: Added Types.ServerModule and Types.ClientModule. You can now use :: Types.ServerModule for full IntelliSense on lifecycle hooks

Improved

  • Error Tracebacks: Switched from pcall to xpcall across the entire framework. When an error occurs in any hook (not just init), the stack trace is filtered to remove internal framework calls. You now see exactly which line in your module caused the crash
  • Logger: Cleaned up internal warnings and added better filtering for stack traces

Notes

  • No breaking changes. Existing modules work as-is
  • Highly recommend updating to get the new Plugin and Type safety features

HangWatcher, Priorities & Profile Methods

Choose a tag to compare

@Nextinel Nextinel released this 13 Oct 02:28
78399cf

Added

  • HangWatcher - warns if a module's init takes longer than 10 seconds. Configurable per module with skipHangWatch = true
  • Priorities - control init order with priority = -1 (lower = earlier). Dependencies always take precedence over priority
  • Profile methods:
    • profile:decrease(key, delta) / profile:decreaseAt(path, key, delta) - shorthand for negative add
    • profile:observe(key, callback) / profile:observe(path, key, callback) - subscribe to field changes. Only number, string, boolean types are supported. Triggers only on :add(), :addAt(), :set(), :setAt(), :decrease(), :decreaseAt()
    • profile:addAt(path, key, delta) / profile:setAt(path, key, value) - modify nested fields without leaving the Data table
  • DataStoreService functions:
    • .tryGetProfile(player) - non-yielding, returns nil if not loaded
    • .awaitProfile(player) - explicit yielding alias of .getProfile(player)
    • .getProfiles() - returns all loaded profiles
  • skipHangWatch - per-module field to disable hang warnings
  • shouldCheckExtrafields - optional flag in network table for the validator. Default is true. Set to false to allow extra fields in the payload

Fixed

  • DependencyResolver now uses Kahn's algorithm with priority as a tie-breaker

Notes

  • asyncInit runs in parallel via task.spawn and is not affected by priority or dependency order
  • No breaking changes. Existing modules work as-is

Demo

Try it: Wave Survival (Download) - a small showcase of Nextinel in action. Covers networking, module lifecycle, profiles, and data saving

Examples

HangWatcher

-- This module's init takes 15s -> HangWatcher warns after 10s
return {
    init = function()
        task.wait(15)
    end,
}

-- This module disables the warning
return {
    skipHangWatch = true,
    init = function()
        task.wait(15)
    end,
}

Priorities

-- Module: DataLoader
return {
    priority = -100, -- runs before everything else
    init = function() end,
}

-- Module: UI
return {
    priority = 100, -- runs last
    init = function() end,
}

Profile methods

local profile = dataStoreService:getProfile(plr)

-- top-level observe
local disconnectTop = profile:observe("Coins", function(new, old)
    print(`Coins: {old} -> {new}`)
end)

-- nested observe
local disconnectNested = profile:observe("values/entry1", "CurrencyName", function(new, old)
    print(`values.entry1.CurrencyName: {old} -> {new}`)
end)

-- nested add/set
profile:addAt("values/entry1", "CurrencyName", 50)
profile:setAt("values/entry1", "CurrencyName", 100)

-- shorthand
profile:decrease("Coins", 10) -- same as :add("Coins", -10)
profile:decreaseAt("values/entry1", "CurrencyName", 5)

-- unsubscribe
disconnectTop()
disconnectNested()

DataStoreService methods

-- non-yielding, returns nil if not loaded yet
local profile = dataStoreService:tryGetProfile(plr)
if profile then
    profile:add("Coins", 1)
end

-- explicit yielding
local profile = dataStoreService:awaitProfile(plr)

-- iterate over all loaded profiles
for plr, profile in dataStoreService:getProfiles() do
    profile:add("Coins", 10)
end

DataStore Module Rework

Choose a tag to compare

@Nextinel Nextinel released this 10 Oct 15:45
9f5eb47

Breaking Changes

  • Now you can get profile type from dataStoreService.profile (exported type)
  • Reworked methods: profile:add(key, delta) and profile:set(key, value) instead of dataStoreService.add(player, key, delta) and dataStoreService.set(player, key, value)
  • Added paths for IN_PLAYER entries instead of parent
  • getProfile(player) now returns a wrapped profile object, not profile.Data. Access raw data via profile.Data.<key> or use profile:add() / profile:set()
  • And a few little fixes

Examples

Before:

local dataStoreService = require("./../Global/DataStoreService")

return {
	update = function()
		for _, plr in game:GetService("Players"):GetPlayers() do
			local profile = dataStoreService.getProfile(plr)
			
			if not profile then continue end
			
			profile.Coins += 1
			dataStoreService.updateData(plr) -- to update leaderstats and other folders in player Instance
		end
	end,
	
	playerDataLoaded = function(plr: Player, profile: any)
		dataStoreService.set(plr, "Coins", 100)
		
		dataStoreService.add(plr, "Coins", math.random(-100, 100))
	end,
}

After:

local dataStoreService = require("./../Global/DataStoreService")

return {
	update = function()
		for _, plr in game:GetService("Players"):GetPlayers() do
			local profile = dataStoreService.getProfile(plr)
			
			if not profile then continue end
			
			profile.Data.Coins += 1
			profile:updateFolders() -- to update leaderstats and other folders in player Instance
		end
	end,
	
	playerDataLoaded = function(plr: Player, profile: dataStoreService.profile)
		profile:set("Coins", 100)
		
		profile:add("Coins", math.random(-100, 100))
	end,
}

Logger & Types

Choose a tag to compare

@Nextinel Nextinel released this 09 Oct 22:30
9f5eb47

New Shared Modules in ReplicatedStorage

  • Logger - logger.register(src), this:info(), this:warn(), this:error()
  • Types - Shared type definitions for Client and Server modules

Notes

No breaking changes. Existing code continues to work as-is

Network changes

Choose a tag to compare

@Nextinel Nextinel released this 09 Oct 10:03
d4ccdeb

Breaking changes:

  • network.remote -> network.channel
  • setupFireServer.remoteNames -> setupFireServer.channelsNames
  • Removed Remotes Folder in ReplicatedStorage
  • Network now uses Jolt (bundled with the framework at ReplicatedStorage.Modules.Global.Jolt)

Not changed:

  • contract
  • onEvent

How to use on server

Instead of getting remotes from Remotes Folder, now Jolt module is required to fire client:

local replicatedStorage = game:GetService("ReplicatedStorage")

local jolt = require(replicatedStorage.Modules.Global.Jolt)

local inventoryChannel = jolt.Server("Inventory")

return {
	playerAdded = function(player)
		-- Fire to a specific player (server -> client)
		inventoryChannel:Fire(player, "hello", 123)
	end,
	
	update = function(dt)
		-- Fire to all clients
		inventoryChannel:FireAll("tick", dt)
	end,
}

Initial release

Choose a tag to compare

@Nextinel Nextinel released this 08 Oct 17:50
7b626be

Structure

  • ReplicatedStorage
    • Assets
    • Modules
    • Remotes
    • HUD
  • ServerScriptService
    • Modules
    • Server
  • StarterPlayerScripts
    • Client

Modules folder branch

  • Global
  • Initialize

Features

  • Network Handlers - Client & server handlers with built-in rate limits and validators
  • Loading Screen - Built-in loading screen
  • DataStoreService - Module with Migrator, built on ProfileStore
  • Version - Built-in version checker that checks for updates on server start