Replicating Abilites Functions from Client to Server

Question: Is there a way you can implement different character abilities running on the client-to-server without using too many RemoteEvents? How could I improve the following code I have below?

Here is how my current format for my code is currently looking like. Assume that some of the following that look like is missing is already included. Also assume I have some kind of anticheat that will deny player’s from abusing RemoteEvents.

-- Local Script 

-- The local script is in charge of player's keybind and hit detection that requires to be instant.
if UserInput at 'E' keybind then
     if playerClass == "projectile" then
          -- cast projectile physics
          RemoteEvents.CreateProjectile:FireServer(projectileName, "playerProjectile")
          RemoteEvents.CastProjectile:FireServer(physicProperties)
          if touch projectile then
               RemoteEvents.DealDamage:FireServer()
          end
     elseif playerClass == "laserbeam" then
          -- cast hitscan
          RemoteEvents.CreateProjectile:FireServer()
     elseif etc... then
          -- etc...
     end
end

-- Server Script

-- This script is in charge of all the remote events that happens from clientToServer.
RemoteEvents.CreateProjectile:OnServerEvent(function(instance, name)
     -- Make projectile under name
end)

RemoteEvents.CastProjectile:OnServerEvent(function()
     -- local projectile = Look for a projectile made by CreateProjectile
     -- castProjectile similarly to client
end)

RemoteEvents.DealDamage:OnServerEvent(function()
     -- Apply damage
end)

This is a summary of what my code looks like. Here is what my RemoteEvent looks like. I am planning to put these remote events into their according to usage (ie. clientToServer Folder, serverToClient Folder)
image
This will for sure be growing into an unmanageable size later on the more I add more classes. To restate, I am asking if there is a better way to organize this so it will become manageable. Some things I am currently doing is finding similarities where I can combine certain RemoteEvents into one, but not all can be combined.

There are a few ways to improve the organization and reduce the number of RemoteEvents in your code. Here are a few suggestions:

  1. Use a dictionary to map playerClass to the appropriate functions on the server.
  2. Use a table of tables to group related actions.

Instead of having a separate RemoteEvent for each playerClass, you can use a dictionary on the server to map each playerClass to the appropriate function that handles the player’s action. For example:

local classFunctions = {
    projectile = function(player, projectileName, physicProperties)
        -- handle projectile action
    end,
    laserbeam = function(player)
        -- handle laserbeam action
    end,
    -- add more classes and functions as needed
}

RemoteEvents.PlayerAction.OnServerEvent:Connect(function(player, class, ...)
    local action = classFunctions[class]
    if action then
        action(player, ...)
    else
        warn("Invalid playerClass:", class)
    end
end)

On the client side, you can simplify the code to just send the player’s class and the arguments to the server:

if UserInput at 'E' keybind then
    RemoteEvents.PlayerAction:FireServer(playerClass, projectileName, physicProperties)
end

Instead of having separate RemoteEvents for each action, you can group related actions into tables and send the action name as an argument to a single RemoteEvent. For example:

local actions = {
    projectile = {
        create = function(player, projectileName)
            -- create projectile
        end,
        cast = function(player, physicProperties)
            -- cast projectile
        end,
        hit = function(player)
            -- deal damage
        end,
    },
    laserbeam = {
        create = function(player)
            -- create laserbeam
        end,
        cast = function(player)
            -- cast laserbeam
        end,
        -- add more actions as needed
    },
    -- add more playerClasses as needed
}

RemoteEvents.PlayerAction.OnServerEvent:Connect(function(player, class, action, ...)
    local classActions = actions[class]
    if classActions then
        local func = classActions[action]
        if func then
            func(player, ...)
        else
            warn("Invalid action:", action)
        end
    else
        warn("Invalid playerClass:", class)
    end
end)

On the client side, you can send the player’s class, action name, and arguments to the server:

if UserInput at 'E' keybind then
    RemoteEvents.PlayerAction:FireServer(playerClass, "cast", physicProperties)
end

There really are a number of ways to do this. I suggest looking into design patterns and system architecture. I wrote a number of articles on the subject on the forums. Feel free to take a look.

3 Likes