130 lines
4.9 KiB
Python
130 lines
4.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
import logging
|
|
from odoo import http
|
|
from odoo.http import request
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _json(data):
|
|
headers = {
|
|
'Content-Type': 'application/json; charset=utf-8',
|
|
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
'Access-Control-Allow-Headers': 'Content-Type',
|
|
}
|
|
try:
|
|
origin = request.httprequest.headers.get('Origin')
|
|
if origin:
|
|
headers['Access-Control-Allow-Origin'] = origin
|
|
headers['Access-Control-Allow-Credentials'] = 'true'
|
|
else:
|
|
headers['Access-Control-Allow-Origin'] = '*'
|
|
except Exception:
|
|
headers['Access-Control-Allow-Origin'] = '*'
|
|
return request.make_response(
|
|
__import__('json').dumps(data, ensure_ascii=False), headers=headers)
|
|
|
|
|
|
def _post_body():
|
|
try:
|
|
raw = request.httprequest.get_data(as_text=True) or '{}'
|
|
return __import__('json').loads(raw)
|
|
except Exception:
|
|
return {}
|
|
|
|
|
|
def _require_user():
|
|
uid = request.session.uid
|
|
if not uid:
|
|
return {'ok': False, 'error': 'auth'}
|
|
user = request.env['res.users'].sudo().browse(uid)
|
|
if not user.exists() or not user.active:
|
|
return {'ok': False, 'error': 'auth'}
|
|
return None
|
|
|
|
|
|
def _get_world():
|
|
user = request.env['res.users'].sudo().browse(request.session.uid) \
|
|
if request.session.uid else request.env['res.users']
|
|
if not user.exists():
|
|
return None
|
|
return request.env['yt.world'].sudo().get_or_create_for_user(user)
|
|
|
|
|
|
class YtWorldChestApi(http.Controller):
|
|
|
|
# ── 列表:当前世界某地块的活跃宝箱 ──
|
|
@http.route('/yt_world/api/chests', type='http', auth='public',
|
|
methods=['GET', 'OPTIONS'], csrf=False)
|
|
def list_chests(self, **kw):
|
|
auth_err = _require_user()
|
|
if auth_err:
|
|
return _json(auth_err)
|
|
world = _get_world()
|
|
if not world:
|
|
return _json({'ok': False, 'error': 'no_world'})
|
|
domain = [('world_id', '=', world.id), ('state', '=', 'active')]
|
|
q = kw.get('q'); r = kw.get('r')
|
|
if q is not None and r is not None:
|
|
# tile_ref 是 Json,按字典值过滤:保留该地块的宝箱
|
|
recs = request.env['yt.world.chest'].sudo().search(domain)
|
|
recs = recs.filtered(lambda c: (c.tile_ref or {}).get('q') == int(q)
|
|
and (c.tile_ref or {}).get('r') == int(r))
|
|
else:
|
|
recs = request.env['yt.world.chest'].sudo().search(domain)
|
|
out = [{
|
|
'id': c.id,
|
|
'cell_i': c.cell_i, 'cell_j': c.cell_j,
|
|
'tier': c.tier, 'reward_type': c.reward_type,
|
|
'reward_amount': c.reward_amount, 'state': c.state,
|
|
'tile_ref': c.tile_ref or {},
|
|
} for c in recs]
|
|
return _json({'ok': True, 'chests': out})
|
|
|
|
# ── 生成:测试期前端每 10s 调一次;生产可挂 ir.cron ──
|
|
@http.route('/yt_world/api/chest/generate', type='http', auth='public',
|
|
methods=['POST', 'OPTIONS'], csrf=False)
|
|
def generate_chest(self, **kw):
|
|
auth_err = _require_user()
|
|
if auth_err:
|
|
return _json(auth_err)
|
|
world = _get_world()
|
|
if not world:
|
|
return _json({'ok': False, 'error': 'no_world'})
|
|
body = _post_body()
|
|
q = body.get('q'); r = body.get('r')
|
|
grid_n = int(body.get('grid_n') or 20)
|
|
q = int(q) if q is not None else None
|
|
r = int(r) if r is not None else None
|
|
chest = request.env['yt.world.chest'].sudo().generate_for_world(
|
|
world, q=q, r=r, grid_n=grid_n)
|
|
if not chest:
|
|
return _json({'ok': False, 'error': 'no_slot'})
|
|
return _json({'ok': True, 'chest': {
|
|
'id': chest.id, 'cell_i': chest.cell_i, 'cell_j': chest.cell_j,
|
|
'tier': chest.tier, 'reward_type': chest.reward_type,
|
|
'reward_amount': chest.reward_amount, 'state': chest.state,
|
|
'tile_ref': chest.tile_ref or {},
|
|
}})
|
|
|
|
# ── 开启:前端生物到达宝箱后调用 ──
|
|
@http.route('/yt_world/api/chest/claim', type='http', auth='public',
|
|
methods=['POST', 'OPTIONS'], csrf=False)
|
|
def claim_chest(self, **kw):
|
|
auth_err = _require_user()
|
|
if auth_err:
|
|
return _json(auth_err)
|
|
world = _get_world()
|
|
if not world:
|
|
return _json({'ok': False, 'error': 'no_world'})
|
|
body = _post_body()
|
|
cid = body.get('chest_id')
|
|
creature_cid = body.get('cid') or body.get('creature_cid')
|
|
chest = request.env['yt.world.chest'].sudo().browse(int(cid) if cid else 0)
|
|
if not chest.exists():
|
|
return _json({'ok': False, 'error': 'no_chest'})
|
|
if chest.world_id.id != world.id:
|
|
return _json({'ok': False, 'error': 'forbidden'})
|
|
res = chest.claim(creature_cid or '')
|
|
return _json(res)
|