chat.lua
1 --[[ 2 ToasterGen Spin 3 4 Copyright (C) 2025 Clifton Toaster Reid <cliftontreid@duck.com> 5 6 This library is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public License 17 along with this library. If not, see <https://www.gnu.org/licenses/>. 18 ]] 19 20 local msg 21 local players 22 23 local function init(charBox, playerDetector) 24 msg = peripheral.wrap(charBox) 25 if msg == nil then 26 error("ChatBox not found", 0) 27 end 28 players = peripheral.wrap(playerDetector) 29 if players == nil then 30 error("PlayerDetector not found", 0) 31 end 32 end 33 34 ---@class Player 35 ---@field name string 36 ---@field uuid string 37 ---@field colour number 38 39 ---@type Player[] 40 local players = {} 41 42 local function addPlayer(player) 43 -- Check if player already exists 44 for _, p in ipairs(players) do 45 if p.uuid == player.uuid then 46 return 47 end 48 end 49 50 -- Define a set of available colors 51 local candidateColors = { 1, 2, 3, 4, 5, 6, 7, 8 } 52 local usedColors = {} 53 54 -- Collect colors that are already in use 55 for _, p in ipairs(players) do 56 if p.colour then 57 usedColors[p.colour] = true 58 end 59 end 60 61 -- Build list of colors not yet assigned 62 local available = {} 63 for _, color in ipairs(candidateColors) do 64 if not usedColors[color] then 65 table.insert(available, color) 66 end 67 end 68 69 -- If no unique color available, return an error 70 if #available == 0 then 71 error("No available colors remaining", 0) 72 end 73 74 -- Select a random color from the available ones 75 local randomIndex = math.random(#available) 76 player.colour = available[randomIndex] 77 78 table.insert(players, player) 79 end 80 81 local function removePlayer(player) 82 for i, p in ipairs(players) do 83 if p.uuid == player.uuid then 84 table.remove(players, i) 85 break 86 end 87 end 88 end 89 90 local function getPlayer(uuid) 91 for _, p in ipairs(players) do 92 if p.uuid == uuid then 93 return p 94 end 95 end 96 return nil 97 end 98 99 local function getPlayers() 100 return players 101 end 102 103 local function clearPlayers() 104 players = {} 105 end 106 107 ---@class tmpBet 108 ---@field amount number 109 ---@field player string | nil 110 ---@field uuid string | nil 111 112 ---@type tmpBet 113 local tmpBet = { 114 amount = 0, 115 player = nil, 116 } 117 118 local PLAYERZONE = 5 119 local COMMANDS = { 120 "register", 121 "redeem", 122 } 123 124 local function has_value(tab, val) 125 for index, value in ipairs(tab) do 126 if value == val then 127 return true 128 end 129 end 130 131 return false 132 end 133 134 ---@class ChatEvent 135 ---@field type string The type of event 136 ---@field username string The username of the player who sent the message 137 ---@field uuid string The UUID of the player who sent the message 138 ---@field message string The message sent by the player 139 ---@field isHidden boolean Whether the message is hidden 140 141 ---Handles chat events 142 ---@param event ChatEvent The chat event to handle 143 local function handleChatEvent(event) 144 if event.type ~= "chat" then 145 return 146 end 147 if not event.isHidden or has_value(COMMANDS, event.message) then 148 print("Received invalid chat event") 149 return 150 end 151 -- Check if the player is 152 local around = players.getPlayersInCubic(PLAYERZONE, PLAYERZONE, PLAYERZONE) 153 local isAround = false 154 for _, player in ipairs(around) do 155 if player.uuid == event.uuid then 156 isAround = true 157 break 158 end 159 end 160 if not isAround then 161 error("Player '" .. event.username .. "' not in range", 0) 162 return 163 end 164 165 if event.message == "register" then 166 if tmpBet.player ~= nil then 167 if tmpBet.player == event.username then 168 msg.sendMessageToPlayer("You are already registered, you may proceed to place a bet", event.username) 169 elseif tmpBet.player ~= event.username then 170 msg.sendMessageToPlayer( 171 "A player is currently registered, please wait for them to place a bet", 172 event.username 173 ) 174 end 175 return 176 end 177 tmpBet.player = event.username 178 tmpBet.uuid = event.uuid 179 msg.sendMessageToPlayer("You have been registered, you may now place a bet", event.username) 180 elseif event.message == "redeem" then 181 msg.sendMessageToPlayer("Please visit the chute to redeem your coins", event.username) 182 end 183 end 184 185 ---@param event string 186 local function handleCoin(event) 187 if event ~= "coin" then 188 return 189 end 190 tmpBet.amount = tmpBet.amount + 1 191 if tmpBet.player == nil then 192 msg.sendMessage( 193 "No player registered, please use '$register' before placing a bet, there are currently " 194 .. tmpBet.amount 195 .. " coins without an owner" 196 ) 197 return -1 198 end 199 msg.sendMessageToPlayer( 200 "Coin received, a total of " .. tmpBet.amount .. " coins are now in your account", 201 tmpBet.player 202 ) 203 return 0 204 end 205 206 local function getBet() 207 if tmpBet.player == nil then 208 msg.sendMessage( 209 "No player is currently registered, please use '$register' before placing a bet, there are " 210 .. tmpBet.amount 211 .. " coins without an owner" 212 ) 213 return nil 214 end 215 local bet = tmpBet 216 tmpBet = { 217 amount = 0, 218 player = nil, 219 } 220 return bet 221 end 222 223 local msgFuncs = {} 224 225 msgFuncs.handleChatEvent = handleChatEvent 226 msgFuncs.handleCoin = handleCoin 227 msgFuncs.getBet = getBet 228 msgFuncs.addPlayer = addPlayer 229 msgFuncs.removePlayer = removePlayer 230 msgFuncs.getPlayer = getPlayer 231 msgFuncs.getPlayers = getPlayers 232 msgFuncs.clearPlayers = clearPlayers 233 msgFuncs.addPlayer = addPlayer 234 msgFuncs.removePlayer = removePlayer 235 msgFuncs.init = init 236 237 --- Sends a message to all players 238 ---@param message string The message to send 239 ---@return nil 240 msgFuncs.sendMessage = function(message) 241 if msg then 242 msg.sendMessage(message, "SoSpin") 243 else 244 error("ChatBox not initialized", 0) 245 end 246 end 247 248 --- Sends a message to a player 249 ---@param message string The message to send 250 ---@param player string The player to send the message to 251 ---@return nil 252 msgFuncs.sendMessageToPlayer = function(message, player) 253 if msg then 254 msg.sendMessageToPlayer(message, player, "SoSpin") 255 else 256 error("ChatBox not initialized", 0) 257 end 258 end 259 260 return msgFuncs