Skip to content

Instantly share code, notes, and snippets.

@Life-In-Dev
Last active July 6, 2018 16:00
Show Gist options
  • Save Life-In-Dev/3decccf3c3d31112e7488f2a7eee0937 to your computer and use it in GitHub Desktop.
Save Life-In-Dev/3decccf3c3d31112e7488f2a7eee0937 to your computer and use it in GitHub Desktop.
A layman's guide on Filtering Enabled in Roblox.

Introduction

There have been many tutorials on Filtering Enabled, some misinterpreted and others that are outright wrong. It's often conveyed as some difficult task one must undergo. Oftentimes, people treat it as if it's a part of the language. I'm here to dismiss all these notions and provide a clear explanation on what it is.

Definition

Filtering Enabled (or Experimental Mode turned off) is essentially a setting used to indicate how the network architecture behaves, and the relationship between the client and server, specifically the authoritativeness of the server over the network architecture.

That's a lot of words! Lets go through them.

Network Architecture

A network architecture is pretty much the design of a network, and the specification for how nodes (usually machines) on the network communicate with one another.

Authority

Authority in a network means exactly what you think it's saying. It's referring to how one machine on the network has superiority over other network nodes. For example in a Filtering Enabled game, the server is authoritative of any changes the client makes. That is, the client cannot make any arbitrary changes and expect for them to be replicated (we'll go over what exactly this means later), and the server is in charge of any changes a client tries to make.

The specific network architecture that Roblox uses, along with pretty much any other game or even website is the Client Server Model.

The Client-Server Model

The Client-Server model is a networking model/architecture where each machine on the network is either a client or a server. There's often only one server, that usually maintains authority over the network. The rest of the machines are clients. The clients request information, which the server may choose to serve back and the server maintains the network. In the context of a Roblox game, each player's machine is a client and the game itself is hosted on the server. Changes made in the server are propagated or replicated to every client in the network.

Replication

You might've heard this term being thrown around in a discussion about Filtering Enabled. Replication is essentially the, well replication or "duplication" of data. In a Roblox game, if the client attempts to instantiate a part in workspace in an environment with FE off, that change is sent to the server, verified because the server in this case is not authoritative of any changes, and the change is replicated to every other client. In a game with FE on, once the request hits the server, it "denies" the change and doesn't replicate to the other clients. Remember, an authoritative server always has the choice to deny a request if need be (we'll talk more about this later).

Too much theory, when can we actually apply this? Let's talk about the various APIs that Roblox offers.

Remote Events

Remote Events allow communication between the server and clients. If a developer needs a change to be replicated in some form, they can make use of Remote Events which'll simply send information to the server. Note that that's all Remote Events do, send information. It's up to you, the developer, to design and write out the listener functions and their respective function signatures (a function signature is essentially defines the parameters and return type of a function).

Remote Event API

Allows communication between the server and client in the form of an event which one can Fire and Listen to, homogeneous with typical events.

Methods

FireClient(Player player, ... arguments)

Description Fires an event signal to the specified player, with an arbitrary number of arguments.

Sample Call

RemoteEvent:FireClient(game.Players.LifeInDevelopment, "foobar", 10)

FireServer has similar functionality, except that it must be invoked from a local script and the player is ommitted from the function call arguments (not the function parameters) to avoid spoofing.

Events

RBXScriptSignal OnServerEvent(Player player, ... arguments)

Description RBXScriptSignal which is fired from a client. The listener parameter contains the player who fired the event, and an arbitrary number of arguments.

Sample

-- Server script
RemoteEvent.OnServerEvent:Connect(function(player, message, coolNumber)
  -- ...
end)

-- Local script
RemoteEvent:FireServer("bar", 21) -- Remember that the player argument is implicit and should not be passed.

OnClientEvent has similar functionality, except that it doesn't take the player as an argument (obviously) and the signal must be listened to on a client and fired from the server.

Remote Functions

Remote Functions are very similar to Remote Events, except that you can return an arbitrary value in the callback and the script that invoked the Remote Function yields until it gets a response.

Remote Function API

Also allows communication between the server and client, a return value and the script that invokes the remote function yields for a response.

Methods

InvokeClient(Player player, ... arguments)

Description Invokes the callback on the client which is bound to the Remote Function, with the specified player and an arbitrary number of arguments.

Sample Call

RemoteFunction:InvokeClient(game.Players.LifeInDevelopment, "overweight skid")

InvokeServer has similar functionality, except that the player argument is implicit and must be invoked from a local script. Also note that it is not reccommended to use InvokeClient, as the client can potentially hang the server if a value is not returned.

Callbacks

OnServerInvoke(Player player, ... arguments)

Description The callback bound to OnServerInvoke is invoked whenever InvokeServer is called, with the player and an arbitrary number of arguments.

Sample

-- Server script
RemoteFunction.OnServerInvoke = function(player, message, coolNumber)
  -- ...
  return -- Ensure that you return in your callback to avoid hanging the client. 
end

-- Local script
RemoteFunction:InvokeServer("foo", 42) -- Remember that the player argument is implicit.

OnClientInvoke has similar functionality, except that InvokeClient is invoked from a server script with the player argument, and the callback is in a local script.

Well with that out of the way, lets start writing some code!

Designing good Remote logic

Lets write out a simple shop system, where the player clicks on a button to exchange their silver for gems.

Lets plan this out:

  1. The player clicks on a button.
  2. A Remote Event is fired to the server, with the amount of silver the player wants to trade in.
  3. A server script listens to the Remote Event.
  4. The server checks whether or not the player has enough silver, returns prematurely if they don't.
  5. The server deducts the silver from the player.
  6. The server calculates how many gems should be given and increments it to the player's gems.

A common but wrong approach would be to pass the amount of silver the player has from the client and also pass the amount of gems that should be exchanged for. You can guess that this'd easily be exploited, and someone can easily pass an arbitrary amount of silver and gems. Another example would actually be where the client deducts their silver and increases their gems themselves, in a filtering enabled game this change wouldn't replicate and would only be seen locally.

The former example is an example of a server that is not authoritative, the client can pass however many silver/gems they want and the server doesn't have the ability to deny the request. Moreover, the server doesn't check if the amount of silver passed was even valid, which they should do. Always be wary of the client, verify anything that they pass or if possible, avoid passing any information at all and check everything server side. In our example, nothing is passed and the server checks the silver & gems themselves, and is able to deny the request - the server is authoritative.

Sample

--Server script
RemoteEvent.OnServerEvent:Connect(function(player, silverToExchange)
  if player.Silver.Value < silverToExchange then return end -- Precondition/Guard clause which checks if the player has enough silver.
  player.Silver.Value = player.Silver.Value - silverToExchange
  player.Gems.Value = player.Gems.Value + CalculateSilverToGems(silverToExchange)
end)

-- Local script
TextButton.MouseButton1Down:Connect(function()
  RemoteEvent:FireServer(400) -- Pass the amount of silver that the player wants to exchange.
end)

Feedback

Well that's pretty much it! You can send me feedback or ask for help through discord at Life#7405. If I missed anything that you think should be included, or got something wrong, then don't hesitate to message me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment