Actually enforce the iris shield instead of only rendering it
The shield's closed/open state only ever controlled the iris block's appearance (bedrock vs water) - the teleport listener never checked it, only whether the gate was open+outgoing. A solid bedrock block stops normal walking, but nothing stopped a player who ended up standing there anyway (flight, elytra, a vehicle) from still getting teleported, which is what was reported: iris visibly closed, travel still worked. findOutgoingGateAt() now skips any gate whose iris is closed, and both teleportPlayer()/teleportEntity() also refuse the trip if the DESTINATION's shield is closed, matching a real iris blocking whatever hits it from either side. Same check added to the cross-server delivery path in CrossServerBridge for the race where the shield closes between the proxy request and the player landing.
This commit is contained in:
@@ -84,11 +84,16 @@ material, unsealed interior, too far from the sign, etc.
|
|||||||
- The **iris shield** is a separate, physical thing from the wormhole connection.
|
- The **iris shield** is a separate, physical thing from the wormhole connection.
|
||||||
**Right-click a button placed directly below the sign** to toggle it. Closed means
|
**Right-click a button placed directly below the sign** to toggle it. Closed means
|
||||||
closed - `gate.iris-shield-material` (default bedrock), solid, blocking everything -
|
closed - `gate.iris-shield-material` (default bedrock), solid, blocking everything -
|
||||||
whether or not the gate is even connected right now. With the shield open, the
|
whether or not the gate is even connected right now, and travel is refused even if
|
||||||
interior just reflects the connection state: `gate.iris-idle-material` (default air)
|
something manages to occupy that space anyway (flight, an elytra, a vehicle - not
|
||||||
if idle, or the event horizon if actively dialed. Closing needs nothing extra;
|
just relying on block collision). It blocks in both directions: a closed shield on
|
||||||
if the gate has a pin set (`/sg pin <code>`), opening a closed shield prompts you
|
the gate you're dialing *from* stops you from ever stepping in, and a closed shield
|
||||||
to type the code in chat within `gate.pin-timeout-seconds` before it'll open.
|
on the *destination* refuses the trip too, matching a real iris stopping anything
|
||||||
|
that hits it from either side. With the shield open, the interior just reflects the
|
||||||
|
connection state: `gate.iris-idle-material` (default air) if idle, or the event
|
||||||
|
horizon if actively dialed. Closing needs nothing extra; if the gate has a pin set
|
||||||
|
(`/sg pin <code>`), opening a closed shield prompts you to type the code in chat
|
||||||
|
within `gate.pin-timeout-seconds` before it'll open.
|
||||||
|
|
||||||
## Multi-world
|
## Multi-world
|
||||||
|
|
||||||
|
|||||||
+7
@@ -85,6 +85,7 @@ public class GateTeleportListener implements Listener {
|
|||||||
List<RuntimeGate> gates = gateManager.all();
|
List<RuntimeGate> gates = gateManager.all();
|
||||||
for (RuntimeGate rg : gates) {
|
for (RuntimeGate rg : gates) {
|
||||||
if (!rg.isOpen() || !rg.isOutgoing() || rg.getStructure() == null || rg.getConnectedTo() == null) continue;
|
if (!rg.isOpen() || !rg.isOutgoing() || rg.getStructure() == null || rg.getConnectedTo() == null) continue;
|
||||||
|
if (rg.getGate().isIrisClosed()) continue; // shield blocks travel even on a connected gate
|
||||||
for (Block iris : rg.getStructure().getIris()) {
|
for (Block iris : rg.getStructure().getIris()) {
|
||||||
if (iris.getX() == standing.getX() && iris.getY() == standing.getY() && iris.getZ() == standing.getZ()
|
if (iris.getX() == standing.getX() && iris.getY() == standing.getY() && iris.getZ() == standing.getZ()
|
||||||
&& iris.getWorld().equals(standing.getWorld())) {
|
&& iris.getWorld().equals(standing.getWorld())) {
|
||||||
@@ -98,6 +99,11 @@ public class GateTeleportListener implements Listener {
|
|||||||
private void teleportPlayer(Player player, RuntimeGate entered) {
|
private void teleportPlayer(Player player, RuntimeGate entered) {
|
||||||
RuntimeGate dest = entered.getConnectedTo();
|
RuntimeGate dest = entered.getConnectedTo();
|
||||||
if (dest == null) return;
|
if (dest == null) return;
|
||||||
|
if (dest.getGate().isIrisClosed()) {
|
||||||
|
player.sendMessage(net.kyori.adventure.text.Component.text(
|
||||||
|
"The iris on the other end is closed.", net.kyori.adventure.text.format.NamedTextColor.RED));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Location loc = player.getLocation();
|
Location loc = player.getLocation();
|
||||||
Vector direction = loc.getDirection();
|
Vector direction = loc.getDirection();
|
||||||
@@ -121,6 +127,7 @@ public class GateTeleportListener implements Listener {
|
|||||||
private void teleportEntity(Entity entity, RuntimeGate entered) {
|
private void teleportEntity(Entity entity, RuntimeGate entered) {
|
||||||
RuntimeGate dest = entered.getConnectedTo();
|
RuntimeGate dest = entered.getConnectedTo();
|
||||||
if (dest == null) return;
|
if (dest == null) return;
|
||||||
|
if (dest.getGate().isIrisClosed()) return; // shield blocks arrival too
|
||||||
if (!dest.getGate().getServerId().equals(plugin.getServerId())) return; // no cross-server carry for non-players
|
if (!dest.getGate().getServerId().equals(plugin.getServerId())) return; // no cross-server carry for non-players
|
||||||
|
|
||||||
Location loc = entity.getLocation();
|
Location loc = entity.getLocation();
|
||||||
|
|||||||
+8
@@ -79,6 +79,14 @@ public class CrossServerBridge implements PluginMessageListener {
|
|||||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||||
Player p = Bukkit.getPlayer(playerId);
|
Player p = Bukkit.getPlayer(playerId);
|
||||||
if (p == null) return;
|
if (p == null) return;
|
||||||
|
if (rg.getGate().isIrisClosed()) {
|
||||||
|
// the shield closed between the request and arrival - can't send them back
|
||||||
|
// through the proxy, so just leave them at this server's default spawn
|
||||||
|
p.sendMessage(net.kyori.adventure.text.Component.text(
|
||||||
|
"The iris on the other end closed before you arrived.",
|
||||||
|
net.kyori.adventure.text.format.NamedTextColor.RED));
|
||||||
|
return;
|
||||||
|
}
|
||||||
double yawRad = Math.toRadians(yaw);
|
double yawRad = Math.toRadians(yaw);
|
||||||
Vector direction = new Vector(-Math.sin(yawRad), 0, Math.cos(yawRad));
|
Vector direction = new Vector(-Math.sin(yawRad), 0, Math.cos(yawRad));
|
||||||
Location landing = gateManager.computeSafeLanding(rg, direction, yaw, pitch);
|
Location landing = gateManager.computeSafeLanding(rg, direction, yaw, pitch);
|
||||||
|
|||||||
Reference in New Issue
Block a user