Fix portal recognition/cache/repair timing
This commit is contained in:
@@ -455,3 +455,11 @@ Karena project ini menargetkan Java 25, compile final sebaiknya dilakukan menggu
|
|||||||
## License
|
## License
|
||||||
|
|
||||||
Lobby Systems is **proprietary software — All Rights Reserved**. Public access to this repository is for viewing, auditing, and reference only. Using, running, compiling, modifying, redistributing, or re-uploading the mod requires prior written permission from DartoKloning. See [`LICENSE`](LICENSE) for the complete terms.
|
Lobby Systems is **proprietary software — All Rights Reserved**. Public access to this repository is for viewing, auditing, and reference only. Using, running, compiling, modifying, redistributing, or re-uploading the mod requires prior written permission from DartoKloning. See [`LICENSE`](LICENSE) for the complete terms.
|
||||||
|
|
||||||
|
|
||||||
|
## v1.6.1
|
||||||
|
|
||||||
|
- Fixed a newly-created Lobby Systems visual portal being able to use vanilla Nether routing on its first entry.
|
||||||
|
- Managed `minecraft:nether_portal` surfaces are now explicitly intercepted so Lobby Systems exclusively owns their destination.
|
||||||
|
- Reduced the creator-side post-create trigger suppression from the old 100-tick window to the configured portal check interval.
|
||||||
|
- Added the Lobby Systems mod icon to Fabric metadata.
|
||||||
|
|||||||
+1
-1
@@ -5,6 +5,6 @@ minecraft_version=26.2
|
|||||||
loader_version=0.19.3
|
loader_version=0.19.3
|
||||||
loom_version=1.17-SNAPSHOT
|
loom_version=1.17-SNAPSHOT
|
||||||
fabric_api_version=0.156.0+26.2
|
fabric_api_version=0.156.0+26.2
|
||||||
mod_version=1.6.0
|
mod_version=1.6.1
|
||||||
maven_group=id.dartokloning
|
maven_group=id.dartokloning
|
||||||
archives_base_name=lobby-systems
|
archives_base_name=lobby-systems
|
||||||
|
|||||||
@@ -49,6 +49,17 @@ public final class LobbySystemsMod implements ModInitializer {
|
|||||||
private static final StarterKitManager STARTER_KITS = new StarterKitManager();
|
private static final StarterKitManager STARTER_KITS = new StarterKitManager();
|
||||||
private static int saveTicker;
|
private static int saveTicker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by the NetherPortalBlock mixin to distinguish Lobby Systems visual
|
||||||
|
* portals from ordinary vanilla Nether portals.
|
||||||
|
*/
|
||||||
|
public static boolean isManagedPortalBlock(Level level, BlockPos pos) {
|
||||||
|
if (level == null || pos == null) return false;
|
||||||
|
return PORTALS.isManagedVisualBlock(
|
||||||
|
level.dimension().identifier().toString(),
|
||||||
|
pos.getX(), pos.getY(), pos.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
LobbyLog.startup();
|
LobbyLog.startup();
|
||||||
@@ -885,7 +896,11 @@ public final class LobbySystemsMod implements ModInitializer {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PORTALS.suppress(player.getUUID(), Math.max(CONFIG.get().portalCooldownTicks, 100));
|
// Only guard the command tick itself. Older builds suppressed the
|
||||||
|
// creator for at least 100 ticks, which left a window where the custom
|
||||||
|
// portal trigger was disabled while vanilla Nether routing was still
|
||||||
|
// active. The NetherPortalBlock mixin now owns that vanilla suppression.
|
||||||
|
PORTALS.suppress(player.getUUID(), Math.max(1, CONFIG.get().portalCheckIntervalTicks));
|
||||||
player.sendSystemMessage(Component.literal(
|
player.sendSystemMessage(Component.literal(
|
||||||
"§aPortal §f" + name + "§a dibuat. §7" + portal.sourceDimension + " §8→ §f" + targetId
|
"§aPortal §f" + name + "§a dibuat. §7" + portal.sourceDimension + " §8→ §f" + targetId
|
||||||
+ "\n§dVisual portal aktif §7(" + visualBlocks + " blok, axis=" + visualAxis + ")."
|
+ "\n§dVisual portal aktif §7(" + visualBlocks + " blok, axis=" + visualAxis + ")."
|
||||||
|
|||||||
@@ -85,6 +85,30 @@ public final class PortalManager {
|
|||||||
return portals.size();
|
return portals.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true when the given block position belongs to a Lobby Systems
|
||||||
|
* portal that uses vanilla nether_portal only as its visual surface.
|
||||||
|
*
|
||||||
|
* Vanilla portal routing must be suppressed for these blocks; Lobby Systems
|
||||||
|
* is the sole owner of their destination.
|
||||||
|
*/
|
||||||
|
public boolean isManagedVisualBlock(String dimension, int x, int y, int z) {
|
||||||
|
List<Map.Entry<String, PortalDefinition>> candidates = byDimension.get(dimension);
|
||||||
|
if (candidates == null || candidates.isEmpty()) return false;
|
||||||
|
|
||||||
|
// Test the center of the block against the inclusive WorldEdit region.
|
||||||
|
double cx = x + 0.5D;
|
||||||
|
double cy = y + 0.5D;
|
||||||
|
double cz = z + 0.5D;
|
||||||
|
for (Map.Entry<String, PortalDefinition> entry : candidates) {
|
||||||
|
PortalDefinition portal = entry.getValue();
|
||||||
|
if (portal.hasNetherPortalVisual() && portal.contains(cx, cy, cz)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void tick(MinecraftServer server, int intervalTicks, int cooldownTicks, PortalTrigger trigger) {
|
public void tick(MinecraftServer server, int intervalTicks, int cooldownTicks, PortalTrigger trigger) {
|
||||||
tick++;
|
tick++;
|
||||||
cooldownUntil.entrySet().removeIf(e -> e.getValue() <= tick);
|
cooldownUntil.entrySet().removeIf(e -> e.getValue() <= tick);
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package id.dartokloning.lobbysystems.mixin;
|
||||||
|
|
||||||
|
import id.dartokloning.lobbysystems.LobbySystemsMod;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.InsideBlockEffectApplier;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.NetherPortalBlock;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.portal.TeleportTransition;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes vanilla nether_portal blocks inside Lobby Systems portal regions purely
|
||||||
|
* visual. Ordinary Nether portals outside managed regions keep vanilla behavior.
|
||||||
|
*/
|
||||||
|
@Mixin(NetherPortalBlock.class)
|
||||||
|
public abstract class NetherPortalBlockMixin {
|
||||||
|
|
||||||
|
@Inject(method = "entityInside", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void dartokloning$cancelVanillaPortalEntry(
|
||||||
|
BlockState state,
|
||||||
|
Level level,
|
||||||
|
BlockPos pos,
|
||||||
|
Entity entity,
|
||||||
|
InsideBlockEffectApplier effectApplier,
|
||||||
|
boolean isPrecise,
|
||||||
|
CallbackInfo ci) {
|
||||||
|
if (!level.isClientSide() && LobbySystemsMod.isManagedPortalBlock(level, pos)) {
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defense in depth: if another mod or a stale portal processor reaches the
|
||||||
|
// destination lookup anyway, managed Lobby Systems portal blocks still never
|
||||||
|
// resolve through vanilla Nether routing.
|
||||||
|
@Inject(method = "getPortalDestination", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void dartokloning$cancelVanillaDestination(
|
||||||
|
ServerLevel currentLevel,
|
||||||
|
Entity entity,
|
||||||
|
BlockPos portalEntryPos,
|
||||||
|
CallbackInfoReturnable<TeleportTransition> cir) {
|
||||||
|
if (LobbySystemsMod.isManagedPortalBlock(currentLevel, portalEntryPos)) {
|
||||||
|
cir.setReturnValue(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 112 KiB |
@@ -28,5 +28,6 @@
|
|||||||
],
|
],
|
||||||
"breaks": {
|
"breaks": {
|
||||||
"world-gamerules": "*"
|
"world-gamerules": "*"
|
||||||
}
|
},
|
||||||
|
"icon": "assets/dartokloning/icon.png"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
"compatibilityLevel": "JAVA_25",
|
"compatibilityLevel": "JAVA_25",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"ServerLevelGameRulesMixin",
|
"ServerLevelGameRulesMixin",
|
||||||
"PlayerListMixin"
|
"PlayerListMixin",
|
||||||
|
"NetherPortalBlockMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
|||||||
Reference in New Issue
Block a user