-
Notifications
You must be signed in to change notification settings - Fork 24
Implemented Warping #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -40,6 +40,237 @@ def recvAnsConnection(self, packet_id, data, seq): | |||||||||||||||||||||||||||||
| self.server.debug("Connection: {!r}".format(connection_data)) | ||||||||||||||||||||||||||||||
| self.sendNtcLogin(3, connection_data, seq) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def recvReqLayerJump(self, packet_id, data, seq): | ||||||||||||||||||||||||||||||
| """ReqLayerJump packet. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ID: 64100100 | ||||||||||||||||||||||||||||||
| JP: レイヤ移動要求(位置バイナリ) | ||||||||||||||||||||||||||||||
| TR: Layer move request (position binary) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| A relay of the target user's layer_host. | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
| length, unk1, server_id, unk2, gate_id, city_id = struct.unpack_from(">HIIHHH", data) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if self.session.local_info["server_id"] == server_id and\ | ||||||||||||||||||||||||||||||
| self.session.local_info["gate_id"] == gate_id and\ | ||||||||||||||||||||||||||||||
| self.session.local_info["city_id"] == city_id: | ||||||||||||||||||||||||||||||
| self.sendAnsAlert(PatID4.AnsLayerJump, | ||||||||||||||||||||||||||||||
| "<LF=8><BODY><CENTER>You're already there.<END>", | ||||||||||||||||||||||||||||||
| seq) | ||||||||||||||||||||||||||||||
|
Comment on lines
+57
to
+59
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these alert messages necessary? I remember when I was reversing the Warp features, the game performed these checks without asking the server nor sending the packet. Isn't an early |
||||||||||||||||||||||||||||||
| elif self.session.local_info["server_id"] != server_id: | ||||||||||||||||||||||||||||||
| # Different Server | ||||||||||||||||||||||||||||||
| if self.session.get_server_full(server_id) or\ | ||||||||||||||||||||||||||||||
| self.session.get_gate_full(server_id, gate_id) or\ | ||||||||||||||||||||||||||||||
| (city_id and self.session.get_city_full(server_id, gate_id, city_id)): | ||||||||||||||||||||||||||||||
| self.sendAnsAlert(PatID4.AnsLayerJump, | ||||||||||||||||||||||||||||||
| "<LF=8><BODY><CENTER>Destination is full.<END>", | ||||||||||||||||||||||||||||||
| seq) | ||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the previous |
||||||||||||||||||||||||||||||
| # TODO: Lock the gate before the player checks its capacity. | ||||||||||||||||||||||||||||||
| # with self.session.find_gate(server_id, gate_id).lock() | ||||||||||||||||||||||||||||||
| if self.session.local_info["gate_id"] != gate_id: | ||||||||||||||||||||||||||||||
| # Same Server, different Gate | ||||||||||||||||||||||||||||||
| if city_id: | ||||||||||||||||||||||||||||||
| city = self.session.find_city(server_id, gate_id, city_id) | ||||||||||||||||||||||||||||||
| with city.lock(): | ||||||||||||||||||||||||||||||
| if city.is_empty(): | ||||||||||||||||||||||||||||||
| self.sendAnsAlert(PatID4.AnsLayerJump, | ||||||||||||||||||||||||||||||
| "<LF=8><BODY><CENTER>City no longer exists.<END>", | ||||||||||||||||||||||||||||||
| seq) | ||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||
| elif self.session.get_gate_full(server_id, gate_id) or\ | ||||||||||||||||||||||||||||||
| city.is_full(): | ||||||||||||||||||||||||||||||
| self.sendAnsAlert(PatID4.AnsLayerJump, | ||||||||||||||||||||||||||||||
| "<LF=8><BODY><CENTER>Destination is full.<END>", | ||||||||||||||||||||||||||||||
| seq) | ||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Step 1: Leave current location | ||||||||||||||||||||||||||||||
| while self.session.layer > 0: | ||||||||||||||||||||||||||||||
| self.notify_layer_departure() | ||||||||||||||||||||||||||||||
| self.session.layer_up() | ||||||||||||||||||||||||||||||
| # Step 2: Join Gate | ||||||||||||||||||||||||||||||
| self.session.layer_down(gate_id) | ||||||||||||||||||||||||||||||
| user = pati.LayerUserInfo() | ||||||||||||||||||||||||||||||
| user.capcom_id = pati.String(self.session.capcom_id) | ||||||||||||||||||||||||||||||
| user.hunter_name = pati.String(self.session.hunter_name) | ||||||||||||||||||||||||||||||
| user.stats = pati.Binary(self.session.hunter_info.pack()) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| data = pati.lp2_string(self.session.capcom_id) | ||||||||||||||||||||||||||||||
| data += user.pack() | ||||||||||||||||||||||||||||||
| self.server.layer_broadcast(self.session, PatID4.NtcLayerIn, | ||||||||||||||||||||||||||||||
| data, seq) | ||||||||||||||||||||||||||||||
| # Step 3: Join City | ||||||||||||||||||||||||||||||
| self.session.layer_down(city_id) | ||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||
| if self.session.get_gate_full(server_id, gate_id): | ||||||||||||||||||||||||||||||
| self.sendAnsAlert(PatID4.AnsLayerJump, | ||||||||||||||||||||||||||||||
| "<LF=8><BODY><CENTER>Destination is full.<END>", | ||||||||||||||||||||||||||||||
| seq) | ||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Step 1: Leave current location | ||||||||||||||||||||||||||||||
| while self.session.layer > 0: | ||||||||||||||||||||||||||||||
| self.notify_layer_departure() | ||||||||||||||||||||||||||||||
| self.session.layer_up() | ||||||||||||||||||||||||||||||
| # Step 2: Join Gate | ||||||||||||||||||||||||||||||
| self.session.layer_down(gate_id) | ||||||||||||||||||||||||||||||
| user = pati.LayerUserInfo() | ||||||||||||||||||||||||||||||
| user.capcom_id = pati.String(self.session.capcom_id) | ||||||||||||||||||||||||||||||
| user.hunter_name = pati.String(self.session.hunter_name) | ||||||||||||||||||||||||||||||
| user.stats = pati.Binary(self.session.hunter_info.pack()) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| data = pati.lp2_string(self.session.capcom_id) | ||||||||||||||||||||||||||||||
| data += user.pack() | ||||||||||||||||||||||||||||||
| self.server.layer_broadcast(self.session, PatID4.NtcLayerIn, | ||||||||||||||||||||||||||||||
| data, seq) | ||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||
| # Same Server, same Gate | ||||||||||||||||||||||||||||||
| if city_id: | ||||||||||||||||||||||||||||||
| city = self.session.find_city(server_id, gate_id, city_id) | ||||||||||||||||||||||||||||||
| with city.lock(): | ||||||||||||||||||||||||||||||
| if city.is_empty(): | ||||||||||||||||||||||||||||||
| self.sendAnsAlert(PatID4.AnsLayerJump, | ||||||||||||||||||||||||||||||
| "<LF=8><BODY><CENTER>City no longer exists.<END>", | ||||||||||||||||||||||||||||||
| seq) | ||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||
| elif city.is_full(): | ||||||||||||||||||||||||||||||
| self.sendAnsAlert(PatID4.AnsLayerJump, | ||||||||||||||||||||||||||||||
| "<LF=8><BODY><CENTER>Destination is full.<END>", | ||||||||||||||||||||||||||||||
| seq) | ||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Step 1: Leave current location | ||||||||||||||||||||||||||||||
| while self.session.layer > 1: | ||||||||||||||||||||||||||||||
| self.notify_layer_departure() | ||||||||||||||||||||||||||||||
| self.session.layer_up() | ||||||||||||||||||||||||||||||
| # Step 2: Join City | ||||||||||||||||||||||||||||||
| self.session.layer_down(city_id) | ||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||
| # Step 1: Leave current location | ||||||||||||||||||||||||||||||
| while self.session.layer > 1: | ||||||||||||||||||||||||||||||
| self.notify_layer_departure() | ||||||||||||||||||||||||||||||
| self.session.layer_up() | ||||||||||||||||||||||||||||||
| self.sendAnsLayerJump(seq) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def sendAnsLayerJump(self, seq): | ||||||||||||||||||||||||||||||
| """NtcLayerJumpGo packet. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ID: 64170200 | ||||||||||||||||||||||||||||||
| JP: レイヤ予約移動実行返答 | ||||||||||||||||||||||||||||||
| TR: Layer reservation move execution reply | ||||||||||||||||||||||||||||||
|
Comment on lines
+157
to
+162
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
| self.send_packet(PatID4.AnsLayerJump, b"", seq) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def recvReqLayerJumpReady(self, packet_id, data, seq): | ||||||||||||||||||||||||||||||
| """AnsLayerJump packet. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ID: 64100200 | ||||||||||||||||||||||||||||||
| JP: レイヤ移動返答(位置バイナリ) | ||||||||||||||||||||||||||||||
| TR: Layer move reply (position binary) | ||||||||||||||||||||||||||||||
|
Comment on lines
+166
to
+171
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Client asking permission to switch Servers. | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
| length, unk1, server_id, unk2, gate_id, city_id = struct.unpack_from(">HIIHHH", data) | ||||||||||||||||||||||||||||||
| if self.session.get_server_full(server_id) or\ | ||||||||||||||||||||||||||||||
| self.session.get_gate_full(server_id, gate_id) or\ | ||||||||||||||||||||||||||||||
| (city_id and self.session.get_city_full(server_id, gate_id, city_id)): | ||||||||||||||||||||||||||||||
| self.sendAnsAlert(PatID4.NtcLayerJumpReady, | ||||||||||||||||||||||||||||||
| "<LF=8><BODY><CENTER>Destination is full.<END>", | ||||||||||||||||||||||||||||||
| seq) | ||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||
| # Step 1: Leave current location | ||||||||||||||||||||||||||||||
| # ( continued in sendNtcLayerJumpReady() ) | ||||||||||||||||||||||||||||||
| while self.session.layer > 0: | ||||||||||||||||||||||||||||||
| self.notify_layer_departure() | ||||||||||||||||||||||||||||||
| self.session.layer_up() | ||||||||||||||||||||||||||||||
| self.sendNtcLayerJumpReady(seq) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def sendNtcLayerJumpReady(self, seq): | ||||||||||||||||||||||||||||||
| """ReqLayerJumpReady packet. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ID: 64160200 | ||||||||||||||||||||||||||||||
| JP: レイヤ予約移動確認返答 | ||||||||||||||||||||||||||||||
| TR: Layer reservation move confirmation reply | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
|
Comment on lines
+190
to
+196
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
sic: I think this function was wrongly identified when I generated the constants so we should rename it |
||||||||||||||||||||||||||||||
| # Step 2: Join Server | ||||||||||||||||||||||||||||||
| # ( continued in recvReqLayerJumpGo() ) | ||||||||||||||||||||||||||||||
| unk = 0x00000004 | ||||||||||||||||||||||||||||||
| data = struct.pack(">I", unk) | ||||||||||||||||||||||||||||||
| self.send_packet(PatID4.NtcLayerJumpReady, data, seq) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def recvReqLayerJumpGo(self, packet_id, data, seq): | ||||||||||||||||||||||||||||||
| """ReqLayerJumpGo packet. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ID: 64170100 | ||||||||||||||||||||||||||||||
| JP: レイヤ予約移動実行要求 | ||||||||||||||||||||||||||||||
| TR: Layer reserved move execution request | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Client, having switched servers, asking permission | ||||||||||||||||||||||||||||||
| to enter the target gate/city. | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
| length, unk1, server_id, unk2, gate_id, city_id = struct.unpack_from(">HIIHHH", data) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # TODO: Lock the gate before the player checks its capacity. | ||||||||||||||||||||||||||||||
| # with self.session.find_gate(server_id, gate_id).lock() | ||||||||||||||||||||||||||||||
| if city_id: | ||||||||||||||||||||||||||||||
| city = self.session.find_city(server_id, gate_id, city_id) | ||||||||||||||||||||||||||||||
| with city.lock(): | ||||||||||||||||||||||||||||||
| if city.is_empty(): | ||||||||||||||||||||||||||||||
| self.sendAnsAlert(PatID4.AnsLayerJump, | ||||||||||||||||||||||||||||||
| "<LF=8><BODY><CENTER>City no longer exists.<END>", | ||||||||||||||||||||||||||||||
| seq) | ||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||
| elif self.session.get_gate_full(server_id, gate_id) or\ | ||||||||||||||||||||||||||||||
| city.is_full(): | ||||||||||||||||||||||||||||||
| self.sendAnsAlert(PatID4.AnsLayerCreateHead, | ||||||||||||||||||||||||||||||
| "<LF=8><BODY><CENTER>Destination is full.<END>", | ||||||||||||||||||||||||||||||
| seq) | ||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Step 3: Join Gate | ||||||||||||||||||||||||||||||
| self.session.layer_down(gate_id) | ||||||||||||||||||||||||||||||
| user = pati.LayerUserInfo() | ||||||||||||||||||||||||||||||
| user.capcom_id = pati.String(self.session.capcom_id) | ||||||||||||||||||||||||||||||
| user.hunter_name = pati.String(self.session.hunter_name) | ||||||||||||||||||||||||||||||
| user.stats = pati.Binary(self.session.hunter_info.pack()) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| data = pati.lp2_string(self.session.capcom_id) | ||||||||||||||||||||||||||||||
| data += user.pack() | ||||||||||||||||||||||||||||||
| self.server.layer_broadcast(self.session, PatID4.NtcLayerIn, | ||||||||||||||||||||||||||||||
| data, seq) | ||||||||||||||||||||||||||||||
| # Step 4: Join City | ||||||||||||||||||||||||||||||
| self.session.layer_down(city_id) | ||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||
| if self.session.get_gate_full(server_id, gate_id): | ||||||||||||||||||||||||||||||
| self.sendAnsAlert(PatID4.AnsLayerCreateHead, | ||||||||||||||||||||||||||||||
| "<LF=8><BODY><CENTER>Destination is full.<END>", | ||||||||||||||||||||||||||||||
| seq) | ||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Step 3: Join Gate | ||||||||||||||||||||||||||||||
| self.session.layer_down(gate_id) | ||||||||||||||||||||||||||||||
| user = pati.LayerUserInfo() | ||||||||||||||||||||||||||||||
| user.capcom_id = pati.String(self.session.capcom_id) | ||||||||||||||||||||||||||||||
| user.hunter_name = pati.String(self.session.hunter_name) | ||||||||||||||||||||||||||||||
| user.stats = pati.Binary(self.session.hunter_info.pack()) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| data = pati.lp2_string(self.session.capcom_id) | ||||||||||||||||||||||||||||||
| data += user.pack() | ||||||||||||||||||||||||||||||
| self.server.layer_broadcast(self.session, PatID4.NtcLayerIn, | ||||||||||||||||||||||||||||||
| data, seq) | ||||||||||||||||||||||||||||||
| self.sendNtcLayerJumpGo(seq) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def sendNtcLayerJumpGo(self, seq): | ||||||||||||||||||||||||||||||
| """NtcLayerJumpGo packet. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ID: 64170200 | ||||||||||||||||||||||||||||||
| JP: レイヤ予約移動実行返答 | ||||||||||||||||||||||||||||||
| TR: Layer reservation move execution reply | ||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||
|
Comment on lines
+265
to
+271
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sic: Ditto, regarding its name. Feel free to ignore this comment. |
||||||||||||||||||||||||||||||
| self.send_packet(PatID4.NtcLayerJumpGo, b"", seq) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| def sendAnsLayerDown(self, layer_id, layer_set, seq): | ||||||||||||||||||||||||||||||
| """AnsLayerDown packet. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
@@ -433,7 +664,6 @@ def sendAnsCircleMatchOptionSet(self, options, seq): | |||||||||||||||||||||||||||||
| pati.unpack_byte(options.is_standby) == 1 | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| self.session.set_circle_standby(is_standby) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| circle = self.session.get_circle() | ||||||||||||||||||||||||||||||
| options.capcom_id = pati.String(self.session.capcom_id) | ||||||||||||||||||||||||||||||
| options.hunter_name = pati.String(self.session.hunter_name) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -139,6 +139,24 @@ def get_server(self): | |
| assert self.local_info['server_id'] is not None | ||
| return DB.get_server(self.local_info['server_id']) | ||
|
|
||
| def get_server_full(self, server_id): | ||
| return DB.get_server(server_id).is_full() | ||
|
|
||
| def get_gate_full(self, server_id, gate_id): | ||
| return DB.get_gate(server_id, gate_id).is_full() | ||
|
|
||
| def get_city_full(self, server_id, gate_id, city_id): | ||
| return DB.get_city(server_id, gate_id, city_id).is_full() | ||
|
|
||
| def get_city_empty(self, server_id, gate_id, city_id): | ||
| return DB.get_city(server_id, gate_id, city_id).is_empty() | ||
|
|
||
| def find_gate(self, server_id, gate_id): | ||
| return DB.get_gate(server_id, gate_id) | ||
|
|
||
| def find_city(self, server_id, gate_id, city_id): | ||
| return DB.get_city(server_id, gate_id, city_id) | ||
|
Comment on lines
+142
to
+158
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm really not a huge fan of this since the I'll let it slide for now since we don't provide a better abstraction to query the database directly, especially for other servers. AFAICT, this point seems still valid with the |
||
|
|
||
| def get_gate(self): | ||
| assert self.local_info['gate_id'] is not None | ||
| return DB.get_gate(self.local_info['server_id'], | ||
|
|
@@ -287,6 +305,12 @@ def leave_city(self): | |
| DB.leave_city(self) | ||
| self.state = SessionState.GATE | ||
|
|
||
| def is_in_city(self): | ||
| return self.state == SessionState.CITY or\ | ||
| self.state == SessionState.CIRCLE or\ | ||
| self.state == SessionState.CIRCLE_STANDBY or\ | ||
| self.state == SessionState.QUEST | ||
|
Comment on lines
+309
to
+312
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. return self.state in (SessionState.CITY, SessionState.CIRCLE,
SessionState.CIRCLE_STANDBY, SessionState.QUEST) |
||
|
|
||
| def try_transfer_city_leadership(self): | ||
| if self.local_info['city_id'] is None: | ||
| return None | ||
|
|
@@ -368,7 +392,7 @@ def get_layer_players(self): | |
|
|
||
| def get_layer_host_data(self): | ||
| """LayerUserInfo's layer_host.""" | ||
| return struct.pack("IIHHH", | ||
| return struct.pack(">IIHHH", | ||
| 3, # layer depth? | ||
| self.local_info["server_id"] or 0, | ||
| 1, # ??? | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add a comment stating that this code is "racy" and the sanity checks are provided on a best-efforts basis.
As already stated we have no reasonable way to ensure the validity of these pieces of information. Preventing the warp due to outdated information is fine, IMHO. Indeed, we have no control over the other distant servers and their state can change between our check and the warp. The worst case being: a server changing from being available to full which these checks can't account for unless we lock the whole server.
Moreover, enforcing/locking a city or even worse a gate or server will severely harm performance, even more so if it's a distant peer. Which will prevent all its population to alter its state when someone is warping to it. If there are no strong reasons, you should avoid using lock here or add a comment to justify its benefits.
For instance, locking a city or a gate from another (distant) server shouldn't be possible. I really doubt that Capcom did these sanity checks anyway, though, I might be wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking about that, and my idea was that they would have a method of communicating to the other server to reserve a slot. That way you avoid having an issue of state changing mid flight. But I don't know if they actually did that or if it would be fast enough to not create a noticeable slowdown in the process.