Minecraft-like Roblox block game rblx.games/135624152691584
roblox roblox-game rojo
at main 196 lines 4.5 kB view raw
1--!native 2--!optimize 2 3 4local Players = game:GetService("Players") 5local ReplicatedStorage = game:GetService("ReplicatedStorage") 6 7local Replica = require(ReplicatedStorage.Packages.replica) 8 9local ClientStateService = {} 10 11local HOTBAR_SIZE = 10 12 13local token = Replica.Token("ClientState") 14 15local blockCatalog = {} 16local playerReplicas = {} :: {[Player]: any} 17local blocksFolder: Folder? = nil 18local readyConnections = {} :: {[Player]: RBXScriptConnection} 19 20local function sortBlocks() 21 table.sort(blockCatalog, function(a, b) 22 local na = tonumber(a.id) 23 local nb = tonumber(b.id) 24 if na and nb then 25 return na < nb 26 end 27 if na then 28 return true 29 end 30 if nb then 31 return false 32 end 33 return a.id < b.id 34 end) 35end 36 37local function rebuildBlockCatalog() 38 table.clear(blockCatalog) 39 if not blocksFolder then 40 return 41 end 42 43 for _, block in ipairs(blocksFolder:GetChildren()) do 44 local id = block:GetAttribute("n") 45 if id ~= nil then 46 local displayName = block:GetAttribute("name") or block:GetAttribute("displayName") or block:GetAttribute("dn") or block.Name 47 table.insert(blockCatalog, { 48 id = tostring(id), 49 name = displayName, 50 }) 51 end 52 end 53 sortBlocks() 54end 55 56local function makeBaseState() 57 local inventory = {} 58 local hotbar = {} 59 60 for _, entry in ipairs(blockCatalog) do 61 inventory[entry.id] = { 62 name = entry.name, 63 count = 999999, 64 } 65 if #hotbar < HOTBAR_SIZE then 66 table.insert(hotbar, entry.id) 67 end 68 end 69 70 return { 71 inventory = inventory, 72 hotbar = hotbar, 73 selectedSlot = #hotbar > 0 and 1 or 0, 74 } 75end 76 77local function sanitizeSelection(hotbar, selectedSlot) 78 if type(selectedSlot) ~= "number" then 79 return (#hotbar > 0) and 1 or 0 80 end 81 if selectedSlot < 1 or selectedSlot > HOTBAR_SIZE then 82 return (#hotbar > 0) and 1 or 0 83 end 84 return selectedSlot 85end 86 87local function refreshReplica(replica) 88 local state = makeBaseState() 89 replica:Set({"inventory"}, state.inventory) 90 replica:Set({"hotbar"}, state.hotbar) 91 replica:Set({"selectedSlot"}, sanitizeSelection(state.hotbar, replica.Data.selectedSlot)) 92end 93 94function ClientStateService:SetBlocksFolder(folder: Folder?) 95 blocksFolder = folder 96 rebuildBlockCatalog() 97 for _, replica in pairs(playerReplicas) do 98 refreshReplica(replica) 99 end 100end 101 102function ClientStateService:GetReplica(player: Player) 103 return playerReplicas[player] 104end 105 106function ClientStateService:GetSelectedBlockId(player: Player) 107 local replica = playerReplicas[player] 108 if not replica then 109 return nil 110 end 111 local data = replica.Data 112 local hotbar = data.hotbar or {} 113 local selectedSlot = sanitizeSelection(hotbar, data.selectedSlot) 114 return hotbar[selectedSlot] 115end 116 117function ClientStateService:HasInInventory(player: Player, blockId: any): boolean 118 local replica = playerReplicas[player] 119 if not replica or not blockId then 120 return false 121 end 122 local inv = replica.Data.inventory 123 return inv and inv[tostring(blockId)] ~= nil or false 124end 125 126local function handleReplicaEvents(player: Player, replica) 127 replica.OnServerEvent:Connect(function(plr, action, payload) 128 if plr ~= player then 129 return 130 end 131 132 if action == "SelectHotbarSlot" then 133 local slot = tonumber(payload) 134 local hotbar = replica.Data.hotbar 135 if not hotbar then 136 return 137 end 138 if slot and slot >= 1 and slot <= HOTBAR_SIZE then 139 replica:Set({"selectedSlot"}, slot) 140 end 141 end 142 end) 143end 144 145local function onPlayerAdded(player: Player) 146 local replica = Replica.New({ 147 Token = token, 148 Tags = { 149 UserId = player.UserId, 150 Player = player, 151 }, 152 Data = makeBaseState(), 153 }) 154 155 if Replica.ReadyPlayers[player] then 156 replica:Subscribe(player) 157 else 158 readyConnections[player] = Replica.NewReadyPlayer:Connect(function(newPlayer) 159 if newPlayer ~= player then 160 return 161 end 162 if readyConnections[player] then 163 readyConnections[player]:Disconnect() 164 readyConnections[player] = nil 165 end 166 replica:Subscribe(player) 167 end) 168 end 169 170 handleReplicaEvents(player, replica) 171 playerReplicas[player] = replica 172end 173 174local function onPlayerRemoving(player: Player) 175 local replica = playerReplicas[player] 176 if replica then 177 replica:Destroy() 178 playerReplicas[player] = nil 179 end 180 if readyConnections[player] then 181 readyConnections[player]:Disconnect() 182 readyConnections[player] = nil 183 end 184end 185 186function ClientStateService:Init() 187 rebuildBlockCatalog() 188 189 for _, player in ipairs(Players:GetPlayers()) do 190 onPlayerAdded(player) 191 end 192 Players.PlayerAdded:Connect(onPlayerAdded) 193 Players.PlayerRemoving:Connect(onPlayerRemoving) 194end 195 196return ClientStateService