also thats odd why wouldnt it use inputs, it sounds much safer and framerate wouldnt affect it if you use delta time, not like i know much about server authoritative movement yet, so maybe im just being stupid by saying this.
It does use inputs for commands
that was a quick reply, anyways happy new year hope everyone is having fun right now.
Iâll probably consider using this (if i get it and player choice rigs (user deciding r6/r15) working) on games where movement isnât a major factor, I wouldnât suggest using server-authorative physics things in any game with many players and/or intensive movement, or if you just expect players to have terrible connections regardless.
Oh dont worry about the connection issues it runs fine, in fact its so good at handling bad pings that intense âpullâ rollbacks almost never happen.
Will this support terrain water?
Also following to this I finally understood what MrChickenRocket was trying to tell me.
He meant predicting if we were gonna keep charging not when we were gonna charge
I have taken a look more indepth into various things inside chickynoid I stumbled into Projectile Sniper module script and while im still extremely confused about commands I think ill eventually get the hang of it, So far I know you can use the bitbuffer module to compress the packets from what I saw and send them over via commands although while checking the generate command module I saw that you need to hardcode commands which is a bit inconvinient but it works I guess.
I also discovered another solution that could be implemented using the antilag module inside chickynoid for compensating charge mechanics based on these diagrams, I will keep reading more how chickynoid does its cooldowns and more to learn if this is the correct solution or not.
Following to this heres the thing im working on for chickynoid
So I was like trying to implement âCommandsâ for chickynoid for my game actions (Blocking,Jabing,Charging,Shoving, etc.)
So after like 1 week of trying my hardest to understand chickynoidâs innerworkings I found out how commands tick!
Commands are part of the âGenerateCommandâ mod, these are by deffault sent every frame chickynoid takes to the server and will get the inputs on that momment.
Problem is they are hardcoded and hard to add as :GenerateCommand() function is responsable for generating the final command sent to the server which is later picked up by :Heartbeat() and passed to the server, So theres really not an easy way to add your own commands to be sent to the server witjout forking and tampering with chickynoid
So I made this modiffication which I think works fine, right now im focussing on constructing commands, ill later focuss on Processing commands on the client so they also run client actions before they are sent to the server just how the :ProcessCommand() function does.
The moddification goes inside Heartbeat and the reason for that is uhh I dont actually have a reason i think it would have been better inside :GenerateCommand() but I forgot why
Heres part of the module that makes the commands get attached to the main command and also handles OOP creation of commands
This is pretty barebones and its missing stuff like the ProcessServerCommand function which takes charge of receieving the commands on the server checking what they have and running the respected functions assigned to these commands so they can run the server code for whatever we need.
Anyways that was my cool uhh project that im working on, If anyone knows a better way to do what I am doing feel free to tell me im just a dumb person trying to make a game with chickynoid!
You didnât need to do that, these lines already allow you to add onto the command.
You are kidding me right, sigh I really am an idiot adding things that were already made
There goes my afternoon
How could I have missed that IT WAS LITERALLY THERE!
Anyways thank you for showing me how it was actually made.
I think I am no longer an idiot and did it right this time!
wrote this simple mod which basicly allows you to add data to a table which then is sent as commands, the reason for this is because I want any script to at any point be able to create commands and be able to also remove commands
For example I have an OOP tool/inventory system, I make a class for it called melee, as soon as the equip function for my system is called on the client, we create the actions for the things we can perform (Block,Charge,Hit,Shove,Inspect) which starts sending commands to the server with the states of said actions. When we are done using our melee and we unequip it we can get rid of these actions so we stop wasting bandwith sending useless data to the server.
I guess ill test how this thing i made works and try to use the bitbuffer module for data that cannot be predicted, as for the input data to the server ill use something similar like enums just how MrChickenRocket did it that way the server already knows what the numbers sent mean.
Working on something big for chickynoid that I plan to release to the public which will facilitate a lot the developement for games on chickynoid.
Its Custom Tools for chickynoid, Chickynoid does not support roblox tools for obvious reasons, so I am writing a mod called InventoryMod, which allows chickynoids to have custom inventories that can hold different objects, It also already comes bundled with an object class called CTool (CitrusTool).
Citrus Tools imitate as much as possible the behavior of roblox tools via chickynoid and are split into different components to make its modification as easy as possible so you can adjust them to work into your game, I also plan to make them work instead of via input events via using a :ProcessCommand() function locally and on ServerSide so they work similar to the already existing weapons mod, and they also support rollback functions the user can code in, In case whatever you are coding desyncs from the server or needs to be controlled from the server, Such as unequipping an users tool.
Heres the way the Client sided components are built, keep in mind they are a rewrite of an older system I made so rn im just kinda rebuilding it and then modifying to work with chickynoid, Networking has not been done yet because I need to add a lot of things.
ClientInventoryMod
local module = {}
module.Objects = {}
module.InventoryRecords = {}
function module:Setup(client)
-- Get all of our different Objects
for i,v in pairs(script:GetChildren()) do
if v:IsA("ModuleScript") then
-- Setup and add our objects to the module's table
local Contents = require(v)
Contents:Setup()
self.Objects[v.Name] = v
end
end
end
function module:Step(client, _deltaTime)
end
return module
CTool
-- Custom tools (CTool) mod!
local CTool = {}
-- Services
local Players = game:GetService("Players")
local StarterGui = game:GetService("StarterGui")
local ReplicatedFirst = game:GetService("ReplicatedFirst")
local LocalPlayer = Players.LocalPlayer
local FastSignal = require(ReplicatedFirst.Packages.Chickynoid.Vendor.FastSignal)
CTool.__index = CTool
CTool.ClassName = "CTool"
CTool.Classes = {}
CTool.IsSetup = false
CTool.ToolIDCounter = 0
CTool.InventoryRecords = {}
CTool.InventoryRecords.Server = {}
-- Events
CTool.OnCToolOwnershipToLocalPlayer = FastSignal.new()
CTool.OnCToolRemovedFromLocalPlayer = FastSignal.new()
CTool.OnCToolEquipped = FastSignal.new()
CTool.OnCToolUnequipped = FastSignal.new()
-- Client Only thing
CTool.InputHandler = nil
-- Constructor function for CTool Object
function CTool.new()
local self = setmetatable({
ID = CTool.ToolIDCounter,
Owner = nil,
IsEquipped = false,
ClassName = CTool.ClassName,
Origin = "Client",
-- Change this when making a new class
CToolClass = CTool.ClassName,
}, CTool)
-- Store our Object inside the Records so we can find it
CTool.InventoryRecords[self.ID] = self
-- Update the ID counter
CTool.InventoryRecords += 1
return self
end
-- Sets a CTool's Owner to the given Player
function CTool:SetOwner(Player)
if CTool.InventoryRecords[Player.UserId] then
self.Owner = Player
CTool.InventoryRecords[Player.UserId].Backpack[self.ID] = self
-- Run exclusive code to the Local Player
if Player == LocalPlayer then
CTool.OnCToolOwnershipToLocalPlayer:Fire(self)
end
else
warn("Inventory not found")
end
end
-- Unequips tool and runs class code
function CTool:Unequip()
if self.IsEquipped == true then
local Inventory = CTool.InventoryRecord[self.Owner.UserId]
local ClassFunctions = require(script[self.ClassName])
-- run it's class code
self:UnequipClass()
self.IsEquipped = false
Inventory.Hand = nil
-- Fire the local events for the input handler
CTool.OnCToolUnequipped:Fire(self)
end
end
-- Equip tool and runs class code
function CTool:Equip()
if self.IsEquipped == false then
local Inventory = CTool.InventoryRecord[self.Owner.UserId]
local ClassFunctions = require(script[self.ClassName])
-- Check if tool is already equipped and unequip if so
if Inventory.Hand then
Inventory.Hand:Unequip()
end
self:EquipClass()
self.IsEquipped = true
Inventory.Hand = self
-- Fire the local events for the input handler
CTool.OnCToolEquipped:Fire(self)
end
end
-- Removes all traces of CTool object
function CTool:Destroy()
-- Check if it has an owner to remove it from backpack and hand
if self.Owner then
local Inventory = CTool.InventoryRecords[self.Owner.UserId]
if self.IsEquipped == true then
self:Unequip()
end
Inventory.Backpack[self.ID] = nil
end
-- Fire local events for the input handler
CTool.OnCToolRemovedFromLocalPlayer:Fire(self)
self = nil
return self
end
-- Sets up all the necesary code to make the object class fully work
function CTool:Setup()
print("RAN")
if CTool.IsSetup == false then
-- Hide roblox's deffault inventory Gui
StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
-- Setup all other Classes of CTool
for i,v in pairs(script:GetChildren()) do
if v:IsA("ModuleScript") then
local Class = require(v)
Class:Setup()
-- Detect if this is the Module in charge of controlling CTools, if it is then its not a class
if Class.InputHandler then
CTool.InputHandler = Class
else
print(v.Name)
CTool.Classes[Class.ClassName] = Class
end
end
end
end
end
return CTool
InputHandler component
local InputHandler = {}
-- Services
local ContextActionService = game:GetService("ContextActionService")
local Players = game:GetService("Players")
local CTool = require(script.Parent)
local LocalPlayer = Players.LocalPlayer
InputHandler.InputHandler = true
-- idk load things
InputHandler.Assets = script.Assets
InputHandler.Hotbar = {}
InputHandler.HotbarSlotsInUse = 0
-- Settings
InputHandler.Settings = {}
InputHandler.Settings.Keybinds = {
[1] = Enum.KeyCode.One,
[2] = Enum.KeyCode.Two,
[3] = Enum.KeyCode.Three,
[4] = Enum.KeyCode.Four,
[5] = Enum.KeyCode.Five,
[6] = Enum.KeyCode.Six,
[7] = Enum.KeyCode.Seven,
[8] = Enum.KeyCode.Eight,
[9] = Enum.KeyCode.Nine,
[10] = Enum.KeyCode.Zero
}
InputHandler.Settings.MaxHotbarSlots = 10 -- This value should not be higher than 10
InputHandler.GUI = nil
-- Setup everything so we can start controlling the CTools
function InputHandler:Setup()
-- Load the Gui
self.GUI = self.Assets.ToolBar:Clone()
self.GUI.Parent = LocalPlayer.PlayerGui
-- Create the function in charge of handling all of our keypresses
local function ActionHandler(Action,InputState,InputObject)
if InputState == Enum.UserInputState.Begin then
local ID = tonumber(Action)
local CToolSelected = CTool.InventoryRecords[LocalPlayer.UserId].Backpack[ID]
if CToolSelected.IsEquipped == true then
CToolSelected:Unequip()
else
CToolSelected:Equip()
end
end
end
-- Connect events
CTool.OnCToolOwnershipToLocalPlayer:Connect(function(OwnedCTool)
-- Create our GUI for the Toolbar
local NewToolFrame = self.GUI.ToolFrame:Clone()
NewToolFrame.Name = OwnedCTool.ID
NewToolFrame.NameLabel.Text = OwnedCTool.Name
NewToolFrame.Visible = true
-- Set up CTool inside a local hotbar slot
if self.HotbarSlotsInUse <= self.Settings.MaxHotbarSlots then
self.HotbarSlotsInUse += 1
NewToolFrame.Parent = self.GUI.Hotbar
for Slot = 1, self.MaxHotbarSlots,1 do
if not self.Hotbar[Slot] then
self.Hotbar[Slot] = OwnedCTool.ID
NewToolFrame.NumberLabel.Text = Slot
ContextActionService:BindAction(OwnedCTool.ID, ActionHandler,false, self.Keybinds[Slot])
break
end
end
else
NewToolFrame.Parent = self.GUI.InventoryMenu
end
end)
CTool.OnCToolRemovedFromLocalPlayer:Connect(function(CToolID)
-- Removes the GUI Frame for the CTool, from the hotbar/Toolbar GUI
self.GUI.HotBar[tostring(CToolID)]:Destroy()
-- Clears the hotbar slot which references the CTool ID
for Slot = 1, self.Settings.MaxHotBarSlots,1 do
if self.HotBar[Slot] then
ContextActionService:UnbindAction(CToolID)
self.HotBar[Slot] = nil
end
end
end)
CTool.OnCToolEquipped:Connect(function(EquippedCTool)
-- Show the GUI effects
self.GUI.HotBar[EquippedCTool.ID].Outline.Visible = true
end)
CTool.OnCToolUnequipped:Connect(function(EquippedCTool)
-- Show the GUI effects
self.GUI.HotBar[EquippedCTool.ID].Outline.Visible = false
end)
end
return InputHandler
Ill publish it as a resource once its fully ready, Let me know what you guys think!
Very cool, but I donât see this becoming the next best character replacement due to the fact thereâs a ton, I mean a ton of bugâs in the system not to mention this in its self is a bad idea,
Youâre making two objective claims without explanation or evidence:
What kind of deal-breaking bugs are there in the system?
Why is a server-authoritative character controller a bad idea? I think itâs a really clever solution.
Currently, in most games, the playerâs character is owned by the client. Itâs an easy solution, but very exploitable.
The idea of Chickynoid is to let the server own the character. By using deterministic movement code, the client can provide an input and run the outcome before the server can respond and come to the same solution. So, input lag is minimal and the security is bulletproof.
Of course, it requires a lot of development since the entire character controller is being written from scratch. But once this is production-ready or if Roblox takes attention, character-based exploits are practically ineffective.
tl;dr: Chickynoid is not an anti-exploit. It does not respond reactively to abuse at the edge. Instead, it solves the problem at the root.
I have been using it for developement and have not found any issues that are game breaking or anything, the maximum I found was the fast delta time exploit to slightly give players a higher jump boost (its like very minimal).
Also saying this is a bad idea is a bit silly considering all triple A titles out there you see use this solution already.
The mod has been released as an alpha, and I think its on a semi stable state, and also utilizes chickynoid features and works with mods!
Make sure to check it out if you are interested in learning about writing mods for chickynoid or wanna learn how to make simple networking with it, or you are just looking for an inventory system for chickynoid.
does it work for R6? because I only found R15 examples
Yes it does!
Get an R6 rig and name it to âR15Rigâ then simply use it to replace the one located on here
Then go into the CharacterModel module script and make sure to have the hip set to this or your preference for your R6 rig to not be clipping into the ground
Make sure to put all your deffault animations inside the Rigâs humanoidâs animator as animation instances with these names
Simple as that!
Thank you for writing that up! You should submit it as a documentation PR
Is this still under development? The last update to the GitHub was 4 months ago.