Skip to content

Instantly share code, notes, and snippets.

@GrenderG
Created April 18, 2025 23:20
Show Gist options
  • Save GrenderG/5ee21ed20dcaf7a94996c3bae177f0bb to your computer and use it in GitHub Desktop.
Save GrenderG/5ee21ed20dcaf7a94996c3bae177f0bb to your computer and use it in GitHub Desktop.
Huusen i-mode game replacement server.
from flask import Flask, request, Response
import json
import os
app = Flask(__name__)
# Configuration.
LEADERBOARD_FILE = 'leaderboard.json'
PORT = 80
def initialize_leaderboard():
"""Initialize with dummy data if file doesn't exist."""
if not os.path.exists(LEADERBOARD_FILE):
with open(LEADERBOARD_FILE, 'w') as f:
json.dump({'NULLGWDOCOMO': 0}, f)
def load_leaderboard():
"""Load leaderboard data from JSON file."""
with open(LEADERBOARD_FILE, 'r') as f:
return json.load(f)
def save_leaderboard(data):
"""Save leaderboard data to JSON file."""
with open(LEADERBOARD_FILE, 'w') as f:
json.dump(data, f)
def get_top_14_scores(leaderboard):
"""
Get top 14 scores from leaderboard.
Returns:
list: Top 14 scores sorted descending, padded with zeros if needed.
"""
all_scores = list(leaderboard.values())
all_scores.sort(reverse=True)
top_scores = all_scores[:14]
top_scores.extend([0] * (14 - len(top_scores)))
return top_scores
@app.route('/b/p2_i.fcgi', methods=['GET'])
def handle_membership():
"""Handle membership requests."""
uid = request.args.get('uid', 'NULLGWDOCOMO')
# Prepare response with 3 params delimited by '&'.
# 1: 1 means membership OK, 0 means not allowed to play.
# 2: Unused integer (send 1).
# 3: String that appears in first-time dialog.
response_data = '1&1&Welcome!'
return Response(
response_data,
mimetype='text/plain',
headers={'Content-Type': 'text/plain; charset=utf-8'}
)
@app.route('/appli/RankSrv', methods=['GET'])
def handle_leaderboard():
"""Handle leaderboard submission request."""
# This is what is sent:
# ranking_str = this.ConnectDataGet(IApplication.getCurrentApp().getArgs()[0]
# + IApplication.getCurrentApp().getArgs()[3]
# + "&g=" + 209
# + "&m=" + var3
# + "&s=" + balH
# + "&hs=" + this.oldhiscore
# + "&n=" + var6, '#');
# We only care about 'balH' (current score), 'hs' can be ignored since we already store that info ourselves.
# Game expects 14 strings with a # delimiter. We assume game expected the first 14 players with the best score.
uid = request.args.get('uid', 'NULLGWDOCOMO')
current_score = int(request.args.get('s', 0))
leaderboard = load_leaderboard()
if uid not in leaderboard or current_score > leaderboard[uid]:
leaderboard[uid] = current_score
save_leaderboard(leaderboard)
top_scores = get_top_14_scores(leaderboard)
response_data = '#'.join(f'{i+1}: {score}' for i, score in enumerate(top_scores))
return Response(
response_data,
mimetype='text/plain',
headers={'Content-Type': 'text/plain; charset=utf-8'}
)
if __name__ == '__main__':
initialize_leaderboard()
app.run(host='127.0.0.1', port=PORT)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment