diff --git a/src/main/java/scripting/portal/PortalScriptManager.java b/src/main/java/scripting/portal/PortalScriptManager.java index f147afc096a..225d16856f3 100644 --- a/src/main/java/scripting/portal/PortalScriptManager.java +++ b/src/main/java/scripting/portal/PortalScriptManager.java @@ -43,7 +43,18 @@ public static PortalScriptManager getInstance() { return instance; } + public boolean isScriptAvailable(String scriptPath) { + ScriptEngine engine = getInvocableScriptEngine(scriptPath); + + return engine instanceof Invocable; + } + private PortalScript getPortalScript(String scriptName) throws ScriptException { + // Additional protection in case fallback has some issue + if (scriptName == null || scriptName.isEmpty()) { + return null; + } + String scriptPath = "portal/" + scriptName + ".js"; PortalScript script = scripts.get(scriptPath); if (script != null) { diff --git a/src/main/java/server/maps/MapFactory.java b/src/main/java/server/maps/MapFactory.java index a1c3f14c218..16da1b9c801 100644 --- a/src/main/java/server/maps/MapFactory.java +++ b/src/main/java/server/maps/MapFactory.java @@ -160,7 +160,7 @@ public static MapleMap loadMapFromWz(int mapid, int world, int channel, EventIns map.setMobInterval((short) DataTool.getInt(infoData.getChildByPath("createMobInterval"), 5000)); PortalFactory portalFactory = new PortalFactory(); for (Data portal : mapData.getChildByPath("portal")) { - map.addPortal(portalFactory.makePortal(DataTool.getInt(portal.getChildByPath("pt")), portal)); + map.addPortal(portalFactory.makePortal(DataTool.getInt(portal.getChildByPath("pt")), map.getId(), portal)); } Data timeMob = infoData.getChildByPath("timeMob"); if (timeMob != null) { diff --git a/src/main/java/server/maps/PortalFactory.java b/src/main/java/server/maps/PortalFactory.java index 58c4784ef37..a6bbb0cc21e 100644 --- a/src/main/java/server/maps/PortalFactory.java +++ b/src/main/java/server/maps/PortalFactory.java @@ -23,6 +23,7 @@ import provider.Data; import provider.DataTool; +import scripting.portal.PortalScriptManager; import java.awt.*; @@ -33,18 +34,18 @@ public PortalFactory() { nextDoorPortal = 0x80; } - public Portal makePortal(int type, Data portal) { + public Portal makePortal(int type, int mapId, Data portal) { GenericPortal ret = null; if (type == Portal.MAP_PORTAL) { ret = new MapPortal(); } else { ret = new GenericPortal(type); } - loadPortal(ret, portal); + loadPortal(ret, mapId, portal); return ret; } - private void loadPortal(GenericPortal myPortal, Data portal) { + private void loadPortal(GenericPortal myPortal, int mapId, Data portal) { myPortal.setName(DataTool.getString(portal.getChildByPath("pn"))); myPortal.setTarget(DataTool.getString(portal.getChildByPath("tn"))); myPortal.setTargetMapId(DataTool.getInt(portal.getChildByPath("tm"))); @@ -52,15 +53,29 @@ private void loadPortal(GenericPortal myPortal, Data portal) { int y = DataTool.getInt(portal.getChildByPath("y")); myPortal.setPosition(new Point(x, y)); String script = DataTool.getString("script", portal, null); - if (script != null && script.equals("")) { - script = null; - } - myPortal.setScriptName(script); if (myPortal.getType() == Portal.DOOR_PORTAL) { myPortal.setId(nextDoorPortal); nextDoorPortal++; } else { myPortal.setId(Integer.parseInt(portal.getName())); } + + // If no script node is set, try to find the fallback script and set it + // otherwise, don't set the script name. Portals break if the script is not found + // and a portal name is set. + if (script != null && !script.isBlank()) { + myPortal.setScriptName(script); + return; + } + + // Check for and set fallback portal script name if available + String fallbackScriptPath = String.format("%s_%s", mapId, portal.getName()); + boolean isScriptAvailable = PortalScriptManager.getInstance().isScriptAvailable("portal/" + fallbackScriptPath + ".js"); + + if (!isScriptAvailable) { + return; + } + + myPortal.setScriptName(fallbackScriptPath); } }