-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathss_socket_server.py
More file actions
197 lines (167 loc) · 6.33 KB
/
ss_socket_server.py
File metadata and controls
197 lines (167 loc) · 6.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
import socketserver
import threading
import json
import time
import os
# List to store client connections
socket_list = []
messages_lock = threading.Lock()
messages = []
stats_lock = threading.Lock()
stats = {
'File Name': "None",
'Score': 0,
'HP': 10,
'Max HP': 10,
'Attack': 1,
'Coins': 0,
'Level': 99,
'FlipFlop Pipe': 0,
'Low HP Textbox': 16,
}
previous_level = 1
score_required = []
xp = 0
for i in range(-1, 100):
xp += ((i // 2) + 1) * 10000
score_required.append(xp)
def manual_levelup_check():
global stats, previous_level
max_hp = 10
attack = 1
level = 1
for i in range(1, len(score_required)):
if stats['Score'] >= score_required[i]:
level += 1
else:
break
for i in range(1, level + 1):
if i % 2 != 0 and i != 1:
attack += 1
elif i != 1:
max_hp += 5
print(stats['File Name'])
if stats['Max HP'] != max_hp:
stats['Max HP'] = max_hp
print("Stats were fixed from desyncronization")
if stats['Attack'] != attack:
stats['Attack'] = attack
print("Stats were fixed from desyncronization")
if stats['HP'] > stats["Max HP"]:
stats['HP'] = stats["Max HP"]
print("Stats were fixed from desyncronization")
# File path for the stats save file
SAVE_FILE_PATH = 'stats.json'
# Locks for thread synchronization
save_file_lock = threading.Lock()
# Define a custom handler class inheriting from socketserver.BaseRequestHandler
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
global messages
global stats
# Add client connection to the list
socket_list.append(self.request)
# Loop to continuously handle client requests
while True:
try:
# Receive data from the client
data = self.request.recv(4096)
if not data:
continue
# Split the received data by newline character
parts = data.decode().split('\n')
# Process each received JSON string individually
for part in parts:
if not part:
continue
try:
# Parse the JSON string into a Python object
data = json.loads(part)
if 'message' in data:
with messages_lock:
messages.extend(data['message'])
if 'data' in data and data['data'] and data['data']['Score'] >= 0:
with stats_lock:
# Check if the data changed is in the stats dictionary
for key in data['data']:
if key in stats:
stats[key] += data['data'][key]
except json.JSONDecodeError:
pass
# print(f"Invalid JSON data received from client {addr}. Skipping.")
except (ConnectionResetError, ConnectionAbortedError):
# Client disconnected
print(f"Client {self.client_address} disconnected.")
# Remove client from the socket list
if self.request in socket_list:
socket_list.remove(self.request)
break
# Function to periodically save stats
def save_stats_periodically():
global stats
manual_levelup_check()
while True:
try:
time.sleep(10) # Save stats every 10 seconds
with open(SAVE_FILE_PATH, 'w') as file:
json.dump(stats, file)
print('[Stats Saved]')
print(stats)
except Exception as e:
print(f"An error occurred while saving stats: {e}")
# Function to send data to all connected clients
def send_data():
global messages
global stats
while True:
time.sleep(0.1)
with messages_lock:
with stats_lock:
if stats:
sending = {
'data': stats.copy(),
'message': messages.copy(),
}
messages.clear()
if socket_list:
# Send dictionary over a socket
json_data = json.dumps(sending)
message = json_data + '\n'
# Send data to all connected clients
for connection in socket_list:
try:
connection.sendall(message.encode())
except BrokenPipeError:
# Handle broken pipe error
print("Broken pipe error. Client disconnected.")
connection.close()
if connection in socket_list:
socket_list.remove(connection)
def main():
# Load stats from save file
load_stats()
# Create the server, set this to your public IP or cloud server, and change the port to an open port on your network/cloud service.
with ThreadedTCPServer(("0.0.0.0", 5556), MyTCPHandler) as server:
print("Server started. Listening for connections...")
# Start a thread to save stats periodically
saving_thread = threading.Thread(target=save_stats_periodically)
saving_thread.start()
# Start a thread to send data to clients
manual_levelup_check()
sending_thread = threading.Thread(target=send_data)
sending_thread.start()
# Activate the server; this will keep running until you interrupt the program with Ctrl-C
server.serve_forever()
def load_stats():
global stats
try:
with open(SAVE_FILE_PATH, 'r') as file:
saved_stats = json.load(file)
stats.update(saved_stats)
print("Stats loaded from:", os.path.abspath(SAVE_FILE_PATH))
except (FileNotFoundError, json.JSONDecodeError):
print("Save file not found or invalid format. Using default stats.")
class ThreadedTCPServer(socketserver.ThreadingTCPServer):
allow_reuse_address = True
if __name__ == "__main__":
main()