1 /*************************************************************************** 2 * (C) Copyright 2003-2015 - Faiumoni e.V. * 3 *************************************************************************** 4 *************************************************************************** 5 * * 6 * This program is free software; you can redistribute it and/or modify * 7 * it under the terms of the GNU General Public License as published by * 8 * the Free Software Foundation; either version 2 of the License, or * 9 * (at your option) any later version. * 10 * * 11 ***************************************************************************/ 12 package games.stendhal.server.script; 13 14 import java.io.IOException; 15 import java.util.List; 16 17 import games.stendhal.common.tiled.LayerDefinition; 18 import games.stendhal.common.tiled.StendhalMapStructure; 19 import games.stendhal.server.core.config.zone.TMXLoader; 20 import games.stendhal.server.core.engine.SingletonRepository; 21 import games.stendhal.server.core.engine.StendhalRPWorld; 22 import games.stendhal.server.core.engine.StendhalRPZone; 23 import games.stendhal.server.core.scripting.ScriptImpl; 24 import games.stendhal.server.entity.player.Player; 25 import marauroa.common.game.IRPZone; 26 27 /** 28 * Replaces a map's data with that loaded from a .tmx. 29 */ 30 public class ChangeMap extends ScriptImpl { 31 @Override execute(final Player admin, final List<String> args)32 public void execute(final Player admin, final List<String> args) { 33 final StendhalRPWorld world = SingletonRepository.getRPWorld(); 34 if (args.size() != 2) { 35 sandbox.privateText(admin, "Usage: /script modified_zone path_to_tmx"); 36 return; 37 } 38 IRPZone zn = world.getRPZone(args.get(0)); 39 if (!(zn instanceof StendhalRPZone)) { 40 sandbox.privateText(admin, "Zone not found: '" + args.get(1) + "'"); 41 return; 42 } 43 StendhalRPZone zone = (StendhalRPZone) zn; 44 StendhalMapStructure map; 45 try { 46 map = TMXLoader.load(args.get(1)); 47 } catch (Exception e) { 48 sandbox.privateText(admin, "Failed to load map: " + e); 49 return; 50 } 51 try { 52 updateZone(zone, map); 53 zone.notifyOnlinePlayers(); 54 } catch (IOException e) { 55 sandbox.privateText(admin, "Failed to update map: " + e); 56 } 57 } 58 59 /** 60 * Update zone from StendhalMapStructure. 61 * 62 * @param zone zone to be updated 63 * @param map new map data 64 * @throws IOException When encoding the layer data fails 65 */ updateZone(StendhalRPZone zone, StendhalMapStructure map)66 private void updateZone(StendhalRPZone zone, StendhalMapStructure map) throws IOException { 67 // FIXME: Add some safety checking. As of now the script allows 68 // replacing any zone with any tmx, whether the size or collisions match. 69 String name = zone.getName(); 70 zone.addTilesets(name + ".tilesets", map.getTilesets()); 71 zone.addLayer(name + ".0_floor", map.getLayer("0_floor")); 72 zone.addLayer(name + ".1_terrain", map.getLayer("1_terrain")); 73 zone.addLayer(name + ".2_object", map.getLayer("2_object")); 74 75 // Roof layers are optional 76 loadOptionalLayer(zone, map, "3_roof"); 77 loadOptionalLayer(zone, map, "4_roof_add"); 78 // Effect layers are optional too 79 loadOptionalLayer(zone, map, "blend_ground"); 80 loadOptionalLayer(zone, map, "blend_roof"); 81 82 zone.addCollisionLayer(name + ".collision", map.getLayer("collision")); 83 zone.addProtectionLayer(name + ".protection", map.getLayer("protection")); 84 // FIXME: Should old spawn points be kept, or change those too? 85 // Currently they are kept. 86 } 87 88 /** 89 * Load an optional layer, if present, to a zone. 90 * 91 * @param zone zone to be updated 92 * @param zonedata new map data 93 * @param layerName name of the layer 94 * @throws IOException When encoding the layer data fails 95 */ loadOptionalLayer(StendhalRPZone zone, StendhalMapStructure zonedata, String layerName)96 private void loadOptionalLayer(StendhalRPZone zone, 97 StendhalMapStructure zonedata, String layerName) throws IOException { 98 LayerDefinition layer = zonedata.getLayer(layerName); 99 if (layer != null) { 100 zone.addLayer(zone.getName() + "." + layerName, layer); 101 } 102 } 103 } 104