From 5a62128a64eb7f78b6edb058ad4f729c3d81427e Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Tue, 7 Sep 2010 20:40:36 +0000 Subject: [PATCH 01/17] updated version --- build.ant.properties | 2 +- libs/marauroa.jar | Bin 316026 -> 316026 bytes runserver.bat | 2 +- runserver.sh | 2 +- src/games/stendhal/client/update/Version.java | 2 +- src/games/stendhal/common/Debug.java | 2 +- .../server/core/engine/GenerateINI.java | 2 +- stendhal.jnlp | 2 +- 8 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.ant.properties b/build.ant.properties index 47054a84ad..5bfbd8acc4 100644 --- a/build.ant.properties +++ b/build.ant.properties @@ -73,7 +73,7 @@ version_server = http://arianne.sourceforge.net/stendhal.version # current version of stendhal version.old = 0.86 -version = 0.86.5 +version = 0.87 # javac options javac.deprecation = true diff --git a/libs/marauroa.jar b/libs/marauroa.jar index dfae3eaff05717d7d34e05783ab7967019cc9d65..37274e7c5586208ba7d4a3f1bc1eeda8abc87434 100644 GIT binary patch delta 9076 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 delta 9070 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 diff --git a/runserver.bat b/runserver.bat index 06ecf05e0e..5d7c5c9346 100644 --- a/runserver.bat +++ b/runserver.bat @@ -1,3 +1,3 @@ -set STENDHAL_VERSION=0.86.5 +set STENDHAL_VERSION=0.87 set LOCALCLASSPATH=.;data\script;data\conf;stendhal-server-%STENDHAL_VERSION%.jar;marauroa.jar;mysql-connector.jar;log4j.jar;commons-lang.jar;h2.jar java -Xmx400m -cp "%LOCALCLASSPATH%" marauroa.server.marauroad -c server.ini -l diff --git a/runserver.sh b/runserver.sh index fe021deaf6..b9fc9ea23c 100644 --- a/runserver.sh +++ b/runserver.sh @@ -1,5 +1,5 @@ #!/bin/sh -STENDHAL_VERSION="0.86.5" +STENDHAL_VERSION="0.87" LOCALCLASSPATH=.:data/script/:data/conf/:stendhal-server-$STENDHAL_VERSION.jar:marauroa.jar:mysql-connector.jar:log4j.jar:commons-lang.jar:h2.jar diff --git a/src/games/stendhal/client/update/Version.java b/src/games/stendhal/client/update/Version.java index 71fcf50812..0c4b2125ae 100644 --- a/src/games/stendhal/client/update/Version.java +++ b/src/games/stendhal/client/update/Version.java @@ -10,7 +10,7 @@ package games.stendhal.client.update; public class Version { /** Version Number. */ - public static final String VERSION = "0.86.5"; + public static final String VERSION = "0.87"; /** * Extract the specified number of parts from a version-string. diff --git a/src/games/stendhal/common/Debug.java b/src/games/stendhal/common/Debug.java index c66edb3afd..5ebf9bf13d 100644 --- a/src/games/stendhal/common/Debug.java +++ b/src/games/stendhal/common/Debug.java @@ -25,7 +25,7 @@ public interface Debug { /** server version. */ // Note: This line is updated by build.xml using a regexp so be sure to adjust it in case you modify this line. - String VERSION = "0.86.5"; + String VERSION = "0.87"; /** diff --git a/src/games/stendhal/server/core/engine/GenerateINI.java b/src/games/stendhal/server/core/engine/GenerateINI.java index fcf8d71b38..cabea6f577 100644 --- a/src/games/stendhal/server/core/engine/GenerateINI.java +++ b/src/games/stendhal/server/core/engine/GenerateINI.java @@ -234,7 +234,7 @@ public class GenerateINI { out.println(); out.println("server_typeGame=" + gameName); out.println("server_name=" + gameName + " Marauroa server"); - out.println("server_version=0.86.5"); + out.println("server_version=0.87"); out.println("server_contact=https://sourceforge.net/tracker/?atid=514826&group_id=66537&func=browse"); out.println(); out.println("# Extensions configured on the server. Enable at will."); diff --git a/stendhal.jnlp b/stendhal.jnlp index 72bf6f02ca..9a1634b415 100644 --- a/stendhal.jnlp +++ b/stendhal.jnlp @@ -22,7 +22,7 @@ Some of these people are NPC, they will give you tasks to accomplish and hints t - + From 77138c75ac028e550bf7c3f194066006b9c63ba3 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Tue, 7 Sep 2010 21:05:50 +0000 Subject: [PATCH 02/17] disabled notification (madmetzger) --- .../server/core/events/achievements/AchievementNotifier.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java b/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java index 0d68d3d707..2286acb5da 100644 --- a/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java +++ b/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java @@ -240,7 +240,7 @@ public class AchievementNotifier { */ private void notifyPlayerAboutReachedAchievement(Player player, Achievement achievement) { - player.sendPrivateText("Congratulations! You have reached the "+achievement.getTitle()+" achievement!"); +// player.sendPrivateText("Congratulations! You have reached the "+achievement.getTitle()+" achievement!"); } /** From 80309069be99f81d89da93f9eee821d296992dce Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Tue, 7 Sep 2010 21:36:06 +0000 Subject: [PATCH 03/17] use full form for internal names of achievements (fixes #3061510) --- .../ExperienceAchievementFactory.java | 16 ++++++------- .../achievements/QuestAchievementFactory.java | 24 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/games/stendhal/server/core/events/achievements/ExperienceAchievementFactory.java b/src/games/stendhal/server/core/events/achievements/ExperienceAchievementFactory.java index a30d569352..5bf86c4a6a 100644 --- a/src/games/stendhal/server/core/events/achievements/ExperienceAchievementFactory.java +++ b/src/games/stendhal/server/core/events/achievements/ExperienceAchievementFactory.java @@ -20,21 +20,21 @@ public class ExperienceAchievementFactory extends AchievementFactory { @Override public Collection createAchievements() { List xpAchievements = new LinkedList(); - xpAchievements.add(createAchievement("xp.lvl.10", "Greenhorn", "Reach level 10", Achievement.EASY_BASE_SCORE, + xpAchievements.add(createAchievement("xp.level.10", "Greenhorn", "Reach level 10", Achievement.EASY_BASE_SCORE, new LevelGreaterThanCondition(9))); - xpAchievements.add(createAchievement("xp.lvl.50", "Novice", "Reach level 50", Achievement.EASY_BASE_SCORE, + xpAchievements.add(createAchievement("xp.level.50", "Novice", "Reach level 50", Achievement.EASY_BASE_SCORE, new LevelGreaterThanCondition(49))); - xpAchievements.add(createAchievement("xp.lvl.100", "Apprentice", "Reach level 100", Achievement.EASY_BASE_SCORE, + xpAchievements.add(createAchievement("xp.level.100", "Apprentice", "Reach level 100", Achievement.EASY_BASE_SCORE, new LevelGreaterThanCondition(99))); - xpAchievements.add(createAchievement("xp.lvl.200", "Adventurer", "Reach level 200", Achievement.MEDIUM_BASE_SCORE, + xpAchievements.add(createAchievement("xp.level.200", "Adventurer", "Reach level 200", Achievement.MEDIUM_BASE_SCORE, new LevelGreaterThanCondition(199))); - xpAchievements.add(createAchievement("xp.lvl.300", "Experienced Adventurer", "Reach level 100", Achievement.MEDIUM_BASE_SCORE, + xpAchievements.add(createAchievement("xp.level.300", "Experienced Adventurer", "Reach level 100", Achievement.MEDIUM_BASE_SCORE, new LevelGreaterThanCondition(299))); - xpAchievements.add(createAchievement("xp.lvl.400", "Master Adventurer", "Reach level 400", Achievement.MEDIUM_BASE_SCORE, + xpAchievements.add(createAchievement("xp.level.400", "Master Adventurer", "Reach level 400", Achievement.MEDIUM_BASE_SCORE, new LevelGreaterThanCondition(399))); - xpAchievements.add(createAchievement("xp.lvl.500", "Stendhal Master", "Reach level 500", Achievement.HARD_BASE_SCORE, + xpAchievements.add(createAchievement("xp.level.500", "Stendhal Master", "Reach level 500", Achievement.HARD_BASE_SCORE, new LevelGreaterThanCondition(499))); - xpAchievements.add(createAchievement("xp.lvl.597", "Stendhal High Master", "Reach level 597", Achievement.HARD_BASE_SCORE, + xpAchievements.add(createAchievement("xp.level.597", "Stendhal High Master", "Reach level 597", Achievement.HARD_BASE_SCORE, new LevelGreaterThanCondition(596))); return xpAchievements; } diff --git a/src/games/stendhal/server/core/events/achievements/QuestAchievementFactory.java b/src/games/stendhal/server/core/events/achievements/QuestAchievementFactory.java index 0b3c972c92..6cbf76f0e0 100644 --- a/src/games/stendhal/server/core/events/achievements/QuestAchievementFactory.java +++ b/src/games/stendhal/server/core/events/achievements/QuestAchievementFactory.java @@ -17,32 +17,32 @@ public class QuestAchievementFactory extends AchievementFactory { public Collection createAchievements() { List questAchievements = new LinkedList(); //daily monster quest achievements - questAchievements.add(createAchievement("quest.special.dmq.10", "Semos' Protector", "Finish daily monster quest 10 times", + questAchievements.add(createAchievement("quest.special.daily.0010", "Semos' Protector", "Finish daily monster quest 10 times", Achievement.EASY_BASE_SCORE, new QuestStateGreaterThanCondition("daily", 2, 9))); - questAchievements.add(createAchievement("quest.special.dmq.50", "Semos' Guardian", "Finish daily monster quest 50 times", + questAchievements.add(createAchievement("quest.special.daily.0050", "Semos' Guardian", "Finish daily monster quest 50 times", Achievement.EASY_BASE_SCORE, new QuestStateGreaterThanCondition("daily", 2, 49))); - questAchievements.add(createAchievement("quest.special.dmq.100", "Semos' Hero", "Finish daily monster quest 100 times", + questAchievements.add(createAchievement("quest.special.daily.0100", "Semos' Hero", "Finish daily monster quest 100 times", Achievement.MEDIUM_BASE_SCORE, new QuestStateGreaterThanCondition("daily", 2, 99))); - questAchievements.add(createAchievement("quest.special.dmq.250", "Semos' Champion", "Finish daily monster quest 250 times", + questAchievements.add(createAchievement("quest.special.daily.0250", "Semos' Champion", "Finish daily monster quest 250 times", Achievement.MEDIUM_BASE_SCORE, new QuestStateGreaterThanCondition("daily", 2, 249))); - questAchievements.add(createAchievement("quest.special.dmq.500", "Semos' Vanquisher", "Finish daily monster quest 500 times", + questAchievements.add(createAchievement("quest.special.daily.0500", "Semos' Vanquisher", "Finish daily monster quest 500 times", Achievement.HARD_BASE_SCORE, new QuestStateGreaterThanCondition("daily", 2, 499))); //daily item quest achievements - questAchievements.add(createAchievement("quest.special.diq.10", "Ados' Supporter", "Finish daily item quest 10 times", + questAchievements.add(createAchievement("quest.special.daily_item.0010", "Ados' Supporter", "Finish daily item quest 10 times", Achievement.EASY_BASE_SCORE, new QuestStateGreaterThanCondition("daily_item", 2, 9))); - questAchievements.add(createAchievement("quest.special.diq.50", "Ados' Provider", "Finish daily item quest 50 times", + questAchievements.add(createAchievement("quest.special.daily_item.0050", "Ados' Provider", "Finish daily item quest 50 times", Achievement.EASY_BASE_SCORE, new QuestStateGreaterThanCondition("daily_item", 2, 49))); - questAchievements.add(createAchievement("quest.special.diq.100", "Ados' Supplier", "Finish daily item quest 100 times", + questAchievements.add(createAchievement("quest.special.daily_item.0100", "Ados' Supplier", "Finish daily item quest 100 times", Achievement.MEDIUM_BASE_SCORE, new QuestStateGreaterThanCondition("daily_item", 2, 99))); - questAchievements.add(createAchievement("quest.special.diq.250", "Ados' Stockpiler", "Finish daily item quest 250 times", + questAchievements.add(createAchievement("quest.special.daily_item.0250", "Ados' Stockpiler", "Finish daily item quest 250 times", Achievement.MEDIUM_BASE_SCORE, new QuestStateGreaterThanCondition("daily_item", 2, 249))); - questAchievements.add(createAchievement("quest.special.diq.500", "Ados' Hoarder", "Finish daily item quest 500 times", + questAchievements.add(createAchievement("quest.special.daily_item.0500", "Ados' Hoarder", "Finish daily item quest 500 times", Achievement.HARD_BASE_SCORE, new QuestStateGreaterThanCondition("daily_item", 2, 499))); //weekly item quest achievement - questAchievements.add(createAchievement("quest.special.wiq.5", "Archaeologist", "Finish weekly item quest 5 times", + questAchievements.add(createAchievement("quest.special.weekly_item.0005", "Archaeologist", "Finish weekly item quest 5 times", Achievement.HARD_BASE_SCORE, new QuestStateGreaterThanCondition("weekly_item", 2, 4))); //elf princess quest achievement - questAchievements.add(createAchievement("quest.special.rhosyd.25", "Faiumoni's Casanova", "Finish elf princess quest 25 times", + questAchievements.add(createAchievement("quest.special.elf_princess.0025", "Faiumoni's Casanova", "Finish elf princess quest 25 times", Achievement.MEDIUM_BASE_SCORE, new QuestStateGreaterThanCondition("elf_princess", 2, 24))); //ultimate collector quest achievement questAchievements.add(createAchievement("quest.special.collector", "Ultimate Collector", "Finish ultimate collector quest", From 6f3e2deb77a4a5da98e0a1176b6fa7ce8707608e Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Wed, 8 Sep 2010 19:15:53 +0000 Subject: [PATCH 04/17] backported logging code by kymara --- src/games/stendhal/server/script/UnblockTradeTable.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/games/stendhal/server/script/UnblockTradeTable.java b/src/games/stendhal/server/script/UnblockTradeTable.java index 53122628a3..4a0e2cdbc6 100644 --- a/src/games/stendhal/server/script/UnblockTradeTable.java +++ b/src/games/stendhal/server/script/UnblockTradeTable.java @@ -1,6 +1,7 @@ package games.stendhal.server.script; import games.stendhal.common.Direction; +import games.stendhal.server.core.engine.GameEvent; import games.stendhal.server.core.engine.SingletonRepository; import games.stendhal.server.core.engine.StendhalRPWorld; import games.stendhal.server.core.engine.StendhalRPZone; @@ -12,6 +13,8 @@ import games.stendhal.server.util.Area; import java.util.List; +import org.apache.log4j.Logger; + /** * Moves players away that spend to much time in an restricted area * @@ -21,6 +24,8 @@ public class UnblockTradeTable extends ScriptImpl implements TurnListener { private static final int CHECK_INTERVAL = 10; private static final int GRACE_PERIOD_IN_TURNS = 200; + private static Logger logger = Logger.getLogger(UnblockTradeTable.class); + private StendhalRPZone zone; private Area pathArea; private Area tablePathArea; @@ -103,7 +108,10 @@ public class UnblockTradeTable extends ScriptImpl implements TurnListener { // at the top left corner of the table, one tile to the right // So that the player cannot just run down, but close to the left // because player tend to put items on the ground. + logger.info("Teleported " + player.getName() + + " away from trading table coordinates " + player.getX() + "," + player.getY()); player.teleport(zone, 36, 2, Direction.DOWN, player); + new GameEvent("trade table", "teleport", player.getName(), zone.getName(), "36", "2").raise(); } } From e7b64884119a4948f5b77c3771cf6ad30209ee21 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Sun, 12 Sep 2010 14:10:09 +0000 Subject: [PATCH 05/17] added a warning on old clients so that we can get some estimate about the non automatic update this time --- .../server/core/engine/StendhalRPRuleProcessor.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/games/stendhal/server/core/engine/StendhalRPRuleProcessor.java b/src/games/stendhal/server/core/engine/StendhalRPRuleProcessor.java index a49570dc26..4dd088342f 100644 --- a/src/games/stendhal/server/core/engine/StendhalRPRuleProcessor.java +++ b/src/games/stendhal/server/core/engine/StendhalRPRuleProcessor.java @@ -169,14 +169,17 @@ public class StendhalRPRuleProcessor implements IRPRuleProcessor { public boolean checkGameVersion(final String game, final String version) { try { - if (game.equals(Configuration.getConfiguration().get("server_typeGame", "stendhal"))) { - return true; + if (!game.equals(Configuration.getConfiguration().get("server_typeGame", "stendhal"))) { + return false; } + if (Debug.VERSION.compareTo(version) > 0) { + logger.warn("Client version: " + version); + } + return true; } catch (IOException e) { logger.error(e, e); return false; } - return false; } /** From 612bff65b53296872c745e8a93426f951b48b97b Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Sun, 12 Sep 2010 14:18:13 +0000 Subject: [PATCH 06/17] base version for update is 0.86.1 not 0.86 which was signed with the old key --- build.ant.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.ant.properties b/build.ant.properties index 5bfbd8acc4..966bf8c246 100644 --- a/build.ant.properties +++ b/build.ant.properties @@ -72,7 +72,7 @@ updates_server = http://arianne.sourceforge.net/stendhal/updates version_server = http://arianne.sourceforge.net/stendhal.version # current version of stendhal -version.old = 0.86 +version.old = 0.86.1 version = 0.87 # javac options From 7742eaa5d95f70747f7f502c05b41d6af009b4b2 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Mon, 13 Sep 2010 20:10:06 +0000 Subject: [PATCH 07/17] deleted broken code --- .../achievements/AchievementNotifier.java | 4 -- .../player/ReadAchievementsOnLogin.java | 40 ------------------- 2 files changed, 44 deletions(-) delete mode 100644 src/games/stendhal/server/entity/player/ReadAchievementsOnLogin.java diff --git a/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java b/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java index 2286acb5da..2e6d2707e4 100644 --- a/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java +++ b/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java @@ -2,11 +2,9 @@ package games.stendhal.server.core.events.achievements; import games.stendhal.common.Grammar; import games.stendhal.server.core.engine.GameEvent; -import games.stendhal.server.core.engine.SingletonRepository; import games.stendhal.server.core.engine.db.AchievementDAO; import games.stendhal.server.core.engine.dbcommand.WriteReachedAchievementCommand; import games.stendhal.server.entity.player.Player; -import games.stendhal.server.entity.player.ReadAchievementsOnLogin; import java.sql.SQLException; import java.util.ArrayList; @@ -96,8 +94,6 @@ public class AchievementNotifier { logger.error("Error while saving new achievement "+a.getTitle(), e); } } - // register the login notifier that checks for each player the reached achievements on login - SingletonRepository.getLoginNotifier().addListener(new ReadAchievementsOnLogin()); } /** diff --git a/src/games/stendhal/server/entity/player/ReadAchievementsOnLogin.java b/src/games/stendhal/server/entity/player/ReadAchievementsOnLogin.java deleted file mode 100644 index cecb0c45d6..0000000000 --- a/src/games/stendhal/server/entity/player/ReadAchievementsOnLogin.java +++ /dev/null @@ -1,40 +0,0 @@ -package games.stendhal.server.entity.player; - -import games.stendhal.server.core.engine.SingletonRepository; -import games.stendhal.server.core.engine.dbcommand.ReadAchievementsForPlayerCommand; -import games.stendhal.server.core.events.LoginListener; -import games.stendhal.server.core.events.TurnListener; -import games.stendhal.server.core.events.TurnListenerDecorator; -import games.stendhal.server.core.events.TurnNotifier; - -import java.util.Set; - -import marauroa.server.db.command.DBCommand; -import marauroa.server.db.command.DBCommandQueue; -import marauroa.server.db.command.ResultHandle; - -public class ReadAchievementsOnLogin implements LoginListener, TurnListener { - - private ResultHandle handle = new ResultHandle(); - - public void onLoggedIn(Player player) { - DBCommand command = new ReadAchievementsForPlayerCommand(player); - DBCommandQueue.get().enqueueAndAwaitResult(command, handle); - TurnNotifier.get().notifyInTurns(1, new TurnListenerDecorator(this)); - } - - public void onTurnReached(int currentTurn) { - ReadAchievementsForPlayerCommand command = DBCommandQueue.get().getOneResult(ReadAchievementsForPlayerCommand.class, handle); - if (command == null) { - TurnNotifier.get().notifyInTurns(0, new TurnListenerDecorator(this)); - return; - } - Player p = command.getPlayer(); - Set identifiers = command.getIdentifiers(); - for (String identifier : identifiers) { - p.addReachedAchievement(identifier); - } - SingletonRepository.getAchievementNotifier().onLogin(command.getPlayer()); - } - -} From 4426de1f3ed3d2578448b3e74186a632ce220995 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Mon, 13 Sep 2010 20:11:58 +0000 Subject: [PATCH 08/17] deleted more broken code --- .../achievements/AchievementNotifier.java | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java b/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java index 2e6d2707e4..b101c6515d 100644 --- a/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java +++ b/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java @@ -138,28 +138,7 @@ public class AchievementNotifier { public void onFinishQuest(Player player) { getAndCheckAchievementsInCategory(player, Category.QUEST); } - - /** - * Checks on login of a player which achievements the player has reached and gives a summarizing message - * - * @param player - */ - public void onLogin(Player player) { - List toCheck = new ArrayList(); - Collection> values = achievements.values(); - for (List list : values) { - toCheck.addAll(list); - } - List reached = checkAchievements(player, toCheck); - // only send notice if actually a new added achievement was reached by doing nothing - if(!reached.isEmpty()) { - StringBuilder sb = new StringBuilder(); - sb.append("You have reached "); - sb.append(Integer.valueOf(reached.size())); - sb.append(" new "+Grammar.plnoun(reached.size(), "achievement")+". Please check #http://stendhalgame.org for details."); - player.sendPrivateText(sb.toString()); - } - } + /** * retrieve all achievements for a category and check if player has reached each of the found achievements From 8191b969679b56dfc81c3c2b461144ef514ac46b Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Mon, 13 Sep 2010 21:48:51 +0000 Subject: [PATCH 09/17] deleted achievement code --- .../core/engine/SingletonRepository.java | 7 - .../core/engine/StendhalPlayerDatabase.java | 2 - .../server/core/engine/StendhalRPWorld.java | 1 - .../server/core/engine/db/AchievementDAO.java | 195 -------------- .../ReadAchievementsForPlayerCommand.java | 41 --- .../WriteReachedAchievementCommand.java | 39 --- .../core/events/achievements/Achievement.java | 99 ------- .../achievements/AchievementFactory.java | 38 --- .../achievements/AchievementNotifier.java | 243 ------------------ .../core/events/achievements/Category.java | 12 - .../ExperienceAchievementFactory.java | 42 --- .../FightingAchievementFactory.java | 30 --- .../achievements/MetaAchievementFactory.java | 29 --- .../achievements/QuestAchievementFactory.java | 58 ----- .../stendhal/server/entity/RPEntity.java | 1 - ...heckForReachedQuestAchievementsAction.java | 15 -- .../stendhal/server/entity/player/Player.java | 7 - .../server/maps/quests/DailyItemQuest.java | 6 +- .../server/maps/quests/DailyMonsterQuest.java | 3 +- .../server/maps/quests/UltimateCollector.java | 6 +- .../server/maps/quests/WeeklyItemQuest.java | 6 +- 21 files changed, 7 insertions(+), 873 deletions(-) delete mode 100644 src/games/stendhal/server/core/engine/db/AchievementDAO.java delete mode 100644 src/games/stendhal/server/core/engine/dbcommand/ReadAchievementsForPlayerCommand.java delete mode 100644 src/games/stendhal/server/core/engine/dbcommand/WriteReachedAchievementCommand.java delete mode 100644 src/games/stendhal/server/core/events/achievements/Achievement.java delete mode 100644 src/games/stendhal/server/core/events/achievements/AchievementFactory.java delete mode 100644 src/games/stendhal/server/core/events/achievements/AchievementNotifier.java delete mode 100644 src/games/stendhal/server/core/events/achievements/Category.java delete mode 100644 src/games/stendhal/server/core/events/achievements/ExperienceAchievementFactory.java delete mode 100644 src/games/stendhal/server/core/events/achievements/FightingAchievementFactory.java delete mode 100644 src/games/stendhal/server/core/events/achievements/MetaAchievementFactory.java delete mode 100644 src/games/stendhal/server/core/events/achievements/QuestAchievementFactory.java delete mode 100644 src/games/stendhal/server/entity/npc/action/CheckForReachedQuestAchievementsAction.java diff --git a/src/games/stendhal/server/core/engine/SingletonRepository.java b/src/games/stendhal/server/core/engine/SingletonRepository.java index 9f801ca29b..4514695f76 100644 --- a/src/games/stendhal/server/core/engine/SingletonRepository.java +++ b/src/games/stendhal/server/core/engine/SingletonRepository.java @@ -2,7 +2,6 @@ package games.stendhal.server.core.engine; import games.stendhal.server.core.events.LoginNotifier; import games.stendhal.server.core.events.TurnNotifier; -import games.stendhal.server.core.events.achievements.AchievementNotifier; import games.stendhal.server.core.rp.StendhalQuestSystem; import games.stendhal.server.core.rp.guilds.GuildList; import games.stendhal.server.core.rp.guilds.GuildPermissionList; @@ -147,12 +146,6 @@ public class SingletonRepository { return AthorFerry.get(); } - /** - * @return the AchievementNotifier instance - */ - public static AchievementNotifier getAchievementNotifier() { - return AchievementNotifier.get(); - } /** * @return the actual EntityManager instance diff --git a/src/games/stendhal/server/core/engine/StendhalPlayerDatabase.java b/src/games/stendhal/server/core/engine/StendhalPlayerDatabase.java index f41ac54098..5faf027c5b 100644 --- a/src/games/stendhal/server/core/engine/StendhalPlayerDatabase.java +++ b/src/games/stendhal/server/core/engine/StendhalPlayerDatabase.java @@ -1,6 +1,5 @@ package games.stendhal.server.core.engine; -import games.stendhal.server.core.engine.db.AchievementDAO; import games.stendhal.server.core.engine.db.CidDAO; import games.stendhal.server.core.engine.db.PostmanDAO; import games.stendhal.server.core.engine.db.StendhalBuddyDAO; @@ -79,6 +78,5 @@ public class StendhalPlayerDatabase { DAORegister.get().register(StendhalKillLogDAO.class, new StendhalKillLogDAO ()); DAORegister.get().register(StendhalNPCDAO.class, new StendhalNPCDAO()); DAORegister.get().register(StendhalWebsiteDAO.class, new StendhalWebsiteDAO()); - DAORegister.get().register(AchievementDAO.class, new AchievementDAO()); } } diff --git a/src/games/stendhal/server/core/engine/StendhalRPWorld.java b/src/games/stendhal/server/core/engine/StendhalRPWorld.java index 94aa8f71de..6b543749de 100644 --- a/src/games/stendhal/server/core/engine/StendhalRPWorld.java +++ b/src/games/stendhal/server/core/engine/StendhalRPWorld.java @@ -151,7 +151,6 @@ public class StendhalRPWorld extends RPWorld { loader.load(); validatePortals(); - SingletonRepository.getAchievementNotifier().initialize(); SingletonRepository.getGagManager(); SingletonRepository.getJail(); } catch (final Exception e) { diff --git a/src/games/stendhal/server/core/engine/db/AchievementDAO.java b/src/games/stendhal/server/core/engine/db/AchievementDAO.java deleted file mode 100644 index 91211b485b..0000000000 --- a/src/games/stendhal/server/core/engine/db/AchievementDAO.java +++ /dev/null @@ -1,195 +0,0 @@ -package games.stendhal.server.core.engine.db; - -import games.stendhal.server.core.events.achievements.Achievement; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import marauroa.server.db.DBTransaction; -import marauroa.server.db.TransactionPool; -/** - * DAO to handle achievements for the stendhal website - * @author madmetzger - * - */ -public class AchievementDAO { - - /** - * logs a reached achievement into the database - * - * @param achievementId - * @param playerName - * @throws SQLException - */ - public void saveReachedAchievement(Integer achievementId, String playerName) throws SQLException { - DBTransaction transaction = TransactionPool.get().beginWork(); - saveReachedAchievement(achievementId, playerName, transaction); - TransactionPool.get().commit(transaction); - } - - /** - * logs a reached achievement into the database - * - * @param achievementId - * @param playerName - * @param transaction - * @throws SQLException - */ - public void saveReachedAchievement(Integer achievementId, String playerName, DBTransaction transaction) throws SQLException { - String query = "INSERT INTO reached_achievement " + - "(charname, achievement_id) VALUES" + - "('[charname]','[achievement_id]');"; - Map parameters = new HashMap(); - parameters.put("charname", playerName); - parameters.put("achievement_id", achievementId); - transaction.execute(query, parameters); - } - - /** - * Saves the base data of an achievement - * - * @param achievement Achievement to save - * @return the id of the stored achievement - * @throws SQLException - */ - public int saveAchievement(Achievement achievement) throws SQLException { - DBTransaction transaction = TransactionPool.get().beginWork(); - int achievementId = saveAchievement(achievement, transaction); - TransactionPool.get().commit(transaction); - return achievementId; - } - - /** - * Saves the base data of an achievement - * - * @param achievement Achievement to save - * @param transaction a database transaction to execute the save operation in - * @return the id of the stored achievement - * @throws SQLException - */ - public int saveAchievement(Achievement achievement, - DBTransaction transaction) throws SQLException { - int achievementId = 0; - String query = "INSERT INTO achievement " + - "(identifier, title, category, description, base_score) VALUES " + - "('[identifier]','[title]','[category]', '[description]', [base_score])"; - Map parameters = new HashMap(); - parameters.put("identifier", achievement.getIdentifier()); - parameters.put("title", achievement.getTitle()); - parameters.put("category", achievement.getCategory().toString()); - parameters.put("description", achievement.getDescription()); - parameters.put("base_score", achievement.getBaseScore()); - transaction.execute(query, parameters); - achievementId = transaction.getLastInsertId("achievement", "id"); - return achievementId; - } - - /** - * Updates the achievement with the given id - * - * @param id - * @param achievement - * @throws SQLException - */ - public void updateAchievement(Integer id, Achievement achievement) throws SQLException { - DBTransaction transaction = TransactionPool.get().beginWork(); - updateAchievement(id, achievement, transaction); - TransactionPool.get().commit(transaction); - } - - /** - * Updates the achievement with the given id - * - * @param id - * @param achievement - * @param transaction - * @throws SQLException - */ - public void updateAchievement(Integer id, Achievement achievement, - DBTransaction transaction) throws SQLException { - String query = "UPDATE achievement SET " + - "identifier='[identifier]', " + - "title='[title]', " + - "category = '[category]', " + - "description = '[description]', " + - "base_score=[base_score] " + - "WHERE id = [id];"; - Map parameters = new HashMap(); - parameters.put("identifier", achievement.getIdentifier()); - parameters.put("title", achievement.getTitle()); - parameters.put("category", achievement.getCategory().toString()); - parameters.put("description", achievement.getDescription()); - parameters.put("base_score", achievement.getBaseScore()); - parameters.put("id", id); - transaction.execute(query, parameters); - } - - /** - * Loads a map from achievement identifier to database serial - * - * @return map with key identifier string and value database id - * @throws SQLException - */ - public Map loadIdentifierIdPairs() throws SQLException { - DBTransaction transaction = TransactionPool.get().beginWork(); - Map map = loadIdentifierIdPairs(transaction);; - TransactionPool.get().commit(transaction); - return map; - } - - /** - * Loads a map from achievement identifier to database serial - * - * @param transaction - * @return map with key identifier string and value database id - * @throws SQLException - */ - public Map loadIdentifierIdPairs(DBTransaction transaction) throws SQLException { - Map map = new HashMap(); - String query = "SELECT identifier, id FROM achievement;"; - ResultSet set = transaction.query(query, new HashMap()); - while (set.next()) { - String identifier = set.getString("identifier"); - Integer id = set.getInt("id"); - map.put(identifier, id); - } - return map; - } - - /** - * Loads all achievements a player has reached - * @param playerName - * @return set identifiers of achievements reached by playerName - * @throws SQLException - */ - public Set loadAllReachedAchievementsOfPlayer(String playerName) throws SQLException { - DBTransaction transaction = TransactionPool.get().beginWork(); - Set set = loadAllReachedAchievementsOfPlayer(playerName, transaction); - TransactionPool.get().commit(transaction); - return set; - } - - /** - * Loads all achievements a player has reached - * @param playerName - * @param transaction - * @return set identifiers of achievements reached by playerName - * @throws SQLException - */ - public Set loadAllReachedAchievementsOfPlayer(String playerName, DBTransaction transaction) throws SQLException { - Map params = new HashMap(); - params.put("playername", playerName); - String query = "SELECT identifier FROM achievement a JOIN reached_achievement ra ON ra.achievement_id = a.id WHERE ra.charname = '[playername]';"; - ResultSet resultSet = transaction.query(query, params); - Set identifiers = new HashSet(); - while(resultSet.next()) { - identifiers.add(resultSet.getString(1)); - } - return identifiers; - } - -} diff --git a/src/games/stendhal/server/core/engine/dbcommand/ReadAchievementsForPlayerCommand.java b/src/games/stendhal/server/core/engine/dbcommand/ReadAchievementsForPlayerCommand.java deleted file mode 100644 index ba9796b92e..0000000000 --- a/src/games/stendhal/server/core/engine/dbcommand/ReadAchievementsForPlayerCommand.java +++ /dev/null @@ -1,41 +0,0 @@ -package games.stendhal.server.core.engine.dbcommand; - -import games.stendhal.server.core.engine.db.AchievementDAO; -import games.stendhal.server.entity.player.Player; - -import java.io.IOException; -import java.sql.SQLException; -import java.util.HashSet; -import java.util.Set; - -import marauroa.server.db.DBTransaction; -import marauroa.server.db.command.AbstractDBCommand; -import marauroa.server.game.db.DAORegister; - -public class ReadAchievementsForPlayerCommand extends AbstractDBCommand { - - private Set identifiers = new HashSet(); - private final Player player; - - /** - * @param player the player whose achievements should be read - */ - public ReadAchievementsForPlayerCommand(Player player) { - this.player = player; - } - - @Override - public void execute(DBTransaction transaction) throws SQLException, - IOException { - identifiers = DAORegister.get().get(AchievementDAO.class).loadAllReachedAchievementsOfPlayer(getPlayer().getName(), transaction); - } - - public Set getIdentifiers() { - return identifiers; - } - - public Player getPlayer() { - return player; - } - -} diff --git a/src/games/stendhal/server/core/engine/dbcommand/WriteReachedAchievementCommand.java b/src/games/stendhal/server/core/engine/dbcommand/WriteReachedAchievementCommand.java deleted file mode 100644 index 17e974a714..0000000000 --- a/src/games/stendhal/server/core/engine/dbcommand/WriteReachedAchievementCommand.java +++ /dev/null @@ -1,39 +0,0 @@ -package games.stendhal.server.core.engine.dbcommand; - -import games.stendhal.server.core.engine.db.AchievementDAO; -import games.stendhal.server.core.events.achievements.Category; - -import java.io.IOException; -import java.sql.SQLException; - -import marauroa.server.db.DBTransaction; -import marauroa.server.db.command.AbstractDBCommand; -import marauroa.server.game.db.DAORegister; -/** - * command to log a reached achievement to the database - * - * @author madmetzger - */ -public class WriteReachedAchievementCommand extends AbstractDBCommand { - - private final Integer id; - private final String playerName; - - /** - * create a new command - * @param id database id of the achievement - * @param playerName name of player who has reached it - */ - public WriteReachedAchievementCommand(Integer id, String title, Category category, String playerName) { - this.id = id; - this.playerName = playerName; - } - - @Override - public void execute(DBTransaction transaction) throws SQLException, - IOException { - AchievementDAO dao = DAORegister.get().get(AchievementDAO.class); - dao.saveReachedAchievement(id, playerName, transaction); - } - -} diff --git a/src/games/stendhal/server/core/events/achievements/Achievement.java b/src/games/stendhal/server/core/events/achievements/Achievement.java deleted file mode 100644 index debe4e7edb..0000000000 --- a/src/games/stendhal/server/core/events/achievements/Achievement.java +++ /dev/null @@ -1,99 +0,0 @@ -package games.stendhal.server.core.events.achievements; - -import games.stendhal.server.entity.npc.ChatCondition; -import games.stendhal.server.entity.player.Player; -/** - * An Achievement a player can reach while playing the game. - * Achievements are given for example for doing a certain number of quests or killing a number of special creatures - * - * @author madmetzger - */ -public class Achievement { - - public static final int EASY_BASE_SCORE = 10; - - public static final int MEDIUM_BASE_SCORE = 50; - - public static final int HARD_BASE_SCORE = 1000; - - private final String identifier; - - private final String title; - - private final Category category; - - private final String description; - - private final int baseScore; - - private final ChatCondition condition; - - - /** - * create a new achievement - * - * @param identifier - * @param title - * @param category - * @param condition - */ - public Achievement(String identifier, String title, Category category, String description, int baseScore, ChatCondition condition) { - this.identifier = identifier; - this.title = title; - this.category = category; - this.condition = condition; - this.description = description; - this.baseScore = baseScore; - } - - /** - * @return the category of this achievement - */ - public Category getCategory() { - return category; - } - - /** - * @return the identifying string - */ - public String getIdentifier() { - return identifier; - } - - /** - * @return the title a player gets awarded for this achievement - */ - public String getTitle() { - return title; - } - - /** - * @return the description of what to do to get this achievement - */ - public String getDescription() { - return description; - } - - /** - * @return the base score for this achievement - */ - public int getBaseScore() { - return this.baseScore; - } - - /** - * Check if a player has fullfilled this achievement - * @param p the player to check - * @return true iff this achievement's condtion evalutates to true - */ - public boolean isFulfilled(Player p) { - boolean fullfilled = condition.fire(p, null, null); - return fullfilled; - } - - @Override - public String toString() { - return "Achievement"; - } - -} diff --git a/src/games/stendhal/server/core/events/achievements/AchievementFactory.java b/src/games/stendhal/server/core/events/achievements/AchievementFactory.java deleted file mode 100644 index c02a64457e..0000000000 --- a/src/games/stendhal/server/core/events/achievements/AchievementFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -package games.stendhal.server.core.events.achievements; - -import games.stendhal.server.entity.npc.ChatCondition; - -import java.util.Collection; -/** - * Factory class for achievements creation with a fixed category - * - * @author madmetzger - */ -public abstract class AchievementFactory { - - /** - * @return the category the factory should use - */ - protected abstract Category getCategory(); - - /** - * Creates a collection of achievements - * - * @return the achievments - */ - public abstract Collection createAchievements(); - - /** - * Creates a single achievement - * @param identifier - * @param title - * @param description - * @param score - * @param condition - * @return the new Achievement - */ - protected Achievement createAchievement(String identifier, String title, String description, int score, ChatCondition condition) { - return new Achievement(identifier, title, getCategory(), description, score, condition); - } - -} \ No newline at end of file diff --git a/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java b/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java deleted file mode 100644 index b101c6515d..0000000000 --- a/src/games/stendhal/server/core/events/achievements/AchievementNotifier.java +++ /dev/null @@ -1,243 +0,0 @@ -package games.stendhal.server.core.events.achievements; - -import games.stendhal.common.Grammar; -import games.stendhal.server.core.engine.GameEvent; -import games.stendhal.server.core.engine.db.AchievementDAO; -import games.stendhal.server.core.engine.dbcommand.WriteReachedAchievementCommand; -import games.stendhal.server.entity.player.Player; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import marauroa.server.db.command.DBCommandQueue; -import marauroa.server.game.db.DAORegister; - -import org.apache.log4j.Logger; -/** - * Checks for reached achievements and marks them as reached for a player if he has fullfilled them - * - * @author madmetzger - */ -public class AchievementNotifier { - - private static final Logger logger = Logger.getLogger(AchievementNotifier.class); - - private static AchievementNotifier instance; - - private Map> achievements; - - private Map identifiersToIds; - - private AchievementNotifier() { - achievements = new HashMap>(); - identifiersToIds = new HashMap(); - } - - /** - * singleton accessor method - * - * @return the AchievementNotifier - */ - public static AchievementNotifier get() { - if(instance == null) { - instance = new AchievementNotifier(); - } - return instance; - } - - /** - * initializes the achievements that are available and registers the login listener - * new added achievements are added to the achievements table - */ - public void initialize() { - //read all configured achievements and put them into the categorized map - Map allAchievements = createAchievements(); - for(Achievement a : allAchievements.values()) { - if(!achievements.containsKey(a.getCategory())) { - achievements.put(a.getCategory(), new LinkedList()); - } - achievements.get(a.getCategory()).add(a); - } - //collect all identifiers from database - Map allIdentifiersInDatabase = collectAllIdentifiersFromDatabase(); - //update stored data with configured achievements - identifiersToIds.putAll(allIdentifiersInDatabase); - for(String identifier : allIdentifiersInDatabase.keySet()) { - Achievement achievement = allAchievements.get(identifier); - try { - // this happens if an achievement is not configured anymore but already in the database - // in that case we should keep it as players could have reached it - // useful to stop checking for a certain achievement but keep results - if(achievement != null) { - DAORegister.get().get(AchievementDAO.class).updateAchievement(allIdentifiersInDatabase.get(identifier), achievement); - } - } catch (SQLException e) { - logger.error("Error while updating exisiting achievement "+achievement.getTitle(), e); - } - } - // remove already stored achievements before saving them - for(String identifier : allIdentifiersInDatabase.keySet()) { - allAchievements.remove(identifier); - } - //save new achievements and add their identifier and id to the identifierToId map - for (Achievement a : allAchievements.values()) { - Integer id; - try { - id = DAORegister.get().get(AchievementDAO.class).saveAchievement(a); - identifiersToIds.put(a.getIdentifier(), id); - } catch (SQLException e) { - logger.error("Error while saving new achievement "+a.getTitle(), e); - } - } - } - - /** - * collects all identifiers from the database - * - * @return a set of all identifier strings - */ - private Map collectAllIdentifiersFromDatabase() { - Map mapFromDB = new HashMap(); - try { - mapFromDB = DAORegister.get().get(AchievementDAO.class).loadIdentifierIdPairs(); - } catch (SQLException e) { - logger.error("Error while loading Identifier to id map for achievements.", e); - } - return mapFromDB; - } - - /** - * checks all for level change relevant achievements for a player - * - * @param player - */ - public void onLevelChange(Player player) { - getAndCheckAchievementsInCategory(player, Category.EXPERIENCE); - } - - - /** - * checks all achievements for a player that should be checked when a player kills sth - * - * @param player - */ - public void onKill(Player player) { - getAndCheckAchievementsInCategory(player, Category.FIGHTING); - } - - /** - * check all achievements for a player that are relevant on finishing a quest - * - * @param player - */ - public void onFinishQuest(Player player) { - getAndCheckAchievementsInCategory(player, Category.QUEST); - } - - - /** - * retrieve all achievements for a category and check if player has reached each of the found achievements - * - * @param player - * @param category - */ - private void getAndCheckAchievementsInCategory(Player player, Category category) { - if(achievements.containsKey(category)) { - List toCheck = achievements.get(category); - List reached = checkAchievements(player, toCheck); - notifyPlayerAboutReachedAchievements(player, reached); - } - } - - /** - * checks for each achievement if the player has reached it. in case of reaching - * an achievement it starts logging and notifying about reaching - * - * @param player - * @param toCheck - */ - private List checkAchievements(Player player, - List toCheck) { - List reached = new ArrayList(); - for (Achievement achievement : toCheck) { - if(achievement.isFulfilled(player) && !player.hasReachedAchievement(achievement.getIdentifier())) { - logReachingOfAnAchievement(player, achievement); - reached.add(achievement); - } - } - //check for meta achievements and add them to the reached list - if(!reached.isEmpty()) { - if(achievements.containsKey(Category.META)) { - reached.addAll(checkAchievements(player, achievements.get(Category.META))); - } - } - return reached; - } - - /** - * Notifies a player about reached achievements via private message - * - * @param player - * @param achievements - */ - private void notifyPlayerAboutReachedAchievements(Player player, List achievements) { - for (Achievement achievement : achievements) { - notifyPlayerAboutReachedAchievement(player, achievement); - } - } - - /** - * logs reached achievement to gameEvents table and reached_achievment table - * - * @param player - * @param achievement - */ - private void logReachingOfAnAchievement(Player player, Achievement achievement) { - String identifier = achievement.getIdentifier(); - String title = achievement.getTitle(); - Category category = achievement.getCategory(); - String playerName = player.getName(); - DBCommandQueue.get().enqueue(new WriteReachedAchievementCommand(identifiersToIds.get(identifier), title, category, playerName)); - player.addReachedAchievement(achievement.getIdentifier()); - new GameEvent(playerName, "reach-achievement", category.toString(), title, identifier).raise(); - } - - /** - * notifies the player about reaching an achievement - * - * @param player - * @param achievement - */ - private void notifyPlayerAboutReachedAchievement(Player player, - Achievement achievement) { -// player.sendPrivateText("Congratulations! You have reached the "+achievement.getTitle()+" achievement!"); - } - - /** - * creates all available achievements - * - * @return map with key identifier and value the identified achievement - */ - private Map createAchievements() { - Map achievementMap = new HashMap(); - for(Achievement a : new ExperienceAchievementFactory().createAchievements()) { - achievementMap.put(a.getIdentifier(), a); - } - for(Achievement a : new FightingAchievementFactory().createAchievements()) { - achievementMap.put(a.getIdentifier(), a); - } - for(Achievement a : new QuestAchievementFactory().createAchievements()) { - achievementMap.put(a.getIdentifier(), a); - } - for(Achievement a : new MetaAchievementFactory().createAchievements()) { - achievementMap.put(a.getIdentifier(), a); - } - return achievementMap; - } - -} diff --git a/src/games/stendhal/server/core/events/achievements/Category.java b/src/games/stendhal/server/core/events/achievements/Category.java deleted file mode 100644 index 4145ea48d1..0000000000 --- a/src/games/stendhal/server/core/events/achievements/Category.java +++ /dev/null @@ -1,12 +0,0 @@ -/** - * - */ -package games.stendhal.server.core.events.achievements; -/** - * categories of achievements - * - * @author madmetzger - */ -public enum Category { - EXPERIENCE, FIGHTING, QUEST, META -} \ No newline at end of file diff --git a/src/games/stendhal/server/core/events/achievements/ExperienceAchievementFactory.java b/src/games/stendhal/server/core/events/achievements/ExperienceAchievementFactory.java deleted file mode 100644 index 5bf86c4a6a..0000000000 --- a/src/games/stendhal/server/core/events/achievements/ExperienceAchievementFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -package games.stendhal.server.core.events.achievements; - -import games.stendhal.server.entity.npc.condition.LevelGreaterThanCondition; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -/** - * Factory for experience achievements - * - * @author madmetzger - */ -public class ExperienceAchievementFactory extends AchievementFactory { - - @Override - protected Category getCategory() { - return Category.EXPERIENCE; - } - - @Override - public Collection createAchievements() { - List xpAchievements = new LinkedList(); - xpAchievements.add(createAchievement("xp.level.10", "Greenhorn", "Reach level 10", Achievement.EASY_BASE_SCORE, - new LevelGreaterThanCondition(9))); - xpAchievements.add(createAchievement("xp.level.50", "Novice", "Reach level 50", Achievement.EASY_BASE_SCORE, - new LevelGreaterThanCondition(49))); - xpAchievements.add(createAchievement("xp.level.100", "Apprentice", "Reach level 100", Achievement.EASY_BASE_SCORE, - new LevelGreaterThanCondition(99))); - xpAchievements.add(createAchievement("xp.level.200", "Adventurer", "Reach level 200", Achievement.MEDIUM_BASE_SCORE, - new LevelGreaterThanCondition(199))); - xpAchievements.add(createAchievement("xp.level.300", "Experienced Adventurer", "Reach level 100", Achievement.MEDIUM_BASE_SCORE, - new LevelGreaterThanCondition(299))); - xpAchievements.add(createAchievement("xp.level.400", "Master Adventurer", "Reach level 400", Achievement.MEDIUM_BASE_SCORE, - new LevelGreaterThanCondition(399))); - xpAchievements.add(createAchievement("xp.level.500", "Stendhal Master", "Reach level 500", Achievement.HARD_BASE_SCORE, - new LevelGreaterThanCondition(499))); - xpAchievements.add(createAchievement("xp.level.597", "Stendhal High Master", "Reach level 597", Achievement.HARD_BASE_SCORE, - new LevelGreaterThanCondition(596))); - return xpAchievements; - } - -} diff --git a/src/games/stendhal/server/core/events/achievements/FightingAchievementFactory.java b/src/games/stendhal/server/core/events/achievements/FightingAchievementFactory.java deleted file mode 100644 index dff824215a..0000000000 --- a/src/games/stendhal/server/core/events/achievements/FightingAchievementFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package games.stendhal.server.core.events.achievements; - -import games.stendhal.server.entity.npc.condition.PlayerHasKilledNumberOfCreaturesCondition; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -/** - * Factory for fighting achievements - * - * @author madmetzger - */ -public class FightingAchievementFactory extends AchievementFactory { - - @Override - public Collection createAchievements() { - List fightingAchievements = new LinkedList(); - fightingAchievements.add(createAchievement("fight.general.rats", "Rat Hunter", "Kill 15 rats", Achievement.EASY_BASE_SCORE, - new PlayerHasKilledNumberOfCreaturesCondition("rat", 15))); - fightingAchievements.add(createAchievement("fight.general.exterminator", "Exterminator", "Kill 10 rats of each kind", Achievement.MEDIUM_BASE_SCORE, - new PlayerHasKilledNumberOfCreaturesCondition(10, "rat", "caverat", "venomrat", "zombie rat", "venom rat", "giantrat", "ratman", "ratwoman", "archrat"))); - return fightingAchievements; - } - - @Override - protected Category getCategory() { - return Category.FIGHTING; - } - -} diff --git a/src/games/stendhal/server/core/events/achievements/MetaAchievementFactory.java b/src/games/stendhal/server/core/events/achievements/MetaAchievementFactory.java deleted file mode 100644 index af8a0a9042..0000000000 --- a/src/games/stendhal/server/core/events/achievements/MetaAchievementFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package games.stendhal.server.core.events.achievements; - -import games.stendhal.server.entity.npc.condition.PlayerHasCompletedAchievementsCondition; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -/** - * Factory for meta achievements - * - * @author madmetzger - */ -public class MetaAchievementFactory extends AchievementFactory { - - @Override - protected Category getCategory() { - return Category.META; - } - - @Override - public Collection createAchievements() { - List achievements = new LinkedList(); - achievements.add(createAchievement("meta.quest.daily-weekly", "Conscientuous Comrade", - "Complete all achievements for daily item quest, daily monster quest and weekly item quest", - Achievement.HARD_BASE_SCORE, new PlayerHasCompletedAchievementsCondition("quest.special.diq.500", "quest.special.wiq.5", "quest.special.dmq.500"))); - return achievements; - } - -} diff --git a/src/games/stendhal/server/core/events/achievements/QuestAchievementFactory.java b/src/games/stendhal/server/core/events/achievements/QuestAchievementFactory.java deleted file mode 100644 index 6cbf76f0e0..0000000000 --- a/src/games/stendhal/server/core/events/achievements/QuestAchievementFactory.java +++ /dev/null @@ -1,58 +0,0 @@ -package games.stendhal.server.core.events.achievements; - -import games.stendhal.server.entity.npc.condition.QuestCompletedCondition; -import games.stendhal.server.entity.npc.condition.QuestStateGreaterThanCondition; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -/** - * Factory for quest achievements - * - * @author madmetzger - */ -public class QuestAchievementFactory extends AchievementFactory { - - @Override - public Collection createAchievements() { - List questAchievements = new LinkedList(); - //daily monster quest achievements - questAchievements.add(createAchievement("quest.special.daily.0010", "Semos' Protector", "Finish daily monster quest 10 times", - Achievement.EASY_BASE_SCORE, new QuestStateGreaterThanCondition("daily", 2, 9))); - questAchievements.add(createAchievement("quest.special.daily.0050", "Semos' Guardian", "Finish daily monster quest 50 times", - Achievement.EASY_BASE_SCORE, new QuestStateGreaterThanCondition("daily", 2, 49))); - questAchievements.add(createAchievement("quest.special.daily.0100", "Semos' Hero", "Finish daily monster quest 100 times", - Achievement.MEDIUM_BASE_SCORE, new QuestStateGreaterThanCondition("daily", 2, 99))); - questAchievements.add(createAchievement("quest.special.daily.0250", "Semos' Champion", "Finish daily monster quest 250 times", - Achievement.MEDIUM_BASE_SCORE, new QuestStateGreaterThanCondition("daily", 2, 249))); - questAchievements.add(createAchievement("quest.special.daily.0500", "Semos' Vanquisher", "Finish daily monster quest 500 times", - Achievement.HARD_BASE_SCORE, new QuestStateGreaterThanCondition("daily", 2, 499))); - //daily item quest achievements - questAchievements.add(createAchievement("quest.special.daily_item.0010", "Ados' Supporter", "Finish daily item quest 10 times", - Achievement.EASY_BASE_SCORE, new QuestStateGreaterThanCondition("daily_item", 2, 9))); - questAchievements.add(createAchievement("quest.special.daily_item.0050", "Ados' Provider", "Finish daily item quest 50 times", - Achievement.EASY_BASE_SCORE, new QuestStateGreaterThanCondition("daily_item", 2, 49))); - questAchievements.add(createAchievement("quest.special.daily_item.0100", "Ados' Supplier", "Finish daily item quest 100 times", - Achievement.MEDIUM_BASE_SCORE, new QuestStateGreaterThanCondition("daily_item", 2, 99))); - questAchievements.add(createAchievement("quest.special.daily_item.0250", "Ados' Stockpiler", "Finish daily item quest 250 times", - Achievement.MEDIUM_BASE_SCORE, new QuestStateGreaterThanCondition("daily_item", 2, 249))); - questAchievements.add(createAchievement("quest.special.daily_item.0500", "Ados' Hoarder", "Finish daily item quest 500 times", - Achievement.HARD_BASE_SCORE, new QuestStateGreaterThanCondition("daily_item", 2, 499))); - //weekly item quest achievement - questAchievements.add(createAchievement("quest.special.weekly_item.0005", "Archaeologist", "Finish weekly item quest 5 times", - Achievement.HARD_BASE_SCORE, new QuestStateGreaterThanCondition("weekly_item", 2, 4))); - //elf princess quest achievement - questAchievements.add(createAchievement("quest.special.elf_princess.0025", "Faiumoni's Casanova", "Finish elf princess quest 25 times", - Achievement.MEDIUM_BASE_SCORE, new QuestStateGreaterThanCondition("elf_princess", 2, 24))); - //ultimate collector quest achievement - questAchievements.add(createAchievement("quest.special.collector", "Ultimate Collector", "Finish ultimate collector quest", - Achievement.HARD_BASE_SCORE, new QuestCompletedCondition("ultimate_collector"))); - return questAchievements; - } - - @Override - protected Category getCategory() { - return Category.QUEST; - } - -} diff --git a/src/games/stendhal/server/entity/RPEntity.java b/src/games/stendhal/server/entity/RPEntity.java index 082fae3c89..c65a30197f 100644 --- a/src/games/stendhal/server/entity/RPEntity.java +++ b/src/games/stendhal/server/entity/RPEntity.java @@ -1135,7 +1135,6 @@ public abstract class RPEntity extends GuidedEntity { } killer.addXP(reward); - SingletonRepository.getAchievementNotifier().onKill(killer); // For some quests etc., it is required that the player kills a // certain creature without the help of others. // Find out if the player killed this RPEntity on his own, but diff --git a/src/games/stendhal/server/entity/npc/action/CheckForReachedQuestAchievementsAction.java b/src/games/stendhal/server/entity/npc/action/CheckForReachedQuestAchievementsAction.java deleted file mode 100644 index 2e2b4ec233..0000000000 --- a/src/games/stendhal/server/entity/npc/action/CheckForReachedQuestAchievementsAction.java +++ /dev/null @@ -1,15 +0,0 @@ -package games.stendhal.server.entity.npc.action; - -import games.stendhal.server.core.engine.SingletonRepository; -import games.stendhal.server.entity.npc.ChatAction; -import games.stendhal.server.entity.npc.EventRaiser; -import games.stendhal.server.entity.npc.parser.Sentence; -import games.stendhal.server.entity.player.Player; - -public class CheckForReachedQuestAchievementsAction implements ChatAction { - - public void fire(Player player, Sentence sentence, EventRaiser npc) { - SingletonRepository.getAchievementNotifier().onFinishQuest(player); - } - -} diff --git a/src/games/stendhal/server/entity/player/Player.java b/src/games/stendhal/server/entity/player/Player.java index 3b6d2e5167..87e21229ca 100644 --- a/src/games/stendhal/server/entity/player/Player.java +++ b/src/games/stendhal/server/entity/player/Player.java @@ -29,7 +29,6 @@ import games.stendhal.common.constants.Nature; import games.stendhal.server.core.engine.SingletonRepository; import games.stendhal.server.core.engine.StendhalRPZone; import games.stendhal.server.core.events.TutorialNotifier; -import games.stendhal.server.core.events.achievements.AchievementNotifier; import games.stendhal.server.core.rp.StendhalRPAction; import games.stendhal.server.entity.Entity; import games.stendhal.server.entity.Outfit; @@ -1999,12 +1998,6 @@ public class Player extends RPEntity { remove("buddies", name); } - @Override - public void setLevel(int level) { - super.setLevel(level); - AchievementNotifier.get().onLevelChange(this); - } - /** * Adds the identifier of an achievement to the reached achievements * diff --git a/src/games/stendhal/server/maps/quests/DailyItemQuest.java b/src/games/stendhal/server/maps/quests/DailyItemQuest.java index 6e989d4dd6..4039565bc9 100644 --- a/src/games/stendhal/server/maps/quests/DailyItemQuest.java +++ b/src/games/stendhal/server/maps/quests/DailyItemQuest.java @@ -5,17 +5,16 @@ import games.stendhal.server.entity.npc.ChatAction; import games.stendhal.server.entity.npc.ConversationPhrases; import games.stendhal.server.entity.npc.ConversationStates; import games.stendhal.server.entity.npc.SpeakerNPC; -import games.stendhal.server.entity.npc.action.CheckForReachedQuestAchievementsAction; import games.stendhal.server.entity.npc.action.DropRecordedItemAction; import games.stendhal.server.entity.npc.action.IncreaseKarmaAction; import games.stendhal.server.entity.npc.action.IncreaseXPDependentOnLevelAction; import games.stendhal.server.entity.npc.action.IncrementQuestAction; import games.stendhal.server.entity.npc.action.MultipleActions; +import games.stendhal.server.entity.npc.action.SayRequiredItemAction; +import games.stendhal.server.entity.npc.action.SayTimeRemainingAction; import games.stendhal.server.entity.npc.action.SetQuestAction; import games.stendhal.server.entity.npc.action.SetQuestToTimeStampAction; import games.stendhal.server.entity.npc.action.StartRecordingRandomItemCollectionAction; -import games.stendhal.server.entity.npc.action.SayRequiredItemAction; -import games.stendhal.server.entity.npc.action.SayTimeRemainingAction; import games.stendhal.server.entity.npc.condition.AndCondition; import games.stendhal.server.entity.npc.condition.NotCondition; import games.stendhal.server.entity.npc.condition.OrCondition; @@ -248,7 +247,6 @@ public class DailyItemQuest extends AbstractQuest { actions.add(new SetQuestAction(QUEST_SLOT, 0, "done")); actions.add(new IncreaseXPDependentOnLevelAction(8, 90.0)); actions.add(new IncreaseKarmaAction(10.0)); - actions.add(new CheckForReachedQuestAchievementsAction()); npc.add(ConversationStates.ATTENDING, ConversationPhrases.FINISH_MESSAGES, diff --git a/src/games/stendhal/server/maps/quests/DailyMonsterQuest.java b/src/games/stendhal/server/maps/quests/DailyMonsterQuest.java index bcb2b8dbc8..a6bf851e33 100644 --- a/src/games/stendhal/server/maps/quests/DailyMonsterQuest.java +++ b/src/games/stendhal/server/maps/quests/DailyMonsterQuest.java @@ -10,7 +10,6 @@ import games.stendhal.server.entity.npc.ConversationPhrases; import games.stendhal.server.entity.npc.ConversationStates; import games.stendhal.server.entity.npc.EventRaiser; import games.stendhal.server.entity.npc.SpeakerNPC; -import games.stendhal.server.entity.npc.action.CheckForReachedQuestAchievementsAction; import games.stendhal.server.entity.npc.action.IncreaseXPDependentOnLevelAction; import games.stendhal.server.entity.npc.action.MultipleActions; import games.stendhal.server.entity.npc.action.SayTimeRemainingAction; @@ -441,7 +440,7 @@ public class DailyMonsterQuest extends AbstractQuest { new KilledForQuestCondition(QUEST_SLOT, 0)), ConversationStates.ATTENDING, null, - new MultipleActions(new DailyQuestCompleteAction(), new CheckForReachedQuestAchievementsAction())); + new MultipleActions(new DailyQuestCompleteAction())); } /** diff --git a/src/games/stendhal/server/maps/quests/UltimateCollector.java b/src/games/stendhal/server/maps/quests/UltimateCollector.java index 034c89f7a1..76730a8a84 100755 --- a/src/games/stendhal/server/maps/quests/UltimateCollector.java +++ b/src/games/stendhal/server/maps/quests/UltimateCollector.java @@ -3,13 +3,12 @@ package games.stendhal.server.maps.quests; import games.stendhal.server.entity.npc.ConversationPhrases; import games.stendhal.server.entity.npc.ConversationStates; import games.stendhal.server.entity.npc.SpeakerNPC; -import games.stendhal.server.entity.npc.action.CheckForReachedQuestAchievementsAction; import games.stendhal.server.entity.npc.action.DropRecordedItemAction; import games.stendhal.server.entity.npc.action.IncreaseXPAction; import games.stendhal.server.entity.npc.action.MultipleActions; +import games.stendhal.server.entity.npc.action.SayRequiredItemAction; import games.stendhal.server.entity.npc.action.SetQuestAction; import games.stendhal.server.entity.npc.action.StartRecordingRandomItemCollectionAction; -import games.stendhal.server.entity.npc.action.SayRequiredItemAction; import games.stendhal.server.entity.npc.condition.AndCondition; import games.stendhal.server.entity.npc.condition.NotCondition; import games.stendhal.server.entity.npc.condition.OrCondition; @@ -21,8 +20,8 @@ import games.stendhal.server.entity.npc.condition.QuestNotStartedCondition; import games.stendhal.server.entity.player.Player; import java.util.ArrayList; -import java.util.List; import java.util.HashMap; +import java.util.List; import java.util.Map; @@ -245,7 +244,6 @@ public class UltimateCollector extends AbstractQuest { "Wow, it's incredible to see this close up! Many thanks. Now, perhaps we can #deal together.", new MultipleActions(new DropRecordedItemAction(QUEST_SLOT), new SetQuestAction(QUEST_SLOT, "done"), - new CheckForReachedQuestAchievementsAction(), new IncreaseXPAction(100000))); npc.add(ConversationStates.QUEST_ITEM_QUESTION, diff --git a/src/games/stendhal/server/maps/quests/WeeklyItemQuest.java b/src/games/stendhal/server/maps/quests/WeeklyItemQuest.java index acc64d6d2c..25b8bd4b00 100644 --- a/src/games/stendhal/server/maps/quests/WeeklyItemQuest.java +++ b/src/games/stendhal/server/maps/quests/WeeklyItemQuest.java @@ -9,17 +9,16 @@ import games.stendhal.server.entity.npc.ConversationPhrases; import games.stendhal.server.entity.npc.ConversationStates; import games.stendhal.server.entity.npc.EventRaiser; import games.stendhal.server.entity.npc.SpeakerNPC; -import games.stendhal.server.entity.npc.action.CheckForReachedQuestAchievementsAction; import games.stendhal.server.entity.npc.action.DropRecordedItemAction; import games.stendhal.server.entity.npc.action.IncreaseKarmaAction; import games.stendhal.server.entity.npc.action.IncreaseXPDependentOnLevelAction; import games.stendhal.server.entity.npc.action.IncrementQuestAction; import games.stendhal.server.entity.npc.action.MultipleActions; +import games.stendhal.server.entity.npc.action.SayRequiredItemAction; +import games.stendhal.server.entity.npc.action.SayTimeRemainingAction; import games.stendhal.server.entity.npc.action.SetQuestAction; import games.stendhal.server.entity.npc.action.SetQuestToTimeStampAction; import games.stendhal.server.entity.npc.action.StartRecordingRandomItemCollectionAction; -import games.stendhal.server.entity.npc.action.SayRequiredItemAction; -import games.stendhal.server.entity.npc.action.SayTimeRemainingAction; import games.stendhal.server.entity.npc.condition.AndCondition; import games.stendhal.server.entity.npc.condition.NotCondition; import games.stendhal.server.entity.npc.condition.OrCondition; @@ -202,7 +201,6 @@ public class WeeklyItemQuest extends AbstractQuest { actions.add(new SetQuestAction(QUEST_SLOT, 0, "done")); actions.add(new IncreaseXPDependentOnLevelAction(5.0/3.0, 290.0)); actions.add(new IncreaseKarmaAction(10.0)); - actions.add(new CheckForReachedQuestAchievementsAction()); actions.add(new ChatAction() { public void fire(final Player player, final Sentence sentence, final EventRaiser raiser) { int goldamount; From cbda433bb2a41b2dd9a1cdf31edd8b2ca5f16c30 Mon Sep 17 00:00:00 2001 From: Kimmo Rundelin Date: Tue, 14 Sep 2010 10:49:10 +0000 Subject: [PATCH 10/17] Non-locking drawing. Hopefully fixes [3065851] "0.87 Bad performance on windows" --- src/games/stendhal/client/GameScreen.java | 8 +-- .../stendhal/client/StaticGameLayers.java | 22 ++++---- src/games/stendhal/client/StendhalClient.java | 35 ++++++------ src/games/stendhal/client/gui/j2DClient.java | 53 ++++++++----------- 4 files changed, 50 insertions(+), 68 deletions(-) diff --git a/src/games/stendhal/client/GameScreen.java b/src/games/stendhal/client/GameScreen.java index 2c0d170273..a95ffe4808 100644 --- a/src/games/stendhal/client/GameScreen.java +++ b/src/games/stendhal/client/GameScreen.java @@ -465,12 +465,8 @@ public class GameScreen extends JComponent implements PositionChangeListener, IG * so if swing internals change some time in the future, a new solution * may be needed. */ - if (StendhalClient.get().tryAcquireDrawingSemaphore()) { - try { - super.paintImmediately(x, y, w, h); - } finally { - StendhalClient.get().releaseDrawingSemaphore(); - } + if (!StendhalClient.get().isInBatchUpdate()) { + super.paintImmediately(x, y, w, h); } } diff --git a/src/games/stendhal/client/StaticGameLayers.java b/src/games/stendhal/client/StaticGameLayers.java index 7636d41568..fa5d9a5647 100644 --- a/src/games/stendhal/client/StaticGameLayers.java +++ b/src/games/stendhal/client/StaticGameLayers.java @@ -75,15 +75,15 @@ public class StaticGameLayers { private double width; /** Name of the layers set that we are rendering right now. */ - private String area; + private volatile String area; /** true when the area has been changed. */ - private boolean areaChanged; + private volatile boolean areaChanged; /** * Whether the internal state is valid. */ - private boolean isValid; + private volatile boolean isValid; public StaticGameLayers() { /* @@ -218,8 +218,10 @@ public class StaticGameLayers { } /** - * Set the name of the area to be rendered. - * @param area the areas name + * Set the name of the area to be rendered. This must not be called before + * ll the layer data for the area have been added. + * + * @param area the area name */ public void setAreaName(final String area) { this.area = area; @@ -230,7 +232,7 @@ public class StaticGameLayers { /** * Invalidate any cached settings. */ - public void invalidate() { + private void invalidate() { isValid = false; } @@ -239,6 +241,7 @@ public class StaticGameLayers { return; } + String area = this.area; if (area == null) { height = 0.0; width = 0.0; @@ -357,13 +360,6 @@ public class StaticGameLayers { return areaChanged; } - /** - * marks the area as changed - */ - public void markAreaChanged() { - this.areaChanged = true; - } - /** * resets the areaChanged flag. */ diff --git a/src/games/stendhal/client/StendhalClient.java b/src/games/stendhal/client/StendhalClient.java index 6978179b4c..1c3c3880a9 100644 --- a/src/games/stendhal/client/StendhalClient.java +++ b/src/games/stendhal/client/StendhalClient.java @@ -28,7 +28,6 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.concurrent.Semaphore; import javax.swing.JOptionPane; @@ -96,8 +95,9 @@ public class StendhalClient extends ClientFramework { /** * Whether the client is in a batch update. */ - private boolean inBatchUpdate = false; - private Semaphore drawingSemaphore = new Semaphore(1); + private volatile boolean inBatchUpdate = false; + /** Name of the current area */ + private String areaName; private final StendhalPerceptionListener stendhalPerceptionListener; @@ -233,7 +233,7 @@ public class StendhalClient extends ClientFramework { if (inBatchUpdate && (contentToLoad == 0)) { inBatchUpdate = false; - drawingSemaphore.release(); + staticLayers.setAreaName(areaName); } } @@ -242,7 +242,6 @@ public class StendhalClient extends ClientFramework { /* * A batch update has begun */ - drawingSemaphore.acquireUninterruptibly(); inBatchUpdate = true; logger.debug("Batch update started"); @@ -263,7 +262,8 @@ public class StendhalClient extends ClientFramework { return items; } - staticLayers.setAreaName(name.substring(0, i)); + //staticLayers.setAreaName(name.substring(0, i)); + areaName = name.substring(0, i); } /* @@ -303,6 +303,17 @@ public class StendhalClient extends ClientFramework { return items; } + + /** + * Check if the client is in the middle of a batch update. A batch update + * starts when a content transfer starts and end on the first perception + * event. + * + * @return true if in a batch update. + */ + public boolean isInBatchUpdate() { + return inBatchUpdate; + } /** * Determine if we are in the middle of transfering new content. @@ -338,8 +349,6 @@ public class StendhalClient extends ClientFramework { logger.error("onTransfer", e); } } - staticLayers.markAreaChanged(); - contentToLoad -= items.size(); /* @@ -614,14 +623,4 @@ public class StendhalClient extends ClientFramework { } return res; } - - public void releaseDrawingSemaphore() { - drawingSemaphore.release(); - } - - public boolean tryAcquireDrawingSemaphore() { - return drawingSemaphore.tryAcquire(); - } - - } diff --git a/src/games/stendhal/client/gui/j2DClient.java b/src/games/stendhal/client/gui/j2DClient.java index f28fc07cf2..57993f9d19 100644 --- a/src/games/stendhal/client/gui/j2DClient.java +++ b/src/games/stendhal/client/gui/j2DClient.java @@ -518,28 +518,24 @@ public class j2DClient implements UserInterface { logger.debug("Move objects"); gameObjects.update(delta); - if (gameLayers.isAreaChanged() && client.tryAcquireDrawingSemaphore()) { - try { - /* - * Update the screen - */ - screen.setMaxWorldSize(gameLayers.getWidth(), gameLayers.getHeight()); - screen.center(); - - // [Re]create the map - - final CollisionDetection cd = gameLayers.getCollisionDetection(); - final CollisionDetection pd = gameLayers.getProtectionDetection(); + if (gameLayers.isAreaChanged() && !client.isInBatchUpdate()) { + /* + * Update the screen + */ + screen.setMaxWorldSize(gameLayers.getWidth(), gameLayers.getHeight()); + screen.center(); - if (cd != null) { - minimap.update(cd, pd, - screen.getGraphicsConfiguration(), - gameLayers.getArea()); - } - gameLayers.resetChangedArea(); - } finally { - client.releaseDrawingSemaphore(); + // [Re]create the map + + final CollisionDetection cd = gameLayers.getCollisionDetection(); + final CollisionDetection pd = gameLayers.getProtectionDetection(); + + if (cd != null) { + minimap.update(cd, pd, + screen.getGraphicsConfiguration(), + gameLayers.getArea()); } + gameLayers.resetChangedArea(); } final User user = User.get(); @@ -555,17 +551,12 @@ public class j2DClient implements UserInterface { lastuser = user; } } - if (client.tryAcquireDrawingSemaphore()) { - try { - if (mainFrame.getMainFrame().getState() != Frame.ICONIFIED) { - logger.debug("Draw screen"); - screen.draw(); - minimap.refresh(); - containerPanel.repaintChildren(); - } - } finally { - client.releaseDrawingSemaphore(); - } + + if (mainFrame.getMainFrame().getState() != Frame.ICONIFIED) { + logger.debug("Draw screen"); + screen.draw(); + minimap.refresh(); + containerPanel.repaintChildren(); } logger.debug("Query network"); From 5dbc56da74d120d6cf027bc44ec13e7ab87784b3 Mon Sep 17 00:00:00 2001 From: Kimmo Rundelin Date: Tue, 14 Sep 2010 13:07:58 +0000 Subject: [PATCH 11/17] Reverted the previous fix attempt because it made problems with map changes --- src/games/stendhal/client/GameScreen.java | 8 ++- .../stendhal/client/StaticGameLayers.java | 22 ++++---- src/games/stendhal/client/StendhalClient.java | 35 ++++++------ src/games/stendhal/client/gui/j2DClient.java | 53 +++++++++++-------- 4 files changed, 68 insertions(+), 50 deletions(-) diff --git a/src/games/stendhal/client/GameScreen.java b/src/games/stendhal/client/GameScreen.java index a95ffe4808..2c0d170273 100644 --- a/src/games/stendhal/client/GameScreen.java +++ b/src/games/stendhal/client/GameScreen.java @@ -465,8 +465,12 @@ public class GameScreen extends JComponent implements PositionChangeListener, IG * so if swing internals change some time in the future, a new solution * may be needed. */ - if (!StendhalClient.get().isInBatchUpdate()) { - super.paintImmediately(x, y, w, h); + if (StendhalClient.get().tryAcquireDrawingSemaphore()) { + try { + super.paintImmediately(x, y, w, h); + } finally { + StendhalClient.get().releaseDrawingSemaphore(); + } } } diff --git a/src/games/stendhal/client/StaticGameLayers.java b/src/games/stendhal/client/StaticGameLayers.java index fa5d9a5647..7636d41568 100644 --- a/src/games/stendhal/client/StaticGameLayers.java +++ b/src/games/stendhal/client/StaticGameLayers.java @@ -75,15 +75,15 @@ public class StaticGameLayers { private double width; /** Name of the layers set that we are rendering right now. */ - private volatile String area; + private String area; /** true when the area has been changed. */ - private volatile boolean areaChanged; + private boolean areaChanged; /** * Whether the internal state is valid. */ - private volatile boolean isValid; + private boolean isValid; public StaticGameLayers() { /* @@ -218,10 +218,8 @@ public class StaticGameLayers { } /** - * Set the name of the area to be rendered. This must not be called before - * ll the layer data for the area have been added. - * - * @param area the area name + * Set the name of the area to be rendered. + * @param area the areas name */ public void setAreaName(final String area) { this.area = area; @@ -232,7 +230,7 @@ public class StaticGameLayers { /** * Invalidate any cached settings. */ - private void invalidate() { + public void invalidate() { isValid = false; } @@ -241,7 +239,6 @@ public class StaticGameLayers { return; } - String area = this.area; if (area == null) { height = 0.0; width = 0.0; @@ -360,6 +357,13 @@ public class StaticGameLayers { return areaChanged; } + /** + * marks the area as changed + */ + public void markAreaChanged() { + this.areaChanged = true; + } + /** * resets the areaChanged flag. */ diff --git a/src/games/stendhal/client/StendhalClient.java b/src/games/stendhal/client/StendhalClient.java index 1c3c3880a9..6978179b4c 100644 --- a/src/games/stendhal/client/StendhalClient.java +++ b/src/games/stendhal/client/StendhalClient.java @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.concurrent.Semaphore; import javax.swing.JOptionPane; @@ -95,9 +96,8 @@ public class StendhalClient extends ClientFramework { /** * Whether the client is in a batch update. */ - private volatile boolean inBatchUpdate = false; - /** Name of the current area */ - private String areaName; + private boolean inBatchUpdate = false; + private Semaphore drawingSemaphore = new Semaphore(1); private final StendhalPerceptionListener stendhalPerceptionListener; @@ -233,7 +233,7 @@ public class StendhalClient extends ClientFramework { if (inBatchUpdate && (contentToLoad == 0)) { inBatchUpdate = false; - staticLayers.setAreaName(areaName); + drawingSemaphore.release(); } } @@ -242,6 +242,7 @@ public class StendhalClient extends ClientFramework { /* * A batch update has begun */ + drawingSemaphore.acquireUninterruptibly(); inBatchUpdate = true; logger.debug("Batch update started"); @@ -262,8 +263,7 @@ public class StendhalClient extends ClientFramework { return items; } - //staticLayers.setAreaName(name.substring(0, i)); - areaName = name.substring(0, i); + staticLayers.setAreaName(name.substring(0, i)); } /* @@ -303,17 +303,6 @@ public class StendhalClient extends ClientFramework { return items; } - - /** - * Check if the client is in the middle of a batch update. A batch update - * starts when a content transfer starts and end on the first perception - * event. - * - * @return true if in a batch update. - */ - public boolean isInBatchUpdate() { - return inBatchUpdate; - } /** * Determine if we are in the middle of transfering new content. @@ -349,6 +338,8 @@ public class StendhalClient extends ClientFramework { logger.error("onTransfer", e); } } + staticLayers.markAreaChanged(); + contentToLoad -= items.size(); /* @@ -623,4 +614,14 @@ public class StendhalClient extends ClientFramework { } return res; } + + public void releaseDrawingSemaphore() { + drawingSemaphore.release(); + } + + public boolean tryAcquireDrawingSemaphore() { + return drawingSemaphore.tryAcquire(); + } + + } diff --git a/src/games/stendhal/client/gui/j2DClient.java b/src/games/stendhal/client/gui/j2DClient.java index 57993f9d19..f28fc07cf2 100644 --- a/src/games/stendhal/client/gui/j2DClient.java +++ b/src/games/stendhal/client/gui/j2DClient.java @@ -518,24 +518,28 @@ public class j2DClient implements UserInterface { logger.debug("Move objects"); gameObjects.update(delta); - if (gameLayers.isAreaChanged() && !client.isInBatchUpdate()) { - /* - * Update the screen - */ - screen.setMaxWorldSize(gameLayers.getWidth(), gameLayers.getHeight()); - screen.center(); + if (gameLayers.isAreaChanged() && client.tryAcquireDrawingSemaphore()) { + try { + /* + * Update the screen + */ + screen.setMaxWorldSize(gameLayers.getWidth(), gameLayers.getHeight()); + screen.center(); + + // [Re]create the map + + final CollisionDetection cd = gameLayers.getCollisionDetection(); + final CollisionDetection pd = gameLayers.getProtectionDetection(); - // [Re]create the map - - final CollisionDetection cd = gameLayers.getCollisionDetection(); - final CollisionDetection pd = gameLayers.getProtectionDetection(); - - if (cd != null) { - minimap.update(cd, pd, - screen.getGraphicsConfiguration(), - gameLayers.getArea()); + if (cd != null) { + minimap.update(cd, pd, + screen.getGraphicsConfiguration(), + gameLayers.getArea()); + } + gameLayers.resetChangedArea(); + } finally { + client.releaseDrawingSemaphore(); } - gameLayers.resetChangedArea(); } final User user = User.get(); @@ -551,12 +555,17 @@ public class j2DClient implements UserInterface { lastuser = user; } } - - if (mainFrame.getMainFrame().getState() != Frame.ICONIFIED) { - logger.debug("Draw screen"); - screen.draw(); - minimap.refresh(); - containerPanel.repaintChildren(); + if (client.tryAcquireDrawingSemaphore()) { + try { + if (mainFrame.getMainFrame().getState() != Frame.ICONIFIED) { + logger.debug("Draw screen"); + screen.draw(); + minimap.refresh(); + containerPanel.repaintChildren(); + } + } finally { + client.releaseDrawingSemaphore(); + } } logger.debug("Query network"); From f4f27c420dd087043db4b39f8e9addf95d4ed3be Mon Sep 17 00:00:00 2001 From: Kimmo Rundelin Date: Tue, 14 Sep 2010 13:11:49 +0000 Subject: [PATCH 12/17] Revoved acquiring the drawing semaphore before the draw requests. They won't be processed in the main thread. Hopefully fixes [3065851] "0.87 Bad performance on windows" --- src/games/stendhal/client/gui/j2DClient.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/games/stendhal/client/gui/j2DClient.java b/src/games/stendhal/client/gui/j2DClient.java index f28fc07cf2..e1d95fed22 100644 --- a/src/games/stendhal/client/gui/j2DClient.java +++ b/src/games/stendhal/client/gui/j2DClient.java @@ -555,17 +555,12 @@ public class j2DClient implements UserInterface { lastuser = user; } } - if (client.tryAcquireDrawingSemaphore()) { - try { - if (mainFrame.getMainFrame().getState() != Frame.ICONIFIED) { - logger.debug("Draw screen"); - screen.draw(); - minimap.refresh(); - containerPanel.repaintChildren(); - } - } finally { - client.releaseDrawingSemaphore(); - } + + if (mainFrame.getMainFrame().getState() != Frame.ICONIFIED) { + logger.debug("Draw screen"); + screen.draw(); + minimap.refresh(); + containerPanel.repaintChildren(); } logger.debug("Query network"); From 96ee933ea5b5ef382b967b412c974834338bbd3d Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Tue, 14 Sep 2010 19:27:01 +0000 Subject: [PATCH 13/17] increased version number --- build.ant.properties | 4 ++-- runserver.bat | 2 +- runserver.sh | 2 +- src/games/stendhal/client/update/Version.java | 2 +- src/games/stendhal/common/Debug.java | 2 +- src/games/stendhal/server/core/engine/GenerateINI.java | 2 +- stendhal.jnlp | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build.ant.properties b/build.ant.properties index 966bf8c246..cae1267457 100644 --- a/build.ant.properties +++ b/build.ant.properties @@ -72,8 +72,8 @@ updates_server = http://arianne.sourceforge.net/stendhal/updates version_server = http://arianne.sourceforge.net/stendhal.version # current version of stendhal -version.old = 0.86.1 -version = 0.87 +version.old = 0.87 +version = 0.87.1 # javac options javac.deprecation = true diff --git a/runserver.bat b/runserver.bat index 5d7c5c9346..0972e271c0 100644 --- a/runserver.bat +++ b/runserver.bat @@ -1,3 +1,3 @@ -set STENDHAL_VERSION=0.87 +set STENDHAL_VERSION=0.87.1 set LOCALCLASSPATH=.;data\script;data\conf;stendhal-server-%STENDHAL_VERSION%.jar;marauroa.jar;mysql-connector.jar;log4j.jar;commons-lang.jar;h2.jar java -Xmx400m -cp "%LOCALCLASSPATH%" marauroa.server.marauroad -c server.ini -l diff --git a/runserver.sh b/runserver.sh index b9fc9ea23c..bdf2a55879 100644 --- a/runserver.sh +++ b/runserver.sh @@ -1,5 +1,5 @@ #!/bin/sh -STENDHAL_VERSION="0.87" +STENDHAL_VERSION="0.87.1" LOCALCLASSPATH=.:data/script/:data/conf/:stendhal-server-$STENDHAL_VERSION.jar:marauroa.jar:mysql-connector.jar:log4j.jar:commons-lang.jar:h2.jar diff --git a/src/games/stendhal/client/update/Version.java b/src/games/stendhal/client/update/Version.java index 0c4b2125ae..3f37abe83e 100644 --- a/src/games/stendhal/client/update/Version.java +++ b/src/games/stendhal/client/update/Version.java @@ -10,7 +10,7 @@ package games.stendhal.client.update; public class Version { /** Version Number. */ - public static final String VERSION = "0.87"; + public static final String VERSION = "0.87.1"; /** * Extract the specified number of parts from a version-string. diff --git a/src/games/stendhal/common/Debug.java b/src/games/stendhal/common/Debug.java index 5ebf9bf13d..773a31d07b 100644 --- a/src/games/stendhal/common/Debug.java +++ b/src/games/stendhal/common/Debug.java @@ -25,7 +25,7 @@ public interface Debug { /** server version. */ // Note: This line is updated by build.xml using a regexp so be sure to adjust it in case you modify this line. - String VERSION = "0.87"; + String VERSION = "0.87.1"; /** diff --git a/src/games/stendhal/server/core/engine/GenerateINI.java b/src/games/stendhal/server/core/engine/GenerateINI.java index cabea6f577..1624a69495 100644 --- a/src/games/stendhal/server/core/engine/GenerateINI.java +++ b/src/games/stendhal/server/core/engine/GenerateINI.java @@ -234,7 +234,7 @@ public class GenerateINI { out.println(); out.println("server_typeGame=" + gameName); out.println("server_name=" + gameName + " Marauroa server"); - out.println("server_version=0.87"); + out.println("server_version=0.87.1"); out.println("server_contact=https://sourceforge.net/tracker/?atid=514826&group_id=66537&func=browse"); out.println(); out.println("# Extensions configured on the server. Enable at will."); diff --git a/stendhal.jnlp b/stendhal.jnlp index 9a1634b415..097462180a 100644 --- a/stendhal.jnlp +++ b/stendhal.jnlp @@ -22,7 +22,7 @@ Some of these people are NPC, they will give you tasks to accomplish and hints t - + From a733c41ef7e0e8477bfff8a504149ff2216fa78a Mon Sep 17 00:00:00 2001 From: Katie Russell Date: Wed, 15 Sep 2010 19:48:12 +0000 Subject: [PATCH 14/17] Backported: Dont teleport back to town hall on minor releases - ID: 3066625 --- src/games/stendhal/common/Version.java | 120 ++++++++++++++++++ .../engine/transformer/PlayerTransformer.java | 3 +- 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 src/games/stendhal/common/Version.java diff --git a/src/games/stendhal/common/Version.java b/src/games/stendhal/common/Version.java new file mode 100644 index 0000000000..0571b9163e --- /dev/null +++ b/src/games/stendhal/common/Version.java @@ -0,0 +1,120 @@ +/* $Id$ + */ +package games.stendhal.common; + +/** + * Handles version numbers + * + * Actual number stored in games.stendhal.common.Debug.VERSION + * This file duplicates methods from games.stendhal.client.update.Version + * as the updater should not depend on anything outside games.stendhal.client.update + * + * @author hendrik + */ +public class Version { + + /** + * Extract the specified number of parts from a version-string. + * + * @param version + * version-string + * @param parts + * number of parts to extract + * @return parts of the version-string + */ + public static String cut(final String version, final int parts) { + int pos = 0; + for (int i = 0; i < parts; i++) { + final int temp = version.indexOf(".", pos + 1); + if (temp < 0) { + pos = version.length(); + break; + } + pos = temp; + } + return version.substring(0, pos); + } + + /** + * Compares two versions. + * + * @param v1 + * 1st version string + * @param v2 + * 2nd version string + * @return see compare + */ + public static int compare(final String v1, final String v2) { + String version1 = v1; + String version2 = v2; + while (!version1.equals("") || !version2.equals("")) { + // split version string at the first dot into the current + // component and the rest of the version + String component1; + final int pos1 = version1.indexOf("."); + if (pos1 > -1) { + component1 = version1.substring(0, pos1); + version1 = version1.substring(pos1 + 1); + } else { + component1 = version1; + version1 = ""; + } + if (component1.equals("")) { + component1 = "0"; + } + + String component2; + final int pos2 = version2.indexOf("."); + if (pos2 > -1) { + component2 = version2.substring(0, pos2); + version2 = version2.substring(pos2 + 1); + } else { + component2 = version2; + version2 = ""; + } + if (component2.equals("")) { + component2 = "0"; + } + + // if the current component of both version is equal, + // we have to have a look at the next one. Otherwise + // we return the result of this comparison. + int res = 0; + try { + // try an integer comparison so that 2 < 13 + final int componentInt1 = Integer.parseInt(component1.trim()); + final int componentInt2 = Integer.parseInt(component2.trim()); + res = componentInt1 - componentInt2; + } catch (final NumberFormatException e) { + // integer comparison failed because one component is not a + // number. Do a string comparison. + res = component1.compareTo(component2); + } + if (res != 0) { + return res; + } + } + return 0; + } + + /** + * Checks whether these versions of stendhal are compatible. + * + * @param v1 + * one version string + * @param v2 + * another version string + * @return true, iff the first two components are equal + */ + public static boolean checkCompatibility(final String v1, final String v2) { + final String ev1 = cut(v1, 2); + final String ev2 = cut(v2, 2); + final boolean res = ev1.equals(ev2); + return res; + } + + private Version() { + // hide constructor; this is a static class + } + +} diff --git a/src/games/stendhal/server/core/engine/transformer/PlayerTransformer.java b/src/games/stendhal/server/core/engine/transformer/PlayerTransformer.java index 904815f44c..401bf31a68 100644 --- a/src/games/stendhal/server/core/engine/transformer/PlayerTransformer.java +++ b/src/games/stendhal/server/core/engine/transformer/PlayerTransformer.java @@ -4,6 +4,7 @@ import static games.stendhal.common.constants.Actions.AWAY; import static games.stendhal.common.constants.Actions.GRUMPY; import games.stendhal.common.Debug; import games.stendhal.common.FeatureList; +import games.stendhal.common.Version; import games.stendhal.server.core.engine.ItemLogger; import games.stendhal.server.core.engine.SingletonRepository; import games.stendhal.server.core.engine.StendhalRPZone; @@ -170,7 +171,7 @@ public class PlayerTransformer implements Transformer { try { if (object.has("zoneid") && object.has("x") && object.has("y")) { - if (object.get("release").equals(Debug.VERSION)) { + if (Version.checkCompatibility(object.get("release"),Debug.VERSION)) { zone = SingletonRepository.getRPWorld().getZone(object.get("zoneid")); } else { player.put("release", Debug.VERSION); From 60d1ee90b04ce448896367e4d1503bd24a059b1a Mon Sep 17 00:00:00 2001 From: Katie Russell Date: Wed, 15 Sep 2010 19:52:11 +0000 Subject: [PATCH 15/17] always set release number --- .../server/core/engine/transformer/PlayerTransformer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/stendhal/server/core/engine/transformer/PlayerTransformer.java b/src/games/stendhal/server/core/engine/transformer/PlayerTransformer.java index 401bf31a68..1c3045bfbf 100644 --- a/src/games/stendhal/server/core/engine/transformer/PlayerTransformer.java +++ b/src/games/stendhal/server/core/engine/transformer/PlayerTransformer.java @@ -174,11 +174,11 @@ public class PlayerTransformer implements Transformer { if (Version.checkCompatibility(object.get("release"),Debug.VERSION)) { zone = SingletonRepository.getRPWorld().getZone(object.get("zoneid")); } else { - player.put("release", Debug.VERSION); if (player.getLevel() >= 2) { TutorialNotifier.newrelease(player); } } + player.put("release", Debug.VERSION); } } catch (final RuntimeException e) { // If placing the player at its last position From 0e2d8f82f12e53fd5e38fceb58a2ad06a3b405e8 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Sun, 19 Sep 2010 18:36:03 +0000 Subject: [PATCH 16/17] updated marauroa --- libs/marauroa.jar | Bin 316026 -> 316106 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/libs/marauroa.jar b/libs/marauroa.jar index 37274e7c5586208ba7d4a3f1bc1eeda8abc87434..4cf6f45d2bb8dd339241084e06d5102b661ae219 100644 GIT binary patch delta 25715 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�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 Date: Sun, 19 Sep 2010 18:46:03 +0000 Subject: [PATCH 17/17] increased version number --- build.ant.properties | 2 +- runserver.bat | 2 +- runserver.sh | 2 +- src/games/stendhal/client/update/Version.java | 2 +- src/games/stendhal/common/Debug.java | 2 +- src/games/stendhal/server/core/engine/GenerateINI.java | 2 +- stendhal.jnlp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.ant.properties b/build.ant.properties index cae1267457..34d73c8af4 100644 --- a/build.ant.properties +++ b/build.ant.properties @@ -73,7 +73,7 @@ version_server = http://arianne.sourceforge.net/stendhal.version # current version of stendhal version.old = 0.87 -version = 0.87.1 +version = 0.87.2 # javac options javac.deprecation = true diff --git a/runserver.bat b/runserver.bat index 0972e271c0..c20f5cb64b 100644 --- a/runserver.bat +++ b/runserver.bat @@ -1,3 +1,3 @@ -set STENDHAL_VERSION=0.87.1 +set STENDHAL_VERSION=0.87.2 set LOCALCLASSPATH=.;data\script;data\conf;stendhal-server-%STENDHAL_VERSION%.jar;marauroa.jar;mysql-connector.jar;log4j.jar;commons-lang.jar;h2.jar java -Xmx400m -cp "%LOCALCLASSPATH%" marauroa.server.marauroad -c server.ini -l diff --git a/runserver.sh b/runserver.sh index bdf2a55879..dd60cd9f07 100644 --- a/runserver.sh +++ b/runserver.sh @@ -1,5 +1,5 @@ #!/bin/sh -STENDHAL_VERSION="0.87.1" +STENDHAL_VERSION="0.87.2" LOCALCLASSPATH=.:data/script/:data/conf/:stendhal-server-$STENDHAL_VERSION.jar:marauroa.jar:mysql-connector.jar:log4j.jar:commons-lang.jar:h2.jar diff --git a/src/games/stendhal/client/update/Version.java b/src/games/stendhal/client/update/Version.java index 3f37abe83e..ba9a0753d9 100644 --- a/src/games/stendhal/client/update/Version.java +++ b/src/games/stendhal/client/update/Version.java @@ -10,7 +10,7 @@ package games.stendhal.client.update; public class Version { /** Version Number. */ - public static final String VERSION = "0.87.1"; + public static final String VERSION = "0.87.2"; /** * Extract the specified number of parts from a version-string. diff --git a/src/games/stendhal/common/Debug.java b/src/games/stendhal/common/Debug.java index 773a31d07b..5e122afe26 100644 --- a/src/games/stendhal/common/Debug.java +++ b/src/games/stendhal/common/Debug.java @@ -25,7 +25,7 @@ public interface Debug { /** server version. */ // Note: This line is updated by build.xml using a regexp so be sure to adjust it in case you modify this line. - String VERSION = "0.87.1"; + String VERSION = "0.87.2"; /** diff --git a/src/games/stendhal/server/core/engine/GenerateINI.java b/src/games/stendhal/server/core/engine/GenerateINI.java index 1624a69495..742da78ee8 100644 --- a/src/games/stendhal/server/core/engine/GenerateINI.java +++ b/src/games/stendhal/server/core/engine/GenerateINI.java @@ -234,7 +234,7 @@ public class GenerateINI { out.println(); out.println("server_typeGame=" + gameName); out.println("server_name=" + gameName + " Marauroa server"); - out.println("server_version=0.87.1"); + out.println("server_version=0.87.2"); out.println("server_contact=https://sourceforge.net/tracker/?atid=514826&group_id=66537&func=browse"); out.println(); out.println("# Extensions configured on the server. Enable at will."); diff --git a/stendhal.jnlp b/stendhal.jnlp index 097462180a..efc01cf50d 100644 --- a/stendhal.jnlp +++ b/stendhal.jnlp @@ -22,7 +22,7 @@ Some of these people are NPC, they will give you tasks to accomplish and hints t - +