Jump to content

pampules

Inactive Member
  • Posts

    3
  • Joined

  • Last visited

  • Feedback

    0%

About pampules

  • Birthday 08/25/2002

Informations

  • Gender
    Male

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

pampules's Achievements

Apprentice

Apprentice (3/16)

  • One Year In
  • Dedicated
  • First Post
  • Conversation Starter
  • Reacting Well

Recent Badges

3

Reputation

  1. [Solved problem] Problem: Could't spam UPPER arrow key + ENTER, index was moving to the element before last element.
  2. [Release] Persistent ChatCache System per Character (Client-Side) Demo [Hidden Content] General Description This system extends the standard chat functionality by allowing each character to automatically save and restore their last sent messages, even after: - channel change, - logout or relog, - or full client restart. Each character keeps its own independent chat history stored locally, containing only unique messages (duplicates are ignored automatically). Technical Overview The system is fully client-side, with no server or database dependency. It stores the last 32 distinct messages sent by the player. Automatic saving occurs after sending a message in chat When reloading the game, the chat history is restored exactly as it was before. Data Structure & Safety Each character’s messages are saved in an encrypted JSON file named: Documents/<your_server_name>/chat_cache/CharacterName.json Security & Stability: The content is encrypted using a lightweight XOR cipher. File writes are handled safely through a temporary .tmp file and a backup .bak file, ensuring data integrity even if: the player teleports while the cache is saving, the client closes suddenly, or the process is interrupted mid-save. The save operation is atomic, meaning it completes entirely or not at all — never leaving a half-written or corrupted file. Cross-Platform Storage Default save directory: Windows: C:\Users\<user>\Documents\Regalis2\chat_cache Linux/macOS: ~/Documents/Regalis2/chat_cache If the Documents folder cannot be accessed (permission issue), the system automatically falls back to a local folder (./chat_cache), so no errors occur. Key Features Character-specific history (not shared across characters). No SQL or server interaction. High performance — runs entirely in memory and writes on controlled intervals. Crash-safe, robust, and auto-recovers from incomplete saves. Automatically skips duplicate messages — only unique ones are saved. Example Behavior You send 10 messages as "Player1". You log out and close the client. You reopen the game and log in again as "Player1". You can navigate through the same 10 messages using the ↑ and ↓ keys — exactly as before. Additional Technical Notes Saving is handled via: json.dumps() → xor_crypt() → .tmp → atomic rename. Automatic restore from .bak if the main file is locked or interrupted. Files are fully encrypted without any noticeable performance loss. The system is easily extensible — timestamped messages or per-channel logging can be added later. Code Implementation uiChat.py #Add after imports def xor_crypt(data, key="ChatKey"): key_len = len(key) result = [] for i, c in enumerate(data): result.append(chr(ord(c) ^ ord(key[i % key_len]))) return "".join(result) #Find self.lastSentenceStack = [] self.lastSentencePos = 0 #Replace with (Replace YOUR_SERVER_NAME with your server name) self.chat_history = [] self.chat_history_index = -1 self.USER_DIR = os.path.expanduser("~") self.chat_cache_dir = os.path.join(self.USER_DIR, "Documents", "YOUR_SERVER_NAME", "chat_cache") self.chat_cache_dir = os.path.normpath(self.chat_cache_dir) self.chat_cache_file = None self.LoadChatCache() #Find def OpenChat(self): #Add self.chat_history_index = len(self.chat_history) #Find def OnIMEKeyDown(self, key): #Replace all lines with def OnIMEKeyDown(self, key): # NEW PERSISTENT CHAT HISTORY if app.VK_UP == key: if hasattr(self, "chat_history") and self.chat_history: self.chat_history_index = max(0, self.chat_history_index - 1) self.SetText(self.chat_history[self.chat_history_index]) self.SetEndPosition() return True if app.VK_DOWN == key: if hasattr(self, "chat_history") and self.chat_history: self.chat_history_index = min(len(self.chat_history), self.chat_history_index + 1) if self.chat_history_index < len(self.chat_history): self.SetText(self.chat_history[self.chat_history_index]) else: self.SetText("") self.SetEndPosition() return True ui.EditLine.OnIMEKeyDown(self, key) #Find __PrevLastSentenceStack, __NextLastSentenceStack, __PushLastSentenceStack #Replace content with pass #Find # LAST_SENTENCE_STACK self.__PushLastSentenceStack(text) # END_OF_LAST_SENTENCE_STACK #Replace with if hasattr(self, "PushChatMessage"): self.PushChatMessage(text) #Find def OnIMEReturn(self): . . . return True #Add def LoadChatCache(self): try: try: if not os.path.exists(self.chat_cache_dir): os.makedirs(self.chat_cache_dir) except Exception: self.chat_cache_dir = os.path.join(os.getcwd(), "chat_cache") if not os.path.exists(self.chat_cache_dir): os.makedirs(self.chat_cache_dir) playerName = player.GetName() self.chat_cache_file = os.path.join(self.chat_cache_dir, "%s.json" % playerName) backup_path = self.chat_cache_file + ".bak" if os.path.exists(backup_path): try: if os.path.exists(self.chat_cache_file): os.remove(self.chat_cache_file) os.rename(backup_path, self.chat_cache_file) except Exception as e: import dbg dbg.LogBox("ChatCache restore from .bak failed: %s" % e) if os.path.exists(self.chat_cache_file): f = open(self.chat_cache_file, "rb") encrypted = f.read() f.close() decrypted = xor_crypt(unicode(encrypted, errors="ignore")) if decrypted.strip(): try: data = json.loads(decrypted) if not isinstance(data.get("messages", []), list): self.chat_history = [] return self.chat_history = [str(x) for x in data.get("messages", [])] return except Exception as e: import dbg dbg.LogBox("ChatCache parse error: %s" % e) except Exception as e: import dbg dbg.LogBox("ChatCache load error: %s" % e) self.chat_history = [] def SaveChatCache(self): try: if not getattr(self, "chat_cache_file", None): return if not self.chat_history: return data = { "messages": self.chat_history[-32:] } temp_path = self.chat_cache_file + ".tmp" backup_path = self.chat_cache_file + ".bak" f = open(temp_path, "wb") content = json.dumps(data, ensure_ascii=False, indent=2) encrypted = xor_crypt(content) f.write(encrypted) f.flush() os.fsync(f.fileno()) f.close() if os.path.exists(self.chat_cache_file): os.rename(self.chat_cache_file, backup_path) os.rename(temp_path, self.chat_cache_file) if os.path.exists(backup_path): os.remove(backup_path) except Exception as e: import dbg dbg.LogBox("ChatCache save error: %s" % e) def PushChatMessage(self, msg): if not msg: return if hasattr(self, "last_saved_message") and msg == self.last_saved_message: return self.last_saved_message = msg if msg in self.chat_history: self.chat_history.remove(msg) self.chat_history.append(msg) if len(self.chat_history) > 32: self.chat_history = self.chat_history[-32:] self.chat_history_index = len(self.chat_history) try: self.SaveChatCache() except Exception as e: chat.AppendChat(chat.CHAT_TYPE_INFO, "Eroare la salvare chat: %s" % e) game.py (BONUS! Rename .json file after changing character name)
×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.