events.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. from flask_socketio import emit
  2. from extensions import socketio, db
  3. from models import Event, Inventory
  4. from flask import request
  5. import json
  6. from dateutil import parser
  7. from datetime import datetime
  8. @socketio.on('connect')
  9. def handle_connect():
  10. print('Client connected')
  11. emit('clear_events')
  12. # Send history
  13. try:
  14. recent_events = Event.query.order_by(Event.timestamp.desc()).limit(30).all()
  15. print(f"Sending history: {len(recent_events)} events")
  16. for event in reversed(recent_events):
  17. emit('game_event', event.to_dict())
  18. except Exception as e:
  19. print(f"Error sending history: {e}")
  20. @socketio.on('disconnect')
  21. def handle_disconnect():
  22. print('Client disconnected')
  23. @socketio.on('game_event')
  24. def handle_game_event(data):
  25. # data = {type: 'CHAT', player: 'Name', content: 'Message', ...}
  26. print(f"Received event: {data}")
  27. # Save to DB
  28. try:
  29. if not data.get('type'):
  30. print(f"Error: Missing event type in {data}")
  31. return
  32. event_timestamp = None
  33. if data.get('timestamp'):
  34. try:
  35. event_timestamp = parser.parse(data.get('timestamp'))
  36. except Exception as e:
  37. print(f"Error parsing timestamp: {e}")
  38. event_timestamp = datetime.utcnow()
  39. event = Event(
  40. event_type=data.get('type'),
  41. player_uuid=data.get('uuid'),
  42. player_name=data.get('player'),
  43. content=data.get('content'),
  44. location=data.get('location'),
  45. timestamp=event_timestamp or datetime.utcnow()
  46. )
  47. db.session.add(event)
  48. db.session.commit()
  49. print(f"Event saved to DB: {event.id}")
  50. # If inventory data is present, save it
  51. if 'inventory' in data:
  52. inventory = Inventory(
  53. event_id=event.id,
  54. player_uuid=data.get('uuid'),
  55. items=json.dumps(data.get('inventory'))
  56. )
  57. db.session.add(inventory)
  58. db.session.commit()
  59. print(f"Inventory saved for event {event.id}")
  60. except Exception as e:
  61. print(f"Error saving event to DB: {str(e)}")
  62. db.session.rollback()
  63. # Broadcast to admin dashboard
  64. print(f"Broadcasting event: {data}")
  65. emit('game_event', data, broadcast=True)
  66. @socketio.on('universal_event')
  67. def handle_universal_event(data):
  68. # data = {type: 'EventName', package: 'pkg', timestamp: '...', event_data: {...}, player: 'Name'}
  69. print(f"Received universal event: {data.get('type')}")
  70. # Save to DB
  71. try:
  72. event_timestamp = None
  73. if data.get('timestamp'):
  74. try:
  75. event_timestamp = parser.parse(data.get('timestamp'))
  76. except Exception as e:
  77. even_timestamp = datetime.utcnow()
  78. # Flatten event_data to string for content if no content provided
  79. content = data.get('content')
  80. if not content and 'event_data' in data:
  81. content = json.dumps(data.get('event_data'))
  82. # Map to existing schema
  83. event = Event(
  84. event_type=data.get('type'),
  85. player_uuid=data.get('uuid'), # Might be missing in generic events
  86. player_name=data.get('player'),
  87. content=content,
  88. location=data.get('event_data', {}).get('location'), # Try to find location
  89. timestamp=event_timestamp or datetime.utcnow()
  90. )
  91. db.session.add(event)
  92. db.session.commit()
  93. except Exception as e:
  94. print(f"Error saving universal event: {e}")
  95. db.session.rollback()
  96. emit('universal_event', data, broadcast=True)
  97. DEFAULT_IGNORED_EVENTS = {
  98. "org.bukkit.event.player.PlayerMoveEvent",
  99. "org.bukkit.event.player.PlayerInputEvent",
  100. "org.bukkit.event.player.PlayerStatisticIncrementEvent",
  101. "org.bukkit.event.player.PlayerVelocityEvent",
  102. "org.bukkit.event.vehicle.VehicleMoveEvent",
  103. "org.bukkit.event.block.BlockPhysicsEvent",
  104. "org.bukkit.event.world.ChunkLoadEvent",
  105. "org.bukkit.event.world.ChunkUnloadEvent",
  106. "com.destroystokyo.paper.event.server.ServerTickEndEvent",
  107. "com.destroystokyo.paper.event.server.ServerTickStartEvent",
  108. "org.bukkit.event.vehicle.VehicleUpdateEvent",
  109. "org.bukkit.event.entity.EntityAirChangeEvent",
  110. "org.bukkit.event.entity.CreatureSpawnEvent",
  111. "org.bukkit.event.world.GenericGameEvent",
  112. "org.bukkit.event.world.EntitiesLoadEvent",
  113. "org.bukkit.event.world.EntitiesUnloadEvent",
  114. "org.bukkit.event.entity.BatToggleSleepEvent",
  115. "org.bukkit.event.entity.EntityPoseChangeEvent",
  116. "org.bukkit.event.entity.EntityRemoveEvent"
  117. }
  118. @socketio.on('event_metadata')
  119. def handle_event_metadata(data):
  120. from models import EventConfig
  121. print(f"Received event metadata: {len(data.get('events', []))} events registered")
  122. # Sync with DB
  123. received_events = data.get('events', [])
  124. try:
  125. # Get existing configs
  126. existing = {c.event_name: c for c in EventConfig.query.all()}
  127. for event_name in received_events:
  128. if event_name not in existing:
  129. # Add new event
  130. package_name = event_name.rsplit('.', 1)[0]
  131. is_enabled = event_name not in DEFAULT_IGNORED_EVENTS
  132. new_config = EventConfig(event_name=event_name, package_name=package_name, is_enabled=is_enabled)
  133. db.session.add(new_config)
  134. db.session.commit()
  135. # Send back configuration
  136. send_config_update()
  137. except Exception as e:
  138. print(f"Error syncing event config: {e}")
  139. db.session.rollback()
  140. emit('event_metadata', data, broadcast=True)
  141. def send_config_update():
  142. from models import EventConfig
  143. try:
  144. enabled_events = [c.event_name for c in EventConfig.query.filter_by(is_enabled=True).all()]
  145. print(f"Sending config update: {len(enabled_events)} enabled events")
  146. emit('config_update', {'enabled_events': enabled_events}, broadcast=True)
  147. except Exception as e:
  148. print(f"Error sending configs: {e}")
  149. @socketio.on("*")
  150. def handle_any_event(event, methods=None, data=None):
  151. if event not in ['connect', 'disconnect', 'game_event', 'universal_event', 'event_metadata']:
  152. print(f"Server received event: {event} with data: {data}")