113 lines
3.5 KiB
Python
113 lines
3.5 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import socket
|
|
import time
|
|
import unittest
|
|
|
|
from client_session import ClientSession
|
|
from fake_player import FakePlayerClient, STATUS_CONNECTED
|
|
from server_core import FalloutTogetherServer
|
|
|
|
|
|
class CombatProtocolTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.sender_server, self.sender_peer = socket.socketpair()
|
|
self.target_server, self.target_peer = socket.socketpair()
|
|
self.server = FalloutTogetherServer()
|
|
self.sender = ClientSession(
|
|
self.sender_server,
|
|
("local", 1),
|
|
1,
|
|
time.time(),
|
|
)
|
|
self.target = ClientSession(
|
|
self.target_server,
|
|
("local", 2),
|
|
2,
|
|
time.time(),
|
|
)
|
|
self.sender.mark_gameplay_active(1)
|
|
self.target.mark_gameplay_active(1)
|
|
self.server._init_rate_state(self.sender, time.monotonic())
|
|
self.server._init_rate_state(self.target, time.monotonic())
|
|
self.server._clients = {
|
|
self.sender_server: self.sender,
|
|
self.target_server: self.target,
|
|
}
|
|
|
|
def tearDown(self) -> None:
|
|
for connection in (
|
|
self.sender_server,
|
|
self.sender_peer,
|
|
self.target_server,
|
|
self.target_peer,
|
|
):
|
|
connection.close()
|
|
|
|
def test_combat_hit_is_authoritative_and_targeted(self) -> None:
|
|
self.server._handle_line(
|
|
self.sender,
|
|
json.dumps(
|
|
{
|
|
"type": "combatHit",
|
|
"playerId": 999,
|
|
"sequence": 7,
|
|
"targetPlayerId": 2,
|
|
"damage": 12.5,
|
|
"weaponFormId": "1f4a6",
|
|
}
|
|
),
|
|
)
|
|
|
|
routed = json.loads(self.target_peer.recv(4096))
|
|
self.assertEqual(routed["playerId"], 1)
|
|
self.assertEqual(routed["targetPlayerId"], 2)
|
|
self.assertEqual(routed["weaponFormId"], "0001F4A6")
|
|
|
|
self.sender_peer.setblocking(False)
|
|
with self.assertRaises(BlockingIOError):
|
|
self.sender_peer.recv(1)
|
|
|
|
def test_invalid_damage_is_not_routed(self) -> None:
|
|
self.server._handle_line(
|
|
self.sender,
|
|
'{"type":"combatHit","sequence":8,"targetPlayerId":2,"damage":NaN}',
|
|
)
|
|
|
|
self.target_peer.setblocking(False)
|
|
with self.assertRaises(BlockingIOError):
|
|
self.target_peer.recv(1)
|
|
|
|
|
|
class FakePlayerCombatHelperTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.fake_socket, self.peer_socket = socket.socketpair()
|
|
self.fake = FakePlayerClient(1, "test")
|
|
self.fake._socket = self.fake_socket
|
|
self.fake._status = STATUS_CONNECTED
|
|
|
|
def tearDown(self) -> None:
|
|
self.fake_socket.close()
|
|
self.peer_socket.close()
|
|
|
|
def test_ranged_fire_action_helper(self) -> None:
|
|
self.fake.send_ranged_fire_action()
|
|
packet = json.loads(self.peer_socket.recv(4096))
|
|
|
|
self.assertTrue(packet["weaponDrawn"])
|
|
self.assertEqual(packet["actionEvents"][0]["type"], 3)
|
|
self.assertEqual(packet["actionEvents"][0]["eventName"], "fireSingle")
|
|
|
|
def test_combat_hit_helper(self) -> None:
|
|
self.fake.send_combat_hit(2, 9.5, 0x1F4A6)
|
|
packet = json.loads(self.peer_socket.recv(4096))
|
|
|
|
self.assertEqual(packet["type"], "combatHit")
|
|
self.assertEqual(packet["targetPlayerId"], 2)
|
|
self.assertEqual(packet["weaponFormId"], "0001F4A6")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|