Peril_Dice/Controller_MessageHandler.lsl

273 lines
9.6 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// === Controller Message Handler Helper Script ===
// Handles non-critical message processing for the Main Controller
// Reduces Main Controller size and improves modularity
// Message constants for communication with main controller
integer MSG_REQUEST_PLAYER_DATA = 8001;
integer MSG_REQUEST_PICK_DATA = 8002;
integer MSG_REQUEST_LIFE_DATA = 8003;
integer MSG_PICK_ACTION = 8004;
integer MSG_DICE_TYPE_REQUEST = 8005;
integer MSG_LEAVE_GAME_REQUEST = 8006;
// Game state data synchronized from Main Controller
list players = [];
list names = [];
list lives = [];
list picksData = [];
list readyPlayers = [];
integer diceType = 6;
// Message constants from Main Controller (synchronized)
integer MSG_SYNC_GAME_STATE = 107;
integer MSG_SYNC_PICKQUEUE = 2001;
// Channel constants for scoreboard updates
integer SCOREBOARD_CHANNEL_1;
integer SCOREBOARD_CHANNEL_2;
integer FLOATER_BASE_CHANNEL;
integer MSG_CLEANUP_FLOAT = 104;
integer MSG_UPDATE_FLOAT = 103;
// Dynamic channel calculation (matches Main Controller)
integer CHANNEL_BASE = -77000;
integer calculateChannel(integer offset) {
// Use BOTH owner's key AND object's key to make channels unique per game instance
string ownerStr = (string)llGetOwner();
string objectStr = (string)llGetKey();
string combinedStr = ownerStr + objectStr;
// Create a more unique hash using both keys
string hashStr = llMD5String(combinedStr, 0);
integer hash1 = llSubStringIndex("0123456789abcdef", llGetSubString(hashStr, 0, 0));
integer hash2 = llSubStringIndex("0123456789abcdef", llGetSubString(hashStr, 1, 1));
integer combinedHash = hash1 * 16 + hash2; // Creates 0-255 range
return CHANNEL_BASE - (offset * 1000) - combinedHash;
}
initializeChannels() {
SCOREBOARD_CHANNEL_1 = calculateChannel(6); // ~-77600 range
SCOREBOARD_CHANNEL_2 = calculateChannel(7); // ~-77700 range
FLOATER_BASE_CHANNEL = calculateChannel(9); // ~-77900 range
}
// Handle player list requests
handlePlayerListRequest(key requester) {
string namesCSV = llList2CSV(names);
llMessageLinked(LINK_SET, 203, namesCSV, requester);
}
// Handle pick data requests
handlePickDataRequest(string targetName, key requester) {
integer i;
for (i = 0; i < llGetListLength(picksData); i++) {
string rawEntry = llList2String(picksData, i);
list parts = llParseString2List(rawEntry, ["|"], []);
if (llList2String(parts, 0) == targetName) {
llMessageLinked(LINK_SET, 205, targetName + "|" + llList2String(parts, 1), requester);
return;
}
}
llMessageLinked(LINK_SET, 205, targetName + "|", requester);
}
// Handle life data requests
handleLifeDataRequest(string playerName, key requester) {
integer idx = llListFindList(names, [playerName]);
if (idx != -1) {
string lifeVal = llList2String(lives, idx);
llMessageLinked(LINK_SET, 208, playerName + "|" + lifeVal, requester);
}
}
// Handle pick actions (ADD_PICK/REMOVE_PICK)
handlePickAction(string actionData) {
list parts = llParseString2List(actionData, ["~"], []);
string action = llList2String(parts, 0);
list args = llParseString2List(llList2String(parts, 1), ["|"], []);
string name = llList2String(args, 0);
string pick = llList2String(args, 1);
integer i;
for (i = 0; i < llGetListLength(picksData); i++) {
string entry = llList2String(picksData, i);
list pdParts = llParseString2List(entry, ["|"], []);
if (llList2String(pdParts, 0) == name) {
list pickList = [];
string rawPicks = llList2String(pdParts, 1);
if (rawPicks != "") {
pickList = llParseString2List(rawPicks, [","], []);
}
if (action == "ADD_PICK") {
if (llListFindList(pickList, [pick]) == -1) {
pickList += [pick];
llOwnerSay("➕ [Message Handler] Added " + pick + " to " + name);
}
} else if (action == "REMOVE_PICK") {
integer idx = llListFindList(pickList, [pick]);
if (idx != -1) {
pickList = llDeleteSubList(pickList, idx, idx);
llOwnerSay("➖ [Message Handler] Removed " + pick + " from " + name);
}
}
// Update local picks data
picksData = llListReplaceList(picksData, [name + "|" + llList2CSV(pickList)], i, i);
// Notify Main Controller of the change
llMessageLinked(LINK_SET, 204, actionData, NULL_KEY);
return;
}
}
}
// Handle dice type requests
handleDiceTypeRequest(key requester) {
llOwnerSay("🎲 [Message Handler] Sending dice type: " + (string)diceType);
llMessageLinked(LINK_SET, 102, (string)diceType, requester); // MSG_ROLL_RESULT
}
// Handle leave game requests
handleLeaveGameRequest(string requestData) {
list parts = llParseString2List(requestData, ["|"], []);
if (llList2String(parts, 0) == "LEAVE_GAME") {
string leavingName = llList2String(parts, 1);
key leavingKey = (key)llList2String(parts, 2);
integer idx = llListFindList(players, [leavingKey]);
if (idx != -1) {
// Remove player's float using the tracked channel
integer ch = FLOATER_BASE_CHANNEL + idx;
llMessageLinked(LINK_SET, MSG_CLEANUP_FLOAT, (string)ch, NULL_KEY);
// Update local lists
players = llDeleteSubList(players, idx, idx);
names = llDeleteSubList(names, idx, idx);
lives = llDeleteSubList(lives, idx, idx);
picksData = llDeleteSubList(picksData, idx, idx);
// Remove from ready list if present
integer readyIdx = llListFindList(readyPlayers, [leavingName]);
if (readyIdx != -1) {
readyPlayers = llDeleteSubList(readyPlayers, readyIdx, readyIdx);
}
llOwnerSay("👋 [Message Handler] " + leavingName + " left the game");
// Notify Main Controller
llMessageLinked(LINK_SET, MSG_LEAVE_GAME_REQUEST, requestData, NULL_KEY);
// Check if game should end (less than 2 players)
if (llGetListLength(names) == 1) {
string winner = llList2String(names, 0);
llSay(0, "✨ ULTIMATE VICTORY! " + winner + " is the Ultimate Survivor!");
// Notify Main Controller of victory
llMessageLinked(LINK_SET, 998, "GAME_WON|" + winner, NULL_KEY);
}
}
}
}
// Synchronize game state from Main Controller
syncGameState(string stateData) {
list parts = llParseString2List(stateData, ["~"], []);
if (llGetListLength(parts) >= 4) {
lives = llCSV2List(llList2String(parts, 0));
// Decode picks data
string encodedPicksDataStr = llList2String(parts, 1);
picksData = [];
if (encodedPicksDataStr != "" && encodedPicksDataStr != "EMPTY") {
list encodedEntries = llParseString2List(encodedPicksDataStr, ["^"], []);
integer i;
for (i = 0; i < llGetListLength(encodedEntries); i++) {
string entry = llList2String(encodedEntries, i);
list entryParts = llParseString2List(entry, ["|"], []);
if (llGetListLength(entryParts) >= 2) {
string playerName = llList2String(entryParts, 0);
string picks = llList2String(entryParts, 1);
// Convert semicolons back to commas
picks = llDumpList2String(llParseString2List(picks, [";"], []), ",");
picksData += [playerName + "|" + picks];
} else {
picksData += [entry];
}
}
}
names = llCSV2List(llList2String(parts, 3));
}
}
default {
state_entry() {
llOwnerSay("📨 [Message Handler] Helper script ready!");
initializeChannels();
}
link_message(integer sender, integer num, string str, key id) {
// Handle player list requests
if (num == 202 && str == "REQUEST_PLAYER_LIST") {
handlePlayerListRequest(id);
return;
}
// Handle pick data requests
if (num == 206) {
handlePickDataRequest(str, id);
return;
}
// Handle life data requests
if (num == 208) {
handleLifeDataRequest(str, id);
return;
}
// Handle pick actions
if (num == 204) {
handlePickAction(str);
return;
}
// Handle dice type requests
if (num == 996) {
if (str == "GET_DICE_TYPE") {
handleDiceTypeRequest(id);
}
return;
}
// Handle leave game requests
if (num == 107) {
handleLeaveGameRequest(str);
return;
}
// Sync game state from Main Controller
if (num == MSG_SYNC_GAME_STATE) {
syncGameState(str);
return;
}
// Sync player list for reference
if (num == MSG_SYNC_PICKQUEUE) {
// Update players list reference (if needed for future functionality)
return;
}
// Handle full reset
if (num == -99999 && str == "FULL_RESET") {
players = [];
names = [];
lives = [];
picksData = [];
readyPlayers = [];
diceType = 6;
llOwnerSay("📨 [Message Handler] Reset complete");
}
}
}