From 6d52587f4e491e91679e1337244370dc4a7200f8 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Thu, 11 Feb 2010 20:19:26 +0000 Subject: [PATCH 01/44] adjusted version numbers --- 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 fa0b7e1e1e..8c7326a308 100644 --- a/build.ant.properties +++ b/build.ant.properties @@ -76,7 +76,7 @@ version_server = http://arianne.sourceforge.net/stendhal.version # current version of stendhal version.old = 0.80 -version = 0.80.5 +version = 0.81 # javac options javac.deprecation = true diff --git a/runserver.bat b/runserver.bat index 73e44b5526..d2b7f24467 100644 --- a/runserver.bat +++ b/runserver.bat @@ -1,3 +1,3 @@ -set STENDHAL_VERSION=0.80.5 +set STENDHAL_VERSION=0.81 set LOCALCLASSPATH=.;data\script;data\conf;stendhal-server-%STENDHAL_VERSION%.jar;marauroa.jar;mysql-connector.jar;log4j.jar;commons-lang.jar java -Xmx400m -cp "%LOCALCLASSPATH%" marauroa.server.marauroad -c server.ini -l diff --git a/runserver.sh b/runserver.sh index a204fa0303..d7c4649055 100644 --- a/runserver.sh +++ b/runserver.sh @@ -1,5 +1,5 @@ #!/bin/sh -STENDHAL_VERSION="0.80.5" +STENDHAL_VERSION="0.81" LOCALCLASSPATH=.:data/script/:data/conf/:stendhal-server-$STENDHAL_VERSION.jar:marauroa.jar:mysql-connector.jar:log4j.jar:commons-lang.jar diff --git a/src/games/stendhal/client/update/Version.java b/src/games/stendhal/client/update/Version.java index 4740b42097..4a93e59d07 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.80.5"; + public static final String VERSION = "0.81"; /** * 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 3469b88ae0..d2532e8d8b 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.80.5"; + String VERSION = "0.81"; /** diff --git a/src/games/stendhal/server/core/engine/GenerateINI.java b/src/games/stendhal/server/core/engine/GenerateINI.java index 825beb8874..bde9912492 100644 --- a/src/games/stendhal/server/core/engine/GenerateINI.java +++ b/src/games/stendhal/server/core/engine/GenerateINI.java @@ -233,7 +233,7 @@ public class GenerateINI { out.println(); out.println("server_typeGame=" + gameName); out.println("server_name=" + gameName + " Marauroa server"); - out.println("server_version=0.80.5"); + out.println("server_version=0.81"); 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 7227086802..b4065356d5 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 f668fc51c945fb2a5bf097676ad7b70d962c3bab Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Fri, 12 Feb 2010 18:36:34 +0000 Subject: [PATCH 02/44] workaround for volume control not working on first playing of a sound. --- src/games/stendhal/client/sound/SoundSystemFacade.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/games/stendhal/client/sound/SoundSystemFacade.java b/src/games/stendhal/client/sound/SoundSystemFacade.java index 11c619ce4f..a404d2b55e 100644 --- a/src/games/stendhal/client/sound/SoundSystemFacade.java +++ b/src/games/stendhal/client/sound/SoundSystemFacade.java @@ -70,7 +70,11 @@ public class SoundSystemFacade extends SoundManager implements WorldListener { myFadingTime = fadingTime; } - play(sound, Numeric.intToFloat(volume, 100.0f), 0, area, loop, myFadingTime); + float vol = Numeric.intToFloat(volume, 100.0f); + play(sound, vol, 0, area, loop, myFadingTime); + + // This is a work around because the music is played at 100% unless it is already playing otherwise. + changeVolume(sound, vol); return sound; } return null; From c8d62e9db4eb5ced43249edef5556557590ddce2 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Fri, 12 Feb 2010 18:40:12 +0000 Subject: [PATCH 03/44] added tavern background music to semos city, village, bank in addition to tavern, and forsaken_mine to semos dungeon --- data/conf/zones/semos.xml | 107 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 3 deletions(-) diff --git a/data/conf/zones/semos.xml b/data/conf/zones/semos.xml index 9f076f099d..7f2b05e3f8 100644 --- a/data/conf/zones/semos.xml +++ b/data/conf/zones/semos.xml @@ -360,12 +360,20 @@ The sharper minded amongst you might prefer to double-click directly on the crea - - wind-2 - 25 + + the_old_tavern + 20 + treecreak-1 @@ -503,6 +511,13 @@ Mature sheep wanted: please speak to Sato. + + + the_old_tavern + 20 + + + @@ -737,6 +752,7 @@ Shepherds please note: keep watch for the wolves while searching for berries her the_old_tavern + 80 @@ -1109,6 +1125,13 @@ Holy mackerel! These chips are tasty. class-name="games.stendhal.server.entity.mapstuff.portal.OneWayPortalDestination" /> + + + the_old_tavern + 20 + + + @@ -1954,15 +1977,35 @@ Mature sheep wanted: please speak to Sato + + + the_forsaken_mine + 20 + + + + + + the_forsaken_mine + 20 + + + + + + the_forsaken_mine + 20 + + + + + + the_forsaken_mine + 20 + + + + + + the_forsaken_mine + 20 + + + + + + the_forsaken_mine + 20 + + + + + + the_forsaken_mine + 20 + + @@ -2091,6 +2162,13 @@ Mature sheep wanted: please speak to Sato + + + + the_forsaken_mine + 20 + + + + + + the_forsaken_mine + 20 + + + + + + the_forsaken_mine + 20 + + + + + + + wind-2 + 20 + + + true @@ -31,6 +39,14 @@ + + + + wind-2 + 20 + + + true From 4a977c5ed41cf7939524fad602b1eae7bc0d4404 Mon Sep 17 00:00:00 2001 From: Kimmo Rundelin Date: Sat, 13 Feb 2010 20:00:15 +0000 Subject: [PATCH 05/44] backport of netbook grey screen fix --- src/games/stendhal/client/GameScreen.java | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/games/stendhal/client/GameScreen.java b/src/games/stendhal/client/GameScreen.java index c22d52d0f2..df10aa90ed 100644 --- a/src/games/stendhal/client/GameScreen.java +++ b/src/games/stendhal/client/GameScreen.java @@ -81,7 +81,6 @@ public class GameScreen implements PositionChangeListener, IGameScreen { private Canvas canvas; private BufferStrategy buffer; - private Graphics g2d; /** * Static game layers. */ @@ -187,8 +186,7 @@ public class GameScreen implements PositionChangeListener, IGameScreen { if (!size.equals(stendhal.screenSize)) { sw = Math.min(canvas.getWidth(), stendhal.screenSize.width); sh = Math.min(canvas.getHeight(), stendhal.screenSize.height); - // Set the user clip to avoid drawing artefacts on some setups - g2d.setClip(0, 0, sw, sh); + // Reset the view so that the player is in the center calculateView(); center(); } @@ -482,6 +480,7 @@ public class GameScreen implements PositionChangeListener, IGameScreen { draw((Graphics2D) g); buffer.show(); + g.dispose(); } } @@ -489,22 +488,13 @@ public class GameScreen implements PositionChangeListener, IGameScreen { /* * swing does not want to give a valid GraphicsConfiguration until the * window has been drawn, so this can not be done in the constructor. - */ + */ if (buffer == null) { canvas.createBufferStrategy(2); - buffer = canvas.getBufferStrategy(); - g2d = buffer.getDrawGraphics(); - } else if (buffer.contentsLost() || buffer.contentsRestored()) { - /* - * On some systems (windows) the draw buffer can get lost in - * certain conditions. Recreate it if that has happened. - */ - final Graphics old = g2d; - g2d = buffer.getDrawGraphics(); - old.dispose(); + buffer = canvas.getBufferStrategy(); } - return g2d; + return buffer.getDrawGraphics(); } private void draw(final Graphics2D g2d) { From ac309393aa596df6943ab1ca27a8559f010f04ab Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Sun, 14 Feb 2010 16:36:38 +0000 Subject: [PATCH 06/44] added commands /manual and /faq --- .../stendhal/client/actions/FAQAction.java | 48 +++++++++++++++++++ .../stendhal/client/actions/ManualAction.java | 47 ++++++++++++++++++ .../client/actions/SlashActionRepository.java | 3 ++ 3 files changed, 98 insertions(+) create mode 100644 src/games/stendhal/client/actions/FAQAction.java create mode 100644 src/games/stendhal/client/actions/ManualAction.java diff --git a/src/games/stendhal/client/actions/FAQAction.java b/src/games/stendhal/client/actions/FAQAction.java new file mode 100644 index 0000000000..3c0aeff61f --- /dev/null +++ b/src/games/stendhal/client/actions/FAQAction.java @@ -0,0 +1,48 @@ +package games.stendhal.client.actions; + +import games.stendhal.client.ClientSingletonRepository; +import games.stendhal.client.gui.BareBonesBrowserLaunch; +import games.stendhal.client.gui.chatlog.HeaderLessEventLine; +import games.stendhal.common.NotificationType; + +/** + * Opens the manual + */ +class FAQAction implements SlashAction { + + /** + * Opens the faq + * + * @param params ignored + * @param remainder ignored + * @return true + */ + public boolean execute(final String[] params, final String remainder) { + ClientSingletonRepository.getUserInterface().addEventLine(new HeaderLessEventLine( + "Trying to open #http://arianne.sourceforge.net/wiki/index.php/StendhalFAQ in your browser.", + NotificationType.CLIENT)); + + BareBonesBrowserLaunch.openURL("http://stendhal.game-host.org/wiki/index.php/StendhalFAQ"); + + return true; + } + + + /** + * Get the maximum number of formal parameters. + * + * @return The parameter count. + */ + public int getMaximumParameters() { + return 0; + } + + /** + * Get the minimum number of formal parameters. + * + * @return The parameter count. + */ + public int getMinimumParameters() { + return 0; + } +} diff --git a/src/games/stendhal/client/actions/ManualAction.java b/src/games/stendhal/client/actions/ManualAction.java new file mode 100644 index 0000000000..8df06a7e0b --- /dev/null +++ b/src/games/stendhal/client/actions/ManualAction.java @@ -0,0 +1,47 @@ +package games.stendhal.client.actions; + +import games.stendhal.client.ClientSingletonRepository; +import games.stendhal.client.gui.BareBonesBrowserLaunch; +import games.stendhal.client.gui.chatlog.HeaderLessEventLine; +import games.stendhal.common.NotificationType; + +/** + * Opens the faq + */ +class ManualAction implements SlashAction { + + /** + * Opens the manual + * + * @param params ignored + * @param remainder ignored + * @return true + */ + public boolean execute(final String[] params, final String remainder) { + ClientSingletonRepository.getUserInterface().addEventLine(new HeaderLessEventLine( + "Trying to open #http://arianne.sourceforge.net/wiki/index.php/StendhalManual in your browser.", + NotificationType.CLIENT)); + + BareBonesBrowserLaunch.openURL("http://stendhal.game-host.org/wiki/index.php/StendhalManual"); + + return true; + } + + /** + * Get the maximum number of formal parameters. + * + * @return The parameter count. + */ + public int getMaximumParameters() { + return 0; + } + + /** + * Get the minimum number of formal parameters. + * + * @return The parameter count. + */ + public int getMinimumParameters() { + return 0; + } +} diff --git a/src/games/stendhal/client/actions/SlashActionRepository.java b/src/games/stendhal/client/actions/SlashActionRepository.java index dae429b837..22d161d2f2 100644 --- a/src/games/stendhal/client/actions/SlashActionRepository.java +++ b/src/games/stendhal/client/actions/SlashActionRepository.java @@ -34,6 +34,8 @@ public class SlashActionRepository { actions.put("drop", new DropAction()); + actions.put("faq", new FAQAction()); + actions.put("gag", new GagAction()); actions.put("gmhelp", new GMHelpAction()); actions.put("grumpy", new GrumpyAction()); @@ -47,6 +49,7 @@ public class SlashActionRepository { actions.put("jail", new JailAction()); actions.put("joinguild", new CreateGuildAction()); + actions.put("manual", new ManualAction()); actions.put("me", new EmoteAction()); actions.put("msg", msg); actions.put("mute", new MuteAction()); From 61131b8810abc35778a3ff871dd87e0aa86a298b Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Sun, 14 Feb 2010 16:54:42 +0000 Subject: [PATCH 07/44] made layer in SoundEvent a required field server side and use infinite radius as default (fixes #2951610) --- src/games/stendhal/client/events/SoundEvent.java | 6 +++++- .../server/entity/npc/behaviour/adder/BuyerAdder.java | 3 ++- .../server/entity/npc/behaviour/adder/SellerAdder.java | 3 ++- src/games/stendhal/server/events/SoundEvent.java | 3 ++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/games/stendhal/client/events/SoundEvent.java b/src/games/stendhal/client/events/SoundEvent.java index a8824038f9..fa40ccd13f 100644 --- a/src/games/stendhal/client/events/SoundEvent.java +++ b/src/games/stendhal/client/events/SoundEvent.java @@ -25,7 +25,11 @@ public class SoundEvent extends Event { if (event.has("volume")) { volume = event.getInt("volume"); } - SoundSystemFacade.get().play(event.get("sound"), entity.getX(), entity.getY(), event.getInt("radius"), layer, volume); + int radius = 100000; + if (event.has("radius")) { + radius = event.getInt("radius"); + } + SoundSystemFacade.get().play(event.get("sound"), entity.getX(), entity.getY(), radius, layer, volume); } } diff --git a/src/games/stendhal/server/entity/npc/behaviour/adder/BuyerAdder.java b/src/games/stendhal/server/entity/npc/behaviour/adder/BuyerAdder.java index aa6dffd7b9..a07c94b81f 100644 --- a/src/games/stendhal/server/entity/npc/behaviour/adder/BuyerAdder.java +++ b/src/games/stendhal/server/entity/npc/behaviour/adder/BuyerAdder.java @@ -1,6 +1,7 @@ package games.stendhal.server.entity.npc.behaviour.adder; import games.stendhal.common.Grammar; +import games.stendhal.common.constants.SoundLayer; import games.stendhal.server.entity.npc.ChatAction; import games.stendhal.server.entity.npc.ChatCondition; import games.stendhal.server.entity.npc.ConversationPhrases; @@ -126,7 +127,7 @@ public class BuyerAdder { boolean success = behaviour.transactAgreedDeal(engine, player); if (success) { - engine.addEvent(new SoundEvent("coins-1")); + engine.addEvent(new SoundEvent("coins-1", SoundLayer.CREATURE_NOISE)); } } }); diff --git a/src/games/stendhal/server/entity/npc/behaviour/adder/SellerAdder.java b/src/games/stendhal/server/entity/npc/behaviour/adder/SellerAdder.java index 081287f043..05b6e5cccb 100644 --- a/src/games/stendhal/server/entity/npc/behaviour/adder/SellerAdder.java +++ b/src/games/stendhal/server/entity/npc/behaviour/adder/SellerAdder.java @@ -1,6 +1,7 @@ package games.stendhal.server.entity.npc.behaviour.adder; import games.stendhal.common.Grammar; +import games.stendhal.common.constants.SoundLayer; import games.stendhal.server.entity.npc.ChatAction; import games.stendhal.server.entity.npc.ChatCondition; import games.stendhal.server.entity.npc.ConversationPhrases; @@ -125,7 +126,7 @@ public class SellerAdder { boolean success = behaviour.transactAgreedDeal(engine, player); if (success) { - engine.addEvent(new SoundEvent("coins-1")); + engine.addEvent(new SoundEvent("coins-1", SoundLayer.CREATURE_NOISE)); } } }); diff --git a/src/games/stendhal/server/events/SoundEvent.java b/src/games/stendhal/server/events/SoundEvent.java index bb7b0fccb3..237d4bded6 100644 --- a/src/games/stendhal/server/events/SoundEvent.java +++ b/src/games/stendhal/server/events/SoundEvent.java @@ -30,9 +30,10 @@ public class SoundEvent extends RPEvent { * * @param sound name of sound to play */ - public SoundEvent(final String sound) { + public SoundEvent(final String sound, SoundLayer layer) { super(Events.SOUND); put("sound", sound); + put("layer", layer.ordinal()); } From cbdc147d4d2e1fbb375347daab3e4859bc301d69 Mon Sep 17 00:00:00 2001 From: Kimmo Rundelin Date: Sun, 14 Feb 2010 20:17:51 +0000 Subject: [PATCH 08/44] backport of divider location patch --- src/games/stendhal/client/gui/j2DClient.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/games/stendhal/client/gui/j2DClient.java b/src/games/stendhal/client/gui/j2DClient.java index d40af8fc9c..e0c2ce4d1d 100644 --- a/src/games/stendhal/client/gui/j2DClient.java +++ b/src/games/stendhal/client/gui/j2DClient.java @@ -346,7 +346,7 @@ public class j2DClient implements UserInterface { chatBox.setMinimumSize(chatText.getPlayerChatText().getMinimumSize()); // Give the user the ability to make the the game area less tall - JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, pane, chatBox); + final JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, pane, chatBox); // Works for showing the resize, but is extremely flickery //splitPane.setContinuousLayout(true); pane.addComponentListener(new SplitPaneResizeListener(screen.getComponent(), splitPane)); @@ -397,6 +397,11 @@ public class j2DClient implements UserInterface { mainFrame.getMainFrame().setMinimumSize(new Dimension(width, height)); mainFrame.getMainFrame().setVisible(true); + /* + * Needed for small screens; Sometimes the divider is placed + * incorrectly unless we explicitly set it. + */ + splitPane.setDividerLocation(stendhal.screenSize.height + 1); } }); directionRelease = null; @@ -1094,7 +1099,7 @@ public class j2DClient implements UserInterface { * so return the divider to the maximum allowed height * by force. */ - splitPane.setDividerLocation(stendhal.screenSize.height); + splitPane.setDividerLocation(stendhal.screenSize.height + 1); } else { child.setSize(newSize); } From cf5413d6a1a241be2edec8a6adb3032490071c68 Mon Sep 17 00:00:00 2001 From: Katie Russell Date: Sun, 14 Feb 2010 21:04:32 +0000 Subject: [PATCH 09/44] Moving the tables outside the tavern one tile -> --- data/conf/zones/semos.xml | 4 ++-- tiled/Level 0/semos/city.tmx | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/data/conf/zones/semos.xml b/data/conf/zones/semos.xml index 7f2b05e3f8..5ff7f8a853 100644 --- a/data/conf/zones/semos.xml +++ b/data/conf/zones/semos.xml @@ -724,7 +724,7 @@ Shepherds please note: keep watch for the wolves while searching for berries her - + You see a nice clean table for resting your drinks on. @@ -733,7 +733,7 @@ Shepherds please note: keep watch for the wolves while searching for berries her - + You see a nice clean table for resting your drinks on. diff --git a/tiled/Level 0/semos/city.tmx b/tiled/Level 0/semos/city.tmx index bc51bcefda..86cf840c4b 100644 --- a/tiled/Level 0/semos/city.tmx +++ b/tiled/Level 0/semos/city.tmx @@ -1,6 +1,5 @@ - - - + + @@ -191,12 +190,12 @@ - H4sIAAAAAAAAAO2ZOW8UMRTHPVvTAzUQwhUIElcJEiUtEpf4BOHIbsiWoYCKK2EhSQECRIWAGvgqnAXkEgXiLnnW+mm85j37ecazu0n2SX/N5fHzz34+xqNUWmvVlLpfS5xpSdNluhdRrislfWk/Z1R5pbJY/rK+Bvyri79MvFO+UvOXLd+g/Tv5JxLmTfnqd/4qrd/4J9T64qfGivXEz5VpwN9d/lOqHPu5xGVKwT9TCwv97Ib0e0poBDQt8CctUwr+lpWXT9rPDki/k9BQ1nk9nNHpdkX4k6os/1wtLPSVst0kfiVlqrr/67mn39pMqe6PfwP+7vFLvo16Mf/ZDPNGHOOsEcc/BvleAF20dAl02fjUc+1p1Tl/nlX5HNoL/hbBz41PIf69kO8+lc8des7Q16PGZ+h5r/nR9yEo1wFHBzN/n8EyN03+4wH/+Lxp3QvxF1mr6dg6CjoG2gIMW0Hbsvb1cUXzw2N1OOtUi6grV1Wuf3R9Yfyg3DjiYssXdxQ/+j+RtXWe4S8738fM/2484ZqTqveYtqDi2PVP8es0oRiPtVD8j1tKOXdR/A3wcTLL5eP/APpYUJ8i+O16mC0QV1L+/cB7xNFIxvOvOOVbMnLvKee+Pv9agP8t6F1A71UeK1xduex3jbi+Mm3E8btsFL97zfGPWfdx/TBpjosqr2NOG7LOOqDkjmfIz8WGhN/ldG3JScfx22P9qJOHhF9r2VMOij+2n3Dxb7NS57Zx/E0nnb1+roo/Zhyx+X+D/hTUX4bfZ1J+7AMSfsmas9fzH8aAlN8XAyH+unNURPpu86NVyW/z1o2w3vuF/wfop1C/mDx87V9n3ukX/hQW0/+xPih+/d9K+l0W2iv38dvzNmV6TZQZcWMeWkOlHf+ke+gjwvxD/FQ92GOCb96z8wv1f658Lv8QaLtAwyrfI7LjAveIYviV6qyDVPw+4/jxH4L7z4D6VyD5Fpfwu+2k1yChMU/CT7W/r/9T+WpbzPJ79jnapElrr+vc9b+OE3v/UKdvKv84ILWq1j/63jLw3jL5rZjzZacO6irncfOn1v92zEvYQ3ux1Po3Zq8k1P534PlC9v85Go7BXPtTRvV7bRNEmo3gb1PW7mf6OGyOm7N2+pTfP1QZlyxet+21YRxPWvd8/FhfXB34jCtnlfwhw/in1tfS+a+sUvBXUR4q7xT/aUN7n7GqsjypyzpQp1Lv3fdaMWz6H99aMj2GVvHt2EiXVeXm8rv7h2vdUrf/amp7bd3cOyliVddnSv5+bfsp0FXmWQp+irtoXcS+12DO0aZAN0A3mfer4u8XewKa8zwvwx/ijqkXtx1j8vbF30vQU08+sfzUPg8Xd1yfk7xfJA1lbwLPOX7Xn8+/u2aYUv4+J7Ey40BM+hC/Pl4DXQ/4wGdTKtznqPek91NZiN+2adCMatcBvsvFvGYP9bmylrLOpP3/IegR6DFoHnTb0gNzH9lDfS5kUo4UMRLaO0N7BnoOeuERskvL9Rn0hdFCPEohC7W/zfIK9Nqj2Hb/5nn2PTIvtNiYkIz/MXNBjKXi95XnH6yyEbMAQAAA + H4sIAAAAAAAAAO2ZOW8UMRTHPVvTAzUQwhUIElcJEiUtEpf4BOHIbsiWSwEVV8JCkgIEiAoBNfBVOAvIJQrEXfKsmafxWu/ZzzOe3UnYJ/01l8fPP/v5GI9Sca3bUOp+I3KmJU2X6V5Aua6U9KX9nFHlFctC+cv6GvKvLf4y8U75is1ftnzD9u/ln4qYN+Wr7vxVWt34p9T/xU+NFf8TP1emIX9/+U+pcuznIpcpBv9swy/0sxvS7ymhMdCMwJ+0TDH4u0ZeLmk/OyD9TkIjSe/1aEKn2xXgT6qy/PMNv9BXzHaT+JWUqer+r+eeurWZUv0f/4b8/eOXfBsNYv4zGRYycYxzmTj+Ccj3AuiioUugy5lPPdeeVr3z51mVz6GD4O8S/Nz45OPfC/nuU/ncoecMfT2e+fQ9HzQ/+j4E5Tpg6WDi7jNY5naW/6THPz5vG/d8/EXWajq2joKOgbYAw1bQtiS9Pq5ofnisDie96hJ1ZavK9Y+uL4wflB1HXGy54o7iR/8nklTnGf6y833I/G/HE645qXoPaQsqjm3/FL9O44vxUPPF/6ShmHMXxd8CHyeTXC7+D6CPBfUpgN+sh7kCcSXl3w+8RyyNJTz/qlW+5Uz2PWXd1+dfC/C/Bb3z6L3KY4WrK5v9biaur8xk4vhtNorfvub4J4z7uH6Yzo5LKq9jThuS3jqgZI9nyM/FhoTf5rRt2UrH8Ztj/biVh4Rfa8VRDoo/tJ9w8W+yUuemcfxtK525fq6KP2QcMfl/g/4U1F+G32VSfuwDEn7JmnPQ8x/GgJTfFQM+/qZ1VET6fvOjVclv8jYzYb3Xhf8H6KdQv5g8XO3fZN6pC38MC+n/WB8Uv/5vJf0u8+2Vu/jNeZsyvSZKMnFjHlpLxR3/pHvoY8L8ffxUPZhjgmveM/Pz9X+ufDb/CGi7QKMq3yMy4wL3iEL4leqtg1j8LuP48R+C/c+A+lcg+RaX8NvtpNcgvjFPwk+1v6v/U/miLSXpsUWkm87Smus6e/2v48TcP9Tp28o9DkitqvUP3lsB9luNlH01O19J8nRNlfPY+VPrfzPmJey+vVhq/RuyVyJp/zuQZjFJ6wDP0XAM5tqfMqrfa5si0mwEX5uStJ/p42h23Jyk6WN+/3D8ywav2fbaMI6njXsufqwvrg5cxpWzan6XYfxT62vp/FdWMfirKA+Vd4z/tL69z1BVWZ7YZR2qV7H37getEDb9j289mR5Dq/h2pNZtdTWb394/XO8Wu/3XUttr6+feSRGruj5j8te17Tugq8yzGPwUd9G6CH2vxZyjdUA3QDeZ96vir4s9Ac07npfh93GH1IvdjiF5u+LvJeipI59Qfmqfh4s7rs9J3i+ShrI3nuccv+3P5d9eM3SUu89JrMw4EJLex6+P10DXPT7wWUf5+xz1nvR+LPPxmzYDmlVpHeC7XMxrdl+fK2sx60za/x+CHoEegxZAtw09yO4ju6/P+UzKESNGfHtnaM9Az0EvHEJ2abk+g74wWgxHKWS+9jdZXoFeOxTa7t8cz74H5oUWGhOS8T9kLgixWPyu8vwDR965HgBAAAA= - H4sIAAAAAAAAAO1aW2sUMRTujLSI1xfvPqpUUbEFUaw+KP4BFVRon91W1N11rZeWIkXpw/48tS9esOqbTwpeEJ88hyb0bEgyZ5LMJG7ng4/Zmckm5zs5yUmyOzIyfGhlsS0YLqTmzxD2FNVxh9lGTN+sZIPcbFD1+/rA1ufqu1TGxGaPgSrg4s864yF0W2pspxZPscaa6gNqBzc/hAS2b/JFzPmoyrZTmWddMO3BEEjRd0fApqOExyLZyPGNr/8+wvfXgJ9EPfNwfQwcJ3wCfJrpy8dAHTHTI6wbc6DvboLjgoO+IRfZYCtnyydlbJKMiWvA64Q3DOWk3lD5OxX9N4G3CG9byrYc4qgIVc8bbUHMGfKzimnxnubP2P0SCjR30JzBfS9xBp5PCU4E8I1pr7A196+7DMrEH5ZVx/+MoLoOk8/lugXXKzNKfVeBf7P1qw2XNDZeTCQ+50XMqHG0JlgUW+MMHaegzCO4HoDYOJhvPPtf8Q1s/y7sl2uZ3BL3Uv8hKHO4QH8bnt/z5H3giYT8e1pjy0mDfZ0AdmMdnPjqQpmHCfkJ4asf52Ou/h7GZcE6sW50NDnFpQ6dflw7dDXlpc4FS7tLhnehfUT1n1XmlHNwf16wqA6dfjnXI1S7n8H98xJ7i5ahHl8U9T/6QL5/YZlDOPFPbV/O1vv/FfA18A25riq++QGffwL/ZPXr55zPcvTr7EaNb4HvgO/J9UM2ODZ+weffDN2632mKzpjnAuQ/3OdPOvYLxsEi+e6i0G6bG2z6Xd7VAbkOlnGg5sK+EvPLSnmO/S76q8o5dFyvatrQ5UKdLVXrr+r3BTqucTzPknbomHvgON508In/us7KVeDciXnlM7ADuaYL/OLYJ6hRt25YYMzhmKvpeTDeyz2ZaY8fAlL/ZZwPQHsPeMVDP0I39jjjn+69bWgr9AHqfyna++rp5xWRN9Sxt2Tpf6lf9j/ur49ng/t0vI6RNaDuDGjM8RyG6ufCNGdLjdvAlu3AHflGHnXJf7Qdes6k+4+G6zmUbv/lmpPkOmcn2LILuDsffG5D2XMtznfp+t8E2/5TPQ9LBWr/63IoPusz/C7163zIPWutCtImdV7ixgpnbREy/in2QOzvZYzJCSgzWfMZMsVsRX26DzTtD6DrAtQxlfPvG8THsPwW1cCMURhzWzw5qhm33PJl22rAQ4z/qjRo0ICH2OeosZHaf7ZV1GVXivpT7peUkKqf6sr9qepv0KDB5kaz/xlO/ANyH73mAEAAAA== + H4sIAAAAAAAAAO1aW2sUMRTujLSI1xfvPqpUUbEFUaw+KP4BFVRon91W1N11rZeWIkXpw/48tS9esOqbTwpeEJ88hyb0bEgyZ5LMJG7ng4/Zmckm5zs5yUmyOzIyfGhlsS0YLqTmzxD2FNVxh9lGTN+sZIPcbFD1+/rA1ufqu1TGxGaPgSrg4s864yF0W2pspxZPscaa6gNqBzc/hAS2b/JFzPmoyrZTmWddMO3BEEjRd0fApqOExyLZyPGNr/8+wvfXgJ9EPfNwfQwcJ3wCfJrpy8dAHTHTI6wbc6DvboLjgoO+IRfZYCtnyydlbJKMiWvA64Q3DOWk3lD5OxX9N4G3CG9byrYc4qgIVc8bbUHMGfKzimnxnubP2P0SCjR30JzBfS9xBp5PCU4E8I1pr7A196+7DMrEH5ZVx/+MoLoOk8/lugXXKzNKfVeBf7P1qw2XNDZeTCQ+50XMqHG0JlgUW+MMHaegzCO4HoDYOJhvPPtf8Q1s/y7sl2uZ3BL3Uv8hKHO4QH8bnt/z5H3giYT8e1pjy0mDfZ0AdmMdnPjqQpmHCfkJ4asf52Ou/h7GZcE6sW50NDnFpQ6dflw7dDXlpc4FS7tLhnehfUT1n1XmlHNwf16wqA6dfjnXI1S7n8H98xJ7i5ahHl8U9T/6QL5/YZlDOPFPbV/O1vv/FfA18A25riq++QGffwL/ZPXr55zPcvTr7EaNb4HvgO/J9UM2ODZ+weffDN2632mKzpjnAuQ/3OdPOvYLxsEi+e6i0G6bG2z6Xd7VAbkOlnGg5sK+EvPLSnmO/S76q8o5dFyvatrQ5UKdLVXrr+r3BTqucTzPknbomHvgON508In/us7KVeDciXnlM7ADuaYL/OLYJ6hRt25YYMzhmKvpeTDeyz2ZaY8fAlL/ZZwPQHsPeMVDP0I39jjjn+69bWgr9AHqfyna++rp5xWRN9Sxt2Tpf6lf9j/ur49ng/t0vI6RNaDuDGjM8RyG6ufCNGdLjdvAlu3AHflGHi2b/9Q26DmT7j8arudQuv2Xa06S65ydYMsu4O588LkNZc+1ON+l638TbPtP9TwsFaj9r8uh+KzP8LvUr/Mh96y1bnBjhbO2CBn/FHsg9vcyxuQElJms+QyZYraiPt0HmvYH0HUB6pjK+fcN4mNYfotqYMYojLktnhzVjFtu+bJtNeAhxn9VGjRowEPsc9TYSO0/2yrqsitF/Sn3S0pI1U915f5U9Tdo0GBzo9n/DCf+AaC8eNwAQAAA @@ -209,7 +208,7 @@ H4sIAAAAAAAAAO3ZSwrCMBSFYc1WVFDQFfjW+q5Dceb+tyA48IZS6MBIU01Ik/+DMxPqIaE3xk4HrmTKHG2rzIlB1rBHbP3vFn1uka3/TrI35GDoGVP/o+RkyJn+H9Hf7/d0Rfe/SHJDrgn0T3n+A0Bb5JW00T/mxlQVCVF1broyU0VQn8/zyrPr71m2mt53hGYuPRaSZSR9bK2k91qyqfTvyb7rSwYB7z+grlBnvC/MeAAIn+n3RSznbXxns/7lZ9kbadLr/1Du17/8nybVc3TZn3M0kB59H/ZyeB82lPfKKOF3y1i6TxLuDwAAAAAAAAD4zRs+ikUJAEAAAA== - + H4sIAAAAAAAAAO3ZQQ6CMBAFUMJFdaEmHsY7uzCEDSlBpmacvpd0SzrDp03pNAH/6jp/BuP2YcnAqPX3Mmo/ZQmgj/u8DgCIYE8hwlaOWtmSO8ijwv+bvRpeBWpsqfAOz9irv3p/WvX5RwsQ62JNJaEj5+vMZ/Fb4rnRT8V1NfN3BsA5FfctvveQByCZ5S4g651A1nn9wtZdzTOoH1HPyWL0nACwcgbv5w0mQTIgAEAAAA== From d11ef4bdd7e46655bba081148ad7c359eec47013 Mon Sep 17 00:00:00 2001 From: Kimmo Rundelin Date: Sun, 14 Feb 2010 21:25:37 +0000 Subject: [PATCH 10/44] backport of screen size calculation fix --- src/games/stendhal/client/GameScreen.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/games/stendhal/client/GameScreen.java b/src/games/stendhal/client/GameScreen.java index df10aa90ed..d4dad6d76f 100644 --- a/src/games/stendhal/client/GameScreen.java +++ b/src/games/stendhal/client/GameScreen.java @@ -183,13 +183,12 @@ public class GameScreen implements PositionChangeListener, IGameScreen { public void componentResized(ComponentEvent e) { Dimension size = canvas.getSize(); - if (!size.equals(stendhal.screenSize)) { - sw = Math.min(canvas.getWidth(), stendhal.screenSize.width); - sh = Math.min(canvas.getHeight(), stendhal.screenSize.height); - // Reset the view so that the player is in the center - calculateView(); - center(); - } + + sw = Math.min(canvas.getWidth(), stendhal.screenSize.width); + sh = Math.min(canvas.getHeight(), stendhal.screenSize.height); + // Reset the view so that the player is in the center + calculateView(); + center(); } public void componentShown(ComponentEvent e) { } From 47941773206650e4e239ca47dfde78a71ad2dc26 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Mon, 15 Feb 2010 21:17:20 +0000 Subject: [PATCH 11/44] fixed thousands of NullPointerExceptions in the chat log on both Java Sun 5 and Java Sun 6. OpenJDK was not affected. --- src/games/stendhal/client/sound/system/SoundSystem.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/games/stendhal/client/sound/system/SoundSystem.java b/src/games/stendhal/client/sound/system/SoundSystem.java index 8a95eb9dc3..99d6249f27 100644 --- a/src/games/stendhal/client/sound/system/SoundSystem.java +++ b/src/games/stendhal/client/sound/system/SoundSystem.java @@ -385,9 +385,10 @@ public class SoundSystem extends Thread { for(Output output: mOutputs) { - /* happens for example if the audio device is in use by an other applicatin - if(output.mAudioFormat == null) - continue; //*/ + /* happens for example if the audio device is in use by an other applicatin */ + if(output.mAudioFormat == null) { + continue; + }//*/ int numBytesPerSample = output.mAudioFormat.getSampleSizeInBits() / 8; int numChannels = output.mAudioFormat.getChannels(); From 34b1865a53b6688e7afb082d97dd67c3e20c6ffc Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Mon, 15 Feb 2010 21:30:39 +0000 Subject: [PATCH 12/44] backported hint about changing zone one /mute --- .../stendhal/client/actions/MuteAction.java | 15 ++++++++++++++- .../stendhal/client/actions/SoundAction.java | 19 ++----------------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/games/stendhal/client/actions/MuteAction.java b/src/games/stendhal/client/actions/MuteAction.java index 0ef236c198..6abd6b43ac 100644 --- a/src/games/stendhal/client/actions/MuteAction.java +++ b/src/games/stendhal/client/actions/MuteAction.java @@ -1,5 +1,10 @@ package games.stendhal.client.actions; +import games.stendhal.client.ClientSingletonRepository; +import games.stendhal.client.gui.chatlog.StandardEventLine; +import games.stendhal.client.gui.wt.core.WtWindowManager; +import games.stendhal.client.sound.SoundSystemFacade; + /** * Set sound characteristics. @@ -17,7 +22,15 @@ class MuteAction implements SlashAction { * @return true if was handled. */ public boolean execute(final String[] params, final String remainder) { - new SoundAction().toggleMute(); + boolean play = Boolean.parseBoolean(WtWindowManager.getInstance().getProperty("sound.play", "true")); + play = !play; + WtWindowManager.getInstance().setProperty("sound.play", Boolean.toString(play)); + SoundSystemFacade.get().setMute(!play); + if (play) { + ClientSingletonRepository.getUserInterface().addEventLine(new StandardEventLine("Sounds are now on.")); + } else { + ClientSingletonRepository.getUserInterface().addEventLine(new StandardEventLine("Sounds are now off. (You may need to change the zone to stop the background music).")); + } return true; } diff --git a/src/games/stendhal/client/actions/SoundAction.java b/src/games/stendhal/client/actions/SoundAction.java index 6804d2f6ee..52ff72aa2e 100644 --- a/src/games/stendhal/client/actions/SoundAction.java +++ b/src/games/stendhal/client/actions/SoundAction.java @@ -1,9 +1,9 @@ package games.stendhal.client.actions; +import games.stendhal.client.ClientSingletonRepository; import games.stendhal.client.gui.j2DClient; import games.stendhal.client.gui.chatlog.StandardEventLine; import games.stendhal.client.gui.wt.core.WtWindowManager; -import games.stendhal.client.sound.SoundSystemFacade; import games.stendhal.common.MathHelper; /** @@ -25,7 +25,7 @@ class SoundAction implements SlashAction { final String command = params[0]; if (command.equals("mute")) { - toggleMute(); + ClientSingletonRepository.getUserInterface().addEventLine(new StandardEventLine("Please use /mute.")); } else if (command.equals("volume")) { volume(params); } @@ -33,21 +33,6 @@ class SoundAction implements SlashAction { return true; } - /** - * toggles the mute state of sounds. - */ - void toggleMute() { - boolean play = Boolean.parseBoolean(WtWindowManager.getInstance().getProperty("sound.play", "true")); - play = !play; - WtWindowManager.getInstance().setProperty("sound.play", Boolean.toString(play)); - SoundSystemFacade.get().setMute(!play); - String qualifier = " "; - if (!play) { - qualifier=" not "; - } - j2DClient.get().addEventLine(new StandardEventLine( - "Sounds are" +qualifier + "now on.")); - } /** * sets the volume of sounds From 0f6a9dcd011e02f5f446ea20bc7f101cec008787 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Wed, 17 Feb 2010 20:33:53 +0000 Subject: [PATCH 13/44] backported "Draw ignored players with DstOut composition" by kiheru --- src/games/stendhal/client/entity/User.java | 49 ++++++++++++++++--- .../client/gui/j2d/entity/Player2DView.java | 19 +++++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/games/stendhal/client/entity/User.java b/src/games/stendhal/client/entity/User.java index cab0524657..1c273c275e 100644 --- a/src/games/stendhal/client/entity/User.java +++ b/src/games/stendhal/client/entity/User.java @@ -7,10 +7,10 @@ import games.stendhal.client.stendhal; import games.stendhal.client.gui.chatlog.HeaderLessEventLine; import games.stendhal.client.update.Version; import games.stendhal.common.Grammar; -import games.stendhal.common.KeyedSlotUtil; import games.stendhal.common.NotificationType; import java.awt.geom.Rectangle2D; +import java.util.HashSet; import marauroa.common.game.RPObject; @@ -22,6 +22,7 @@ import marauroa.common.game.RPObject; public class User extends Player { private static User instance; + private HashSet ignore = new HashSet(); private String serverVersion = null; @@ -267,6 +268,13 @@ public class User extends Player { NotificationType.ERROR)); } } + + if (changes.hasSlot("!ignore")) { + RPObject ign = changes.getSlot("!ignore").getFirst(); + if (ign != null) { + addIgnore(ign); + } + } } } @@ -274,6 +282,12 @@ public class User extends Player { public void onChangedRemoved(final RPObject base, final RPObject diff) { modificationCount++; super.onChangedRemoved(base, diff); + if (diff.hasSlot("!ignore")) { + RPObject ign = diff.getSlot("!ignore").getFirst(); + if (ign != null) { + removeIgnore(ign); + } + } } /** @@ -362,11 +376,34 @@ public class User extends Player { return false; } - // compatibility with 0.79 server - if (!User.get().rpObject.hasSlot("!ignore")) { - return false; + return User.get().ignore.contains(name); + } + + /** + * Add players to the set of ignored players. + * Player names are the attributes prefixed with '_'. + * + * @param ignoreObj The container object for player names + */ + private void addIgnore(RPObject ignoreObj) { + for (String attr : ignoreObj) { + if (attr.charAt(0) == '_') { + ignore.add(attr.substring(1)); + } + } + } + + /** + * Remove players from the set of ignored players. + * Player names are the attributes prefixed with '_'. + * + * @param ignoreObj The container object for player names + */ + private void removeIgnore(RPObject ignoreObj) { + for (String attr : ignoreObj) { + if (attr.charAt(0) == '_') { + ignore.remove(attr.substring(1)); + } } - // end compatibility - return KeyedSlotUtil.getKeyedSlot(User.get().rpObject, "!ignore", "_" + name) != null; } } diff --git a/src/games/stendhal/client/gui/j2d/entity/Player2DView.java b/src/games/stendhal/client/gui/j2d/entity/Player2DView.java index 6e9c7b702f..6ee9375d3f 100644 --- a/src/games/stendhal/client/gui/j2d/entity/Player2DView.java +++ b/src/games/stendhal/client/gui/j2d/entity/Player2DView.java @@ -18,6 +18,7 @@ import games.stendhal.client.entity.User; import games.stendhal.client.sprite.Sprite; import games.stendhal.client.sprite.SpriteStore; +import java.awt.AlphaComposite; import java.awt.Graphics2D; import java.util.List; @@ -41,6 +42,8 @@ class Player2DView extends RPEntity2DView { * Sprite representing grumpy. */ private static Sprite grumpySprite; + + private boolean ignored = false; /** @@ -104,6 +107,15 @@ class Player2DView extends RPEntity2DView { return store.getFailsafeOutfit(); } } + + @Override + protected AlphaComposite getComposite() { + // Check for ghostmode to avoid ignored ghostmode admins becoming visible + if (User.isIgnoring(entity.getName()) && !((RPEntity) entity).isGhostMode()) { + return AlphaComposite.DstOut; + } + return super.getComposite(); + } /** * Determine is the user can see this entity while in ghostmode. @@ -152,6 +164,13 @@ class Player2DView extends RPEntity2DView { */ @Override protected void draw(final Graphics2D g2d, final int x, final int y, final int width, final int height) { + boolean newIgnoreStatus = User.isIgnoring(entity.getName()); + if (newIgnoreStatus != ignored) { + visibilityChanged = true; + ignored = newIgnoreStatus; + markChanged(); + } + super.draw(g2d, x, y, width, height); if (((Player) entity).isAway()) { From 6f20d5ddb63aeae1348a96050145f0c67b816ed1 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Wed, 17 Feb 2010 20:55:49 +0000 Subject: [PATCH 14/44] backport of fixed NullPointerException on non existing files by plassy (fixes #2953740) --- .../common/resource/ResourceManager.java | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/games/stendhal/common/resource/ResourceManager.java b/src/games/stendhal/common/resource/ResourceManager.java index bb47a82ea9..1f9cc53d47 100644 --- a/src/games/stendhal/common/resource/ResourceManager.java +++ b/src/games/stendhal/common/resource/ResourceManager.java @@ -55,11 +55,18 @@ public class ResourceManager extends ResourceLocator } } - private class CPSchemeLocator implements ResourceLocator.Locator + private interface SchemeLocator + { + void addSearchPath(String path); + InputStream locate (URI uri); + boolean isLocatable (URI uri); + } + + private class CPSchemeLocator implements ResourceLocator.Locator, SchemeLocator { final ArrayList mPaths = new ArrayList(); - void addSearchPath(String path) + public void addSearchPath(String path) { if(path.endsWith("/")) path = path.substring(0, path.length() - 1); @@ -87,25 +94,27 @@ public class ResourceManager extends ResourceLocator { InputStream stream = locate(uri); - try + if(stream != null) { - stream.close(); + try + { + stream.close(); + } + catch(IOException exception) + { + assert false: exception; + stream = null; + } } - catch(IOException exception) - { - assert false: exception; - stream = null; - } - return stream != null; } } - private class SchemeLocator implements ResourceLocator.Locator + private class FSSchemeLocator implements ResourceLocator.Locator, SchemeLocator { final ArrayList mDirectories = new ArrayList(); - void addSearchPath(String path) + public void addSearchPath(String path) { File directory = new File(mRootDirectory, path); @@ -113,7 +122,7 @@ public class ResourceManager extends ResourceLocator mDirectories.add(directory); } - File locateFile(URI uri) + public File locateFile(URI uri) { for(File directory: mDirectories) { @@ -146,7 +155,7 @@ public class ResourceManager extends ResourceLocator } } - private final HashMap mSchemeLocators = new HashMap(); + private final HashMap mSchemeLocators = new HashMap(); private File mRootDirectory = null; public void addScheme(String name, String ...searchPaths) @@ -156,10 +165,10 @@ public class ResourceManager extends ResourceLocator if(!mSchemeLocators.containsKey(name)) { - CPSchemeLocator locator = new CPSchemeLocator(); + SchemeLocator locator = new CPSchemeLocator(); mSchemeLocators.put(name, locator); - setLocator(name, locator); + setLocator(name, (Locator)locator); for(String path: searchPaths) locator.addSearchPath(path); @@ -168,7 +177,7 @@ public class ResourceManager extends ResourceLocator public void addSearchPath(String scheme, String path) { - CPSchemeLocator locator = mSchemeLocators.get(scheme); + SchemeLocator locator = mSchemeLocators.get(scheme); assert locator != null; assert path != null; From 02319cbac9e246c9cb818532856a0b2c3eec94ab Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Wed, 17 Feb 2010 21:22:03 +0000 Subject: [PATCH 15/44] increased volume of dungeon sound --- data/conf/zones/semos.xml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/data/conf/zones/semos.xml b/data/conf/zones/semos.xml index 5ff7f8a853..25e8510425 100644 --- a/data/conf/zones/semos.xml +++ b/data/conf/zones/semos.xml @@ -1980,7 +1980,7 @@ Mature sheep wanted: please speak to Sato the_forsaken_mine - 20 + 40 @@ -1992,7 +1992,7 @@ Mature sheep wanted: please speak to Sato the_forsaken_mine - 20 + 40 @@ -2003,7 +2003,7 @@ Mature sheep wanted: please speak to Sato the_forsaken_mine - 20 + 40 @@ -2051,7 +2051,7 @@ Mature sheep wanted: please speak to Sato the_forsaken_mine - 20 + 40 @@ -2062,7 +2062,7 @@ Mature sheep wanted: please speak to Sato the_forsaken_mine - 20 + 40 @@ -2076,7 +2076,7 @@ Mature sheep wanted: please speak to Sato the_forsaken_mine - 20 + 40 @@ -2087,7 +2087,7 @@ Mature sheep wanted: please speak to Sato the_forsaken_mine - 20 + 40 @@ -2166,7 +2166,7 @@ Mature sheep wanted: please speak to Sato the_forsaken_mine - 20 + 40 @@ -2378,7 +2378,7 @@ Mature sheep wanted: please speak to Sato the_forsaken_mine - 20 + 40 @@ -2394,7 +2394,7 @@ Mature sheep wanted: please speak to Sato the_forsaken_mine - 20 + 40 @@ -2425,7 +2425,7 @@ Mature sheep wanted: please speak to Sato the_forsaken_mine - 20 + 40 From 34e51b64f631edd38f4e0a0dcebe6ec81ae1dd8b Mon Sep 17 00:00:00 2001 From: Kimmo Rundelin Date: Wed, 17 Feb 2010 23:35:11 +0000 Subject: [PATCH 16/44] added ignored player drawing --- doc/CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/CHANGES.txt b/doc/CHANGES.txt index 203b151aad..5f00e51822 100644 --- a/doc/CHANGES.txt +++ b/doc/CHANGES.txt @@ -8,6 +8,7 @@ Changelog - having multiple correct answers for a riddle now possible - athor labyrinth redrawn - h2 database support +- ignored players are drawn as black forms *bug fixes* - numerous small map fixes @@ -18,6 +19,7 @@ Changelog - feedback on using portals and chests from too far away - fixed "Drag and drop sometimes misses slots and hits ground instead" (was for drag and drop onto same slot) - better reject message for inactive accounts +- fixed leander stealing all the pizzas of a player who has failed the quest previously *code* - sound system rewritten and using oggs From 8a1315a96b201aacc4ae062872d475db619a765f Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Thu, 18 Feb 2010 18:20:20 +0000 Subject: [PATCH 17/44] fixed logout while dying bug --- doc/CHANGES.txt | 2 ++ .../core/engine/StendhalRPRuleProcessor.java | 23 ++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/doc/CHANGES.txt b/doc/CHANGES.txt index 5f00e51822..e9ac1a93e9 100644 --- a/doc/CHANGES.txt +++ b/doc/CHANGES.txt @@ -33,6 +33,8 @@ Changelog +0.80.1: server only release +* fixed logout while dying 0.80 *features* diff --git a/src/games/stendhal/server/core/engine/StendhalRPRuleProcessor.java b/src/games/stendhal/server/core/engine/StendhalRPRuleProcessor.java index d91d89a135..1924055fad 100644 --- a/src/games/stendhal/server/core/engine/StendhalRPRuleProcessor.java +++ b/src/games/stendhal/server/core/engine/StendhalRPRuleProcessor.java @@ -36,6 +36,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -210,15 +211,18 @@ public class StendhalRPRuleProcessor implements IRPRuleProcessor { * * @param entity * The entity to check. - * @return true if the given entity has been killed this turn. + * @return pair of killed, killer if the specified entity did logout while dying, null otherwise. */ - private boolean wasKilled(final RPEntity entity) { - for (final Pair entry : entityToKill) { + private Pair removedKilled(final RPEntity entity) { + Iterator> itr = entityToKill.iterator(); + while (itr.hasNext()) { + Pair entry = itr.next(); if (entity.equals(entry.first())) { - return true; + itr.remove(); + return entry; } } - return false; + return null; } /** @@ -495,10 +499,13 @@ public class StendhalRPRuleProcessor implements IRPRuleProcessor { public synchronized boolean onExit(final RPObject object) { try { final Player player = (Player) object; - if (wasKilled(player)) { - logger.info("Logged out shortly before death: Killing it now :)"); - player.onDead(killerOf(player)); + + Pair entry = removedKilled(player); + if (entry != null) { + logger.info(object.get("name") + " logged out shortly before death: Killing it now :)"); + entry.first().onDead(entry.second()); } + if (!player.isGhost()) { notifyOnlineStatus(false, player.getName()); } From 061a9c90e25684ba85ff119d8f76fc116575c464 Mon Sep 17 00:00:00 2001 From: Kimmo Rundelin Date: Thu, 18 Feb 2010 21:47:30 +0000 Subject: [PATCH 18/44] converted to ogg --- data/sounds/kettle-1.ogg | Bin 0 -> 12857 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 data/sounds/kettle-1.ogg diff --git a/data/sounds/kettle-1.ogg b/data/sounds/kettle-1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..5f259bb386f7b520ce18620365bc3630d4d0ef59 GIT binary patch literal 12857 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 K7l&X{0{;VPw3#FT literal 0 HcmV?d00001 From 558cc536aa471476a2716ad53e58961e4d623194 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Fri, 19 Feb 2010 06:53:41 +0000 Subject: [PATCH 19/44] backported current state of sound system --- data/sounds/creak-1.ogg | Bin 0 -> 20541 bytes data/sounds/fire-2.ogg | Bin 0 -> 54057 bytes data/sounds/frog-1.ogg | Bin 0 -> 25587 bytes data/sounds/gorilla-4.ogg | Bin 0 -> 19438 bytes .../stendhal/client/actions/MuteAction.java | 3 +- .../stendhal/client/entity/AudibleEntity.java | 90 +++ .../stendhal/client/entity/Creature.java | 119 +-- .../client/entity/DomesticAnimal.java | 9 +- src/games/stendhal/client/entity/Entity.java | 33 - src/games/stendhal/client/entity/Food.java | 7 +- src/games/stendhal/client/entity/IEntity.java | 18 - .../client/entity/LoopedSoundSource.java | 30 +- src/games/stendhal/client/entity/NPC.java | 50 +- src/games/stendhal/client/entity/Player.java | 17 +- .../stendhal/client/entity/RPEntity.java | 11 +- src/games/stendhal/client/entity/Sheep.java | 20 +- .../client/sound/SoundSystemFacade.java | 103 +-- .../client/sound/manager/SoundFile.java | 96 ++- .../client/sound/manager/SoundManager.java | 113 +-- .../client/sound/system/SoundSystem.java | 698 +++++++++--------- .../system/processors/DirectedSound.java | 18 +- .../system/processors/OggVorbisDecoder.java | 9 +- .../system/processors/PCMStreamConverter.java | 36 +- .../sound/system/processors/Recorder.java | 89 +-- src/games/stendhal/common/memory/Field.java | 94 +++ 25 files changed, 896 insertions(+), 767 deletions(-) create mode 100644 data/sounds/creak-1.ogg create mode 100644 data/sounds/fire-2.ogg create mode 100644 data/sounds/frog-1.ogg create mode 100644 data/sounds/gorilla-4.ogg create mode 100644 src/games/stendhal/client/entity/AudibleEntity.java create mode 100644 src/games/stendhal/common/memory/Field.java diff --git a/data/sounds/creak-1.ogg b/data/sounds/creak-1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..503af1017a977922987c912075b6a7e5fe837b6f GIT binary patch literal 20541 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 literal 0 HcmV?d00001 diff --git a/data/sounds/fire-2.ogg b/data/sounds/fire-2.ogg new file mode 100644 index 0000000000000000000000000000000000000000..03575c9e0d95bddfb0b281e7a6ef03c50286f97b GIT binary patch literal 54057 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 G01^N&IM&<% literal 0 HcmV?d00001 diff --git a/data/sounds/frog-1.ogg b/data/sounds/frog-1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..1ea00e81122ab17ce7036b346a72c63486b9fea6 GIT binary patch literal 25587 zcmcG#WmsK3(=fU=PN9?*r?`7@cXutW#a)UO-$jcScWaBgQ=C$YyE|?1V#S^PE!z8j z-uLKJ5{QS>Yf~H72LME} z?BN3dP+rKN?`Me0L&^VyhmsFD+`<_s7|gK$72d-CB|{A6>ex72v#7kbBD1$K)%ru6 zOpc75m6eB;o1OiE76kDxGKIK=76cFl04i5}2I+iP++a*XaaDpfBJmNsJpysXr-4N5 ziu!}puCe5Kx#I8i>E4dTY61@h!o=QS2S>BI-o3W2eAd?3u`0fs65?@Nl$ z8q5_#Ar4++>3!V@6<83(W# z(5Dfs-OzuT48@nn_=sB0x0<<@tBa8?U(H9HDO>LqpApf-x0UHS(!ZI>HUh>zX6mA+ zgLqq+-MPAt{>Esly~ffR9$+pbJ0_V=d%ze?xmRp@bUheDEVqeCSEvSKvQ1v<843?D z*9TI6UcbKW5M^RLB#YXbk~7A>fiabyos~??|DgQA`@>|gzoM9-(XW>1Q6{#m$)ul} z60+}zU2L<;+0(u3->^z6#()#d5)6V)I6 z;U5{udvPQJ^H{Y9%BJt=3o~CoVkr8{PO^ug0RWX_qVcE1|MMIXjXtGTdj>wtlk8lR z8d93>7PHCjx{ZGNb0LNoe#_u<>HbP5*+Tcfp1)lOHJS_*_P-sW@4shyjoV_9%TR;cP*cl6JJ~_M z!F@5sV)4Rn^?yBv$bY){3;_7!De2=W=;POTW2odrt@{`NQKScrjQB|xv&I`wB^OU^ z6K~~}T$Gl+la|d;@&^ULd_Z{!5e07|ir+*Oy@}a=7jK=GTvVLSI8dnW5H=fAWosRj!H$lyQPhp|{3h$uDyyhT@kL?4o9Izqn{ zt3JTDNn{$qSD0xw!bg{tIKW4nmGF!{A57A3WhRcuZDuA+$kBoF(FpkN*qc`*qRzxQkpoL z8p%qU^%kR?4)ZTHmvJ?x8!YtC{j`(ampPQ?ACh3MJD4@aHnXEZKZK0X$ZtSMHtYtVqtEoHVw>T4GJmc3@ zRMPA?P*G7@Q+89sa?`xOn0~JlcaVyovAf0m ztmL@6lxC8}LzPJuhMpGMjbIT6O%K0SH$%e|cS9XZ{fm%EcXz`ii&bq4-3trD-Wm7R z3&qI>rP*osNlo|F8TXAehs8^b|`FT;c~$DCcCI14wV#&Coc-ec5`qS@or+p|-{R zg{JnoAJ~W==YFgBnzI)m%R{G=vtC{JZXJ0;@t{2G_JfTOIU#}`3S)5O(Z^tDa zCDxaj5YI=OpZF(Zh>syF2%JK}iB6A+{+kXTEpV5>|S>8Ew%ZL2|23T!i~>XBfEf;<~Y%CUN5M$DQy@0l4Lbq}stMR`4;1pVL2 zr*X~7+a4;X?unO=eyBXU37igZ7Yuxg>5r4F@kN2EKi+n zlPFl7eTytHUi~4a{wO~$Ufu3PqPn_mIjHw=4|@NclNuKpR9k8w_7Py>Of+~bsK%)| z@4?i6B00_pY8LSy2&jDygMT6J?#q90G~EpiFC^8tKmi5?TnH=$LUhmlCSU%6G=vy) zYHEX!WQ$cD!v~xOcYS=V=?92|K2NCrto!ms$SXenM#tUe!<()nfnEUkjerc~!adiL z;iV@;WBSu7&~O9CR!o*W2oqdN^D))s!MPFN88k~+KcHh1);t5=fwGDc2QHD(i4W`K zLo7e>*?(-a|FP2kD~1SMs_+7rB6GR))x4q~$QdC}kZ31z9@T)Q&9IU;!*<{ll_ zk+zFibvw2hJ=epwlo``9uC1jY%&t0Yvx=tk?>>k04SIINLYHL0s@2nauD>6Q$w;<~ zrJ&!SfoTxMw?z{C`wQ|b0PqZg2P6ZdIm)QAaAJ_~9(s#{3Xox%f&-ih>LJ)|5Ss{G zoaw05|G+TBQK-%Th2sH)6RF;zoAq+VQc*=$YP|?t>!-CTNVf9}Dv#h%DDBdBgshM1$bWVr;OIXAfL=t*r{hG@p*=`4VZF$* zpfwDJKA;mB=p=`el;jMH`%wL5{KpaG8EB;Z6A%y({=`5z1P~DZZe=>n|7JdHWgg&~ zgU0?ekl^C#=)eHq@Qfx(N^%M?P!f|+QIZCEeX6diEG?*nZGW z6{AdY*U=mK<97`F5P4VS z9>PUnzbAy)L4YD8Q!A6188%K=!~MJyfsoi2cmw!*5wE~f3>u2o@52fwjW=6GaA>3C z&{)`-ZE`07=-yLwa8m(vsxzmr!&Z$3{AVnD_s8+FswE|tN?Oht2*2}>*4}*boqKoL z*6Zom$YsKuY?e;vH0EXysQW4RJ-q>ym$?IXOLc6Q-{$$ksY>*@>0M!qC!8qUGm!bi zv#>2y13I+bMVKS&&(`}Ahj)${KekP0fG%Nve2PE_V6wZm({Q)#`O6a>_MQ^9^L)5P zfeRml^ZP<_Q;IVCQmunUq$jtX+)z}f*x|~?8`oDKIy}=fot5L6OlFWSKW^$6{^%TJ zw|;xNkFI>JXmo+JWT?#W!E_&8=usV-0;97c9zb|MH}n~{#YCU#czLzNkWzS9NTcsz z*8W5RXl7T7C4h9+X&hiqmr=Gm8$GeydoS|lLbbiEYi6o;yKKrk?Q*KvQ6#=uL!hL^ z6|<7$*-Fvgr>Z5fh#7xjq&xz}-XS74-kI)$Ug!%?OXw_O1beEzsHp8~-+k=NfrG>( znzz}KSFD}@p;HOX6*+n2m_IwhwSX3ffYJ{L6wV`MXaKfFK?ON{-}9>(4j2-$NwtFx zDdNvO3xX7*!GG`FT|^R4btGh)GTe_776~wMW;MEmNT?+JWVu!HCq9FxZ4Y*{Vv=z_ z$f)~z#P?RBJ#Cb3Oj|Jhxi#`sZZlRyKiq;Y9jnG1nRT!^nlXttt>u?Cp-q?tp?@kq7nRF-(9?M6NlIFf;oBvt&tuU5;RlaQ$v}t_WHiITcjd)k^!o4 z6%H=yHh!A@Z~WRSv>^)$7E~V>Ur|r>;rXgm?Ua~}h5rD6yx}?y)xo&zUtOqCw?!(m zrqv#}OMO^=Cv^ds1f9}==;XAgidn0f`eGpjfEm1B&^tA%0d8k%kJ`-ljB@yS)kWce z74~l=*!w`IL%2oSuYWx@Sy!k@+x_GCUQUW$qADhz_e)P z>pHv281tL63J?Xz79>&G4$F*OX6{IC05q!U{f;M;cQ>jx&jgWy&#z=&5z$=CA2fb* zf_xlwFi6=S5df%WHSSkxPW{K9ek>pdVox2@EHW(|_kG>P8xf(OTb7c)!cnc^9Yr66 z_2!mBaKXh>)OILU&*)QP+qBzhaR~q{^euOv1~f$WT%N3Yl$am_veJ(6okctd01`fk z4giW)1g7>-Sq`%R2b+d7t!DI8Z^z7B=IjOYc2eQ{zV#eChh^Ig??*ynXdA^%ub{kEqvYloj#xT+&ojb18Ho@tfM?S9wnyX1_ z(m$I?M!)AMCo)=~RO;*-Q&QhAWWS%bnaYIGnJjdcSv||2hQcA;Oz=cK8~Xd^x)p07 zBjUob@M&D$N*vhQdLz+eI#;!aKdkXWe0L!SWIsYGM2Q40oyZ#UX5-iBO~Z{91oW9nqF|omoW-AAjUX3ffcNR3o$T z>vW zM*T3*A5X*{A=|`y5Z4^9zPBHnZ(7uf zd#8jEuR}9^OT$xtI4q5<9Ld?0w^u?+Fn-461IN^!l6ViJH(-;k?C%~F>PKk{eQcZd z3Sw^A8)b?Bbw7}F^-(YwzIV93;3=@rI!U~;Q;&9zw%%H)RFMdJch)Z8RTZ~2h5Yf? zu191<|M77BIK&`hr{tYJLPVVsL1OoEAcde_(>NB(w6AdGb50YX{LqvMKdF!Xs*2|L zuN$;E)|gHz^l;@wdJsc@9-6<@YRi&u_A7kK4cP3~u^0JPA>OxOQ64}Z69d^P2pcdJ zd&JCM6B8@T{$I;p@0Z3oP~AHpA_xuixhy`q}VO2sy3JUrx&Ey=2$ zp!^l3c>-b$7^SQ)z+ACwpJK1MvYt#xU1ZvZ6{QWgamJ>hau7?hb_RsE82O)tYu$e% zYFm~(d>qEYFs~xQOy}xgU^H5}6!*5pESVrTJQ<&9PC^0-y*aDO8g%f##>I0ZJ0@3u#Svl?0wo z4U!|KA1qV7#HPS!P4TLuG@RL)Ot(99t35coZCla3Fg)2ViTp)B#ksTb(W$IeW8mfL z07aKp(tE5|h|J%Vnk##~R+)~EtvF*cihFEQ9h*#3F%1W7X&N7CZ<;_5_wBF4%tCjE z(biF9IDXL4vFD_y3vnK%KS`(9MAN^!y#m3ag5YFgnep@XnMp5dMB0Ud%Bgu; z1|AqS&O%zw-A4MKIQrGm-~IJD^(cQ329#dnHhFQWl=_)ylX_4 z!9YjAuXw`W1oIaQ!LQvyrP9r+Eh=oyJKg%QS`5tr>|A}oKN8e!v3*86770rez{xpn)(j{{cbh=^x{>_**94<#;pYLVsg2#AN7t#-yfD zwv3?1fm?tcW%oRPbw#%36 zCtrRigoqrN3i(N0*b6iANgp}X^Qbf5Uf)T{GWlz*N1Knl`Ra|zRIk6$ z+gh|6iho5S;{{1gw}9(}^G`Ov>)2mX^5nz**YJgr7(V-{O(ivb)TxIC0j$9Gd@t2*Ns(8FT>WzDz-vM! zOKhi9!Wt3XSF&;wwdcY%cZYMuFO0Cb;5j#iKvcwMesy&?&>igEcNzm@)LOD0HO9=hEk_wPP{F8(C1C&`1qGmAyPUl`1 z^b&oI8sbD!GXd~{Zk67;92&dkMS;^7;{j{PLZxnw#4@8j2l*8gZp-G+ti>6$bQT9W zOgWD>s&L)W+BmuOI8zAHK2jfcH&I|d#&Ym8{_TD}gUj@sLc4Iz+5ey#E&%9+=#^*~ zNZ8XbwY?DH@|Y$QXZJ8Sl*53&Mu=-Osbr%Bw+ z!_ICA{kThe_*R4LzLwkEExA1{m1s+~;1h7U{ris9vgZZ1mumsH=wUKAd(3@8BnOh7(7D4=;8IVnxp-=8fA*+;$7 zVUw}%O%0FwBNbT-M~yb|{z5dXqvw?!PX125PKL&XH@0#6cu$2adD1KU`zKdp`q?V> zxPKkRePfs5*>WFhf;-U`4uVf($}p&Ad3s*ImQK>b#pL{zvio+6LyzR+HNp2HL&P`g zmGmX0XYTd;5Z0=32rFbIN%Au1M>9~_Z&{eT8*5*}Q7bBqAOY}BQrbrLUJ>(TTfKm7 za`&8NeLk4w@R{VeE3kL<6y9A{&96=kI{HEu|53uZyz?7QedlKZk;w>9f6z{kwZmRj8$rA!2F-kuw3lf*nP zxTuilx-Bm_R=2;Sg}sbSDH~`AFBJMAumjuuj;R4)40{*iYM{Aj!s5QT*w2W*vV7)23D8zrQC|inxaDDyMV4 zKAos}{rv9t6PD4YLUEb*1?!uRq(bQl%->)n30DS9lqnvZnU4T&OY9S4xp^%yy(8r< z|7)d@*(^TK5!$S%V1S+DDLOjXfZr9@CChmyT~1ENfmA9#?f93HVuqrvQhmrU$r+< z8qDrXp7BNvw48JQ&OcPy9P1~80Q)^|_jdkqgZKUO{$Dg->8PU3{=B;UZ}OP~ptnYP zKJlluDiZ+h*;uxp*mp-+kTDL63Ut+M zR*g*JWqTMM?GR3pq!P0y=iQ0O?Wl`-JFsk>UwB@BW>%?5jS_qsK4ud%q$v6JEjh3^ zLn!3iB%Hui(3_K@Gx{sRe5)O^qP(}=GqYIX-ErX*O1TAYv0>pmf)R4k#b#gIPpSNe z>9$5LPNX-EA-QS|>)}$N%v;Kqp4y|I-gFh-C37Rvl_3e(eZ^|CYP*v0LPaIxncLZ1 zU=+BHheOWy5mCpX<8BZ$`LT9@v! zg?KtqXlTKG%u0yU1&t%t50^aZc<*7HR~{;7pI<;mWuA%>z(358zI}+d&*M!VXy;bR zs4S&y_3sO1o%me6><04su>41phYNI1DIy;OOuk+bzLl0At9QNUQ3}CJ8uzusQZa9@ zr@4XP0mJ*B^QV5_z_CRE@^)rLMlZg=Hqh>G*y(fIe3|}fI1tt6*O5d#;IHZtO$h;A zVkdWYpLd_^?>~3y-U=gKV1c{L+VVdDJh7q%@O&#l2ZkcXW-c9oX|>^bOKF^Qy0pAQ zO#r7_I{LiwIqFqbFM$W>2>QdDx4=VZYN13TNSOmzexqIH8WHHKfp+4>nRCd<8*?r(_dOCfj^Ar}Z9ZUN4Bx8AMqIrUc8=6d`meT3y9{FYO@ zq~Y@+aE$kp{XfC09M>Cn{zISWDA%^@AB!c*{TUfiCG~>+VJovM5%I-WLwuugVZ%0W zI`^r$Rc6oM{y4Kdy?g_!Qcv=)sAz8|2%S8A!f11SzBqek$tygp>d9Ql+$a-z!tk@~ zwsCsunEI|mV3^k4Hos+4M3Zm~$hLGlSygFP#nk$+P{{1bG26#A^jC8`0q8iM$nG*v zRG!aW^rq2W3I6+0vg6Olaef=_LpXlA{(JjoPNY6UJ7)_e71rv-g~fS>q6>(5ew;2- zHs9Y6^bVff9jE&i8fY(REy+!1yujNJ(zj}T|X&AHTqY&HP5x@pB z^6{6;kz0*G8P#cVEmJm!HyrGWxjk_1FBvT?C?70JuxWixIdrkQH7&$zH*z z3Z+Uk2c>f#7BYJCRChL(2oPP)?!TLKUtMW;`4|BEkR{bQ{%NFx^l-e)z!&N)Ua|Debn=df+;|9jw%6Yvr6K;4@Ebtuo0)avSM zfh;7zWW>qoDZ_LFz;4NTrO%V=&~!lY|`I~baC)S0Ec=`ztj)SSzMX``kQC7xCKT7?Ts_IKY0e*Q|d$B zO= z5Ad~P{Hjn5?_2QoJpwBPsO!UeQ<=T; z;FSpg_^IDB#C<3Eo^(;Y;DB?r?}e#6`K7u9B)Tqah{QK_7<--m@+=f22Wp}sXD&z=ikp^wFgZc-Y&mcA zoxkfBgntB7sjRMEMEhTy!|qmhTH347kL93#;|j$E)Zo_e|CdP=WK3`$vC=mbMgCG! zW(XR90K{ic;qR7jdHV*u@HL@*ga)db2hVMbN;!fZuu)-2q+-3)W0j9Ta+S-N%H2Bmp!Dp@&amU>%|2=>W2hfTRR_qIX;*B|kHD0Z0AlcpR zBgn7`W_+RYh3oFy@8B{z?>8UmM5H(Zpy_PWnT&7Z3_E^Ci`=%1+X@;A1YW!|ra3L> zg?H=o@{@S>u(Ck=`C3I*NV#Y{g_3gC(dy%Y%mJKschhFlOd2INKva0R*}rt?g4Ex7 z>pU9EB^e?=-!pq33Lkjne&h?TGo!K(T>tbKfB*u~K9@&1_LsN&`;+AngRIu#XnHT` zL6#3-`Br|h6uG?yz*`LN-EO+GXWMiYO@6Q+VaWT4su5(yZBI>1x;o*a`dV)Dsf|2b zw`AkRf$ujf-b8l79d`k+i?&OkhZtZe8~EBzTXXYcat)vc zIEU8cZ;*m=-xLKvK!Lwm!K1mE!V)C_ey>-p70vhY+&vqX z78^wZF7CA4)U9yFGTFi~|7+Uu?UO26RkPG+MNdbNN*9LiTQamhwS$dB87Np@` z4xs-4bV#t^Kll-t=t8~04;>?fjy3>{kTE=q3V;1BIyCelmxBH=_y#==3^aM<6qJ-y zKH_X11ovpPSmk4ikc-(g)yyQ;ih`0zAAZ z&}lSNW>y$f+epyv-c&Fuv1)Z5S1-=hWX-T@U(G(&+NTAT-|(Fs;P-TDJf53m)YME+ zz4C1sbgC=rv2ZUkn!8t-t0?|n!}6I*d%UEeQg{S&gdEb2= zYGbP^Cd-eO!pWjtp?HZ|h!4;`Bnk2h9q_(Y%<)zhwyh8HEt#$UmEIXYm9NlSTc0Md zNp;&{S63v_+VTlA>=R$N;>{b#ueRZ(d`<>BSOzN_of~Rv%U9^UN@@_hNRt6-bo20% z6fy+;H?$G~`vAlGKIwGwV%8pe8-w{dtF-AB9|zWhfe%2vS1;QMj@8S{hmJS6xvNc6xyJfbkoYU5Qv!tb?#dtnYBZV^Un(m&bj2@7oW2ls!6@s@=V#J9v zaqShU+Tg5f7+pt(UJ3y)kp5a-f2HC7y+!(7gr*W-3Q%DCeDq6t17m zw8&u)pTZ}JM-QeTNa-0z1^^9mtenPBF)A?qB`gP-4kULI#xMVNbtbT z?FLKAem{{Y1@OD=E?|}R>Uvnj_r&~DyDv&E$%_5Q6RN5_@Mcf&e$KO6GzjkA*Zn&Y zKc(B#B{q+bnV&K@mN*})r@b>V0c-B9^FH*_do(;V&2n^FY1=y4y;^5$nXdFropjHY zjpbzw61j-nC+CU^fG_XKam|(Qe?A*nnsI}T`cp5BY7pZF zR~@^Pr>ECnZ_ZmXz9>O!@@;u)_eY$f1~fgmZzn~3y{YJsfU0_57;Mo>=)zTG)^!W6 zbLrsjS2Q3Mf`T91S9`mnX*HwKgC9;0#Lk|#pS|ntty~rKGPt6($_Sb6Q0lWlWjdjF z2Ef$~EZ)L*>@l|#*nvMzXzj>2b^q!MQ+tD*)0jbqxcXJQ`fcN31uK3gxO;f4=mE10 zEx-hd%m<#|cX-tt-3L5Lx^6dzn>KblJvyRF1&%GI1`h)oG)=yEHk0_k7#tl{4obDz zdRRxjs~{iQzkovoZhSk4rC0ET7F7FPjNDHGnr4j8<96*ue%5qw*m_j)({>09ZuP1k z%Q#%g>9C8~4yts;Up*~0vdhL7@=-Hve>JsdQeRg&|Le=<`^D?VaOTX#pKA>j(j$K~ zBC0RHvLs^!H4OTg3~(kfi|$pbFP4eSA7(Rv>!hxMYwg4FIgGAR$zEB>Wz%c?X8_;M5mc~iFn#l^1mht!wrKH&RT==a97RQvUK0V;R_spa`(On>WLUsuxY71 zU^c+(AZD_O$$Mmfn_3q1i-OmWfY=mss|1HOd#hwwMdS0+F>dqsZ?ye?^8LJ;zI0vs zIdlzwbPFY6MfX*bo-ls{NrF%Mk==O`$kJ=5Odlchd|UC`*RrQunT9i*GOi7F&wdXI z(3KBa_(2SDp>Re`cx!0iHHV@bL?I9U(2dnWBdl1Xu7$9K4+q}FUUM-Rvew{ihXfA> zKR6muhv{5h{W(IoQPEL@G4Ka8 zZYvhp2ZuH+IC*&Ola|@9(C7FpY4GtMb|s?ovFnc}Ztxh=j?7N3nRl5+3f=9EjulQX zWRQ}Y+O2*Vyx9?;bVZFea?Bbx_$V~dj4L!wBF%Fc&Ws{GieZli=j{Qth1RBwb@5%& zN`2np`-}yUQi10i=4Tx(t(f1dzcy#?j}49&zR-fLkcwnq1W z$G&;CdNHj~S&7SOz}1DMs?w0)@=1D}KpU@*+RfeeonKC=x;}0fVI8V68bU!S$+S=2 zPv@a6D%y*+Uthh<-dAQC^&=8}Mj*FBx0c;YQRD6P(H(mn;Mj`v2zcY4oVdT*VvM@X zU?ebQz7!g>gJ?PN39koWBtlF7A!fs{UoU~ zGS)*`G+KS;y>MWeA*zlYJfz>qPDFP6@*Z2hX_j6wa`pax4X?4hr9vpnpS9}3O}&X3 zO@mBIRv`};Hb?N}?lSWP4!E1@{rU+CKvCP1g56H4aDFGyWO$DB^z=3L_ON=6uyOOx z=I#zjf)}3wKvv1Xk?!Q1NAv)nPv6ykZHD>P!R6PnwF_arC0w1A2v*Q~14YSG&XA~cv2Ro)E=SYM^fpyIF~UzBq_}bF2NpYX9f*%-2>Is5{iu~p^{S1txmT)fA>;mwB{3zT6?UZILcPm{`ycs=SsNE-E*XS0qwENh4Pb+zJ#TRq5A??&P8e@}D+iff8P|oL|kphOOKIV$!uLZT&G}fSTxjb2x z#M1FQ?QBr##N-Js^sr+NHf#aaBj+&+;0pXKfUQ;RgOPt!xbz~nsH(6zG!0`1U#UBRY%CB3)5vS^kV zhQNI39Xq+wPX1gHwCRVz-ExaaIMNRQFt{PTZg*ug&dF?P!DC0zF*4#FHBc%$2ac20 zzr$jhuw#u9l5)y^ycaW|0Sw9@xyVqVv^EtJOtMJHde99ZnQ1QU%3L% z+MKj{u5_ZCVixSGH?!+Mc#We`yTR*XD?;8t859t8>ZCT+f0cM4;OoCBLc}PFaiiUw zDU1lBz>E@(;7ufeT(ozzmDgr!E*{N>EmwlT&>fNO{k1T-_XTf*MPnn9aRRC@RDX-j zMr00S-w)eOP$B9}Krfa8n+}1gKAHAe-d`$KxML_l9aVI)?boz|H^-+GklgKeB2Tq& zTKm9lw#Tw2Ek-UPU|pk};B9eud2U(`$<5%rs!g4zrA?q8>igP(xcEdB6_|n+TyOr8 zG>xIw&$(%+8uh%Wvo&l>OF6L>@R)f~ zi{5!ZS#7giUF^~YtWPw~`)KQ!TTQDhJVJy(B?sy*kQub;5655hK0z9z^X>TcX7cvY z-T>Z_k%Xn^@)sm-UO@FG)AGt3I?{hex&fi-&=_BLd4{?^pnbWLG*!`%9r)ND1E|X8 zH@+)baa!kS;()w6Wl_RX+%$*mflTN72?hpNSosUH(%93~-KO8&6}Y{VYW1B4lTWKeq)rU1~gZvh*y3cLLBr zwfcT%YZd>4dSUI=aEFov9Mz)LkrBnj26)L8Qxy0$LEUX0Q#tvZ;q}GVq%(K7WIgYfU0xzNj3rb31iwbDrm0!xk69YU8vv z_s(d>k9^2?u$3kY&*T)b-@l=@IT2?9s8+T2G|Bdtxla&eq2LrNS|#@ab=Yia&+x}6 z1QC0&_N>h^yPdMM=IwJ(Iul}@x?B8LXW!!iH7O|o)g-v5d|p$0Xq6lcK+`xPIK!SR z?jCi20c5=vkgi1V1s-9KVg)#{-(8_lREq*8)y9(n<3H^$LIv+}kQkE>GSz{-h0)!X z_4z9oRTU`MI%lHc>o_fvq~o4&Dz-;s5bPg~-&A6KT!mb5$N=!CFM#{(cN;_!Tl{@2 zqqoSXD=LjCX2bL08O3_^ zCXnP9AALphC1!=UVqU=jRPBdwebXpyR?9EpZ>v5&URD*Q}>Cj{JD{= zsRkzvL0D_-O~@q$0ML5`9T96L^k87&$X|GIKgBVn5`%raqViKIBv=5D1QZlY2hdTQMFO+&_4x(){Q<*b3(q$|KinhP^L>eJ~5OZ2Efo%cRsOX0OZ+THL3&{rFeaMH7w6D|lIFm4Cu$C=URZ|8O^p%@5@jeBiW!^ons z05sv%XYKosghnOo0{(B;+A*z@Xeb{eOln`Pu~jT^^q3SX9hZ2@BfP6OA9cpLUBeFm90^Lwi1pPOm> zx+90DhS*=fBYS2X;?GB{b>AVi61=f%l_gCv!kc509L1Hx4VZ&IbqdgYO)l2eDs{M; zpGo;|CDBZPKSzY60LkY7zHRuufMu)Jinhfp7vFFoxo+-oA|Oq&v~t%o9!xb zt-mO?tVr1}v-pVsE^WyoU%h3}>oR{JKYauv@b)&)si-Oaxmj5k8mh!VE#uGRpO(p@ z0O@&HWUBF~sf*&_5a023I)2SHmSR6=x%j3>U;2Q}qhVjyAFi2;hFlxOoR3fh0gn_S zXV~aQC*2!iLadynoI`)u$BSlm+6{ZEPgbJ+ih-u)2=MolQTeoa)GyA~9cr!OUfu>G zaQe?ot^@J(Kej5SaXe#?EN0Ofhwc%$MaEWN+bh;|wdrF!2q@nxb%(Td+!$hOGAz0@ zr@5{wpIwSl<_r-OI@*r2PKbFNkMIs0`-cQK>SLXc3KIFCAC%IZFcH|>eaMv4u8mxq zHvKjEIa9i!zSH>tVPWEW;0}tN-GJ-&bNmso2VT8CToDGi;Q(rrQ9IvvIE>FsQfu#4 zanS|s{EHJ@Mq<#q`?Rk%Z31kGDcFbrlS9{f57Dgy+FM$P?J(<#cJ3bNV+ReCzeEf> zU)iuY5H)U6N94cZ_5|YhbkEJ^x{;RpYOnl?A_T!zY)saqT8-L|lUfoxU~vqVib&R3 zd`p_Lpuo`=i3co!=D|r_sd5S-E&|YV-QB7{GKu!`x!#<*XO4`WZVAKQfJDcr;zGa` z6$UjRdg3IMc5^@KWI6XF3c_|3B^WxNF1FN^MDhc&z7ToW_A+#Sc?S8+5)cJ%mYc^- zMdQu~e1GIsh1MtNp$!l%Yus~eXW=Pmi5mlv50fj@Yvb$QL4_wzv#lh6z1VovX5C!q zHDP0i0$y;J!CIGDP{}d)j1XH#O*9RzOt+^2VRaBOIAE&%*+qJQ&rQ#_oPkZAc~%J3 zvc^p|;`~b)b!2dp9or%u)lC`abV?`)-vIae;0+wnn)bfj+!Nqo@0|EnF1n}XWm;SF z3ySV1FK6{Tfb_oQ%hM-oCCKgfo9~5dI#Y1~veS`dL(FY&0NRYl3YG$ZRC%BMn%}*Q zG9qrh%ifFu*WdCJUrV8s?Cx2^TmpVCxxRSAIytM6bwnLd?Qo!5s+E?Gl|l;d5ZUx) zwcCNBdLYH}IkNr$iygb@+z3pgOTXnYWTLW`!L`8szAo|R;3?prw(NY@kzuD4dCQT- zz&q>Z#*$G#{hBflkUxj~xgr4FKcUn6@Vl@jTzkHYJ>nB`T z6?YB%mRja8d^}Ly=NxUY^J~b3Tj*=S8_&b}FKvDWmOV59;EvCI^jbYD^h3!^@!|#J zaRu&~))N5y;Yjkst#Q_ZtzM60hisu7Q;lqiPXfantn66w*iV6YpV0U6;^zeoqmvS6 zb8(bKbNI#2(}&cpzIVAc6Z0AAX2nhi^R4{E6qEX?T#tk|IbIYac|+a{@r(BBZX?Kl z9iyUDG~|I@udwC*0q;~;;I|&)xAy(tPWUt8_0@`#?<7X%wXYWnVoF z6G*i9;_FV9N9%jHtX}C>*j#O9Jl-~>dmd(MFHRTLtfNpDQPJth@vEKhy8|;>bH-Nh znr7e+QB;_tpk>A7=OlV7*Nj~A?lJ$9;sAAGxMQM~0t4~7{!hX0qilaZoh*=s+j!HG zgs#$9-jYF}(d25|;N^;Ons^;?_M8kfsIR=lA@?b62QbM-xUTy7)~PszteSF!Wa&{O zlVDX8B&s;f(HE(6f?;*kJ+2Y0-^CP4m0PUFKHFRqd36!R-yAeHUCc>FDT#;)`{1ta zO*1Pe%|yiR?`Xp^1tub7gW{%#%Yz_J>cr!O{n>I3l6Ide(&Vh0Q?2&U9g2AJ1Jo>y zG01fn3|sd4(pH*%y&9Or5E8f>q>3w#+9+@RqUIFb>$!Jud7y}IOdu;MoM!>O26(E% zw2Y)e;n@y{tr=p-X;5^I551-c@Dn^*)ZxbWTZi0fyF^;|b~AyPC5;}+s9tGxViK+O zCm;I((~CQ$fjc9q(I>Vi9+J~GsnySzhf(`h@!l7r*@w5T1Y?sr?`p5PX_|6#wcw2P zcbst>CboR2G7zK|oWr1(eX*H0e>t#S;b7MNfh=}6=>-;!M`N>uc`2qcF-b$9%v)4k zz{m=`bN#*vGgg?DIQvr!K1HLaYenSQr7{GrO}NXo_`kPy`K(Bh;F*O1uM4XQj3v4T%8(ztFu50HdJx2mY<;+@XR{a{DF*cig>1V zXK)}eO)Vhz>r|icUrGg@TeRN4Ro<=MK9v#t(s4Gu0VVCxS0$c3`-?iw3F}G_zHzXq zwMSlYhZumRE-iw7coXf{3X5BR&%F~n>6bH16%HzEzc9}s zOA_DzBKbtUchcAD!@Buc8wKEjMt{l49sESfhTC{9p*XBvpK5)JlddR(Fi@ddDtX#? zk~z^h+l#q~Ibe_xC+KmT!++N{Gx+YKqB;SSFI(!pyqdip^C={WKkBE;++sZgPSVf2 zb4N5hM1u0GdY$)Fn`TWhlP^OD^KO0sCC8=S%aQCd;q(cLrtHZ`R^IGoY0)74za5dl zhk2>-Co$G#F8A)Tggz}SUWMD^BKT4A0hA4n&LPh{o8k~Omx>zk#P4TP0 zX57~D{e*!rv4kVz0J=Wu#Rmv;ND7h_Vgn%sBf!N_oR=W&5BrF3&)iq+54K=zUC!5; z#XE$_RfxlF0GqOGe~V{UDQkAqxfjj)#sh* z=k%b)0(9*wJ={p7cC{eY$W6rRUO#zXi9|TC7lX*H6lgdeUCVMv$xMVto0t%h(Jg^gnB0Tq6WVaQK z6{}0*W-(@}{YBL-r$2|harFlaOq+CfTz~cmxFq&WP*)h~+^RKWs83Pl53UkDc-H9H zqqC`6hWPa*&H!5Z=a;)q^C#8qI&6$xg-@~Y<5rqUgZKJ+__pobI1ZEz_uiC&8Oa<0 z9A`xNRCN3RfH^D0faYw<$IaZLIzEmAvC_wmJ~h!@S#Yu`F&fY+CIiGb4mSMXr3mRQ z?JndsOz!PH>!udK=(LJaK3T}FqGnGsF59h*OCNDZk#yNxNyx5A=<7drbRmX1h9X9E zD(Xnyur;shzI!5vvAyhPhp%l+n2t=pJvAPGOYvbF>K@C-8YSSj+7wS6DVh@V7x*gx zkYJO=*9RsTzv%@8kfAsfB1Am48sRwXCMpTp#b_TbLe24WPv8yho( zK5#2LJpS*p^lwiBLt}gJ13*{lEIVy;14%C+0mSDtPn7I6U2n*#JUR>&fV84=_MKbR zsT3F3aiff2_^{>qQ)91cpN&Kla;(^O zIR|3+J343oSWD`Xuyfs-5a*j@{k1Psvs7n=tB7#SW$e?;>H`uxsjRJ%(cNtL!h}@O zZRB1u>|pZx|3S^6=95@-jxPdqMA9x!Hg{M1>#Y@&o!o)=y%VXw72LwGV|~DF(e3+--0^-hIAY>LyGD9EZvG zrMvcbe?n`aQ~~_M{<7BBSB~6y?Ss>0e>`yJ{mcm-rkT^!{Y3u`Lc6jAN-fN$3j#t^ zFiRasod`)FKr$wztfg5d4~6eJJ7`8YCtNbb4^PG$?e_DW@jx>#P!+Av)dkZp#~c1#5n~c{MIh}%P>+t4GI8GwpF;KbP-}IV6rIg9DZ_!MU@4^XO7jK zh%xt0UWNvM3S}RND=IGLN5bSEkpQjVKdw~9W?f#)7KBQ@g{0w#mYw;K56PQvXMs)w zsyIMQnmTQTi3bnxuKnb|eq!c7DQzXO+O)E}n@R5PEU>d>2&d$lneFMhM!p6d37l2 z>#9Cl61179;$*_uPF58@H^?W?+7k;)2g&~B&(7W})PVf6Ym`8o0QQjiuU+%M*Ii0M zPu41Xt2F9_>gzRNu0Dyk$h%?s&(?@}m~^Y~e3JQzmeA_LHs(q(DpvEiCWAn!fWMgj zP?T|O#kkIMk3Of2KlDcUrJ#X2p635&na^YjK-?<)j&1J!-PrqEsD&{6rkZ}c)qcuX zO7I2%KMlN_u`=`~Gyr4JmakSn=+jf4ky_8Far(J$WyU4gX7!#+Ab{W=)eCY^`ITt{ zH~^}EjK<3SDf8#p)aR#M05r7W1^#IFW^-32`bDD9G6ZNiO$+LosF=;)T|eF`eFx#v zKRWhClhVz7AIE#$t#@ZE0X@NV^%W_NoyoEVxi>c7!!*9aa*wm+v6x{&};jV8sLa7SvfNbU<(du zI85XLmevhcs9g2gE7m@BK%%>w{0Qz2->72v7qD%dz#QIlgtpyGit0sEeER1!1;e}bNvd#4P&5j6^jGK~95(2)vYKfK? zAxQGtp~H2)G&kA89ea3r{$)8U_=f1_uJz{hUIHrs5vrFmfUH`gjoZ}^Ae>t@{+pEh z&O#i2soTBrZVq?L-VLouR)7QT$rL5ImvmCotCZ{(K3vqeSxwOk{)Vt>c7!tU0b06O zbB~Gj&4&9eD;G10)~%4^%Y|F~;2sw_zUbU?NyI#;H8iBB$QKVaJeH-Tl0Sb^V0D|I zrrRlaAY}|6F#~EQFAtpRU8SQVn@nzcXAnc@D>78;n}LpQ9CrCoLD~_Fz&{XC!Uvya z(|kW&{mpe3F29CI(*-h^5Vg=+sG40{PUQ6eyNt4tVK^z!kHfA6mF-cB)fcd4kY~K z(HZEfkU)u_iejyUoiX3L67qep!X?X-c%wbW3r#XOKoC$O`LR>3$d+lXVX?5)Xg7Yr zMAo{l&|WyAThg+?16lg1(Oguy*1%kbe-E&^+~lp`sa|ten0_TR+jQT2_L6l9AN-Oo zVe&5k4k=&l7k@q!lb?Q3p}YkgjO+IVQS!^1PKjm?S;Eac}N5l~VRn zec=Nz`L_>d53FV%RVHtT06aY!0~9XPxnC>ylswRiYwCfKBxGo0XJ%rRi?1H}mDZ}D zY?(V7gq{wO+oO)Pv%!PT8?RTq4+j2;f6T&5zk`h3A95Le_s2*+zorUC?Z{3YeMP_o zd?`TJ_VI^pgj03@^_2EeNx#r$Vp0%Y7%w*Q>0NSA%8+ORtroSro7ZyB7sRK@$R?q) zMS2kE2m==5y9a>JmpQzwoj5FMpTF?aiKI(C$}Feha^8{%0@?w~mN=m*#Q~!Is09E> zXIs`?@W5i#cd(fQsSq11s)%UiFJW$01puAZUoaH+oE5431zsB9A@z@wYaEHkN>!Xm zabEF@ja?iB@B%joDBBYKiA~pyG1yUVk*##Hcz%U1_USUZr+&84DS@LkA|&AGAk3=o z&_M%C7>!S?-VPs74luBBAOPTZO|rhqi;?SFK}wc*WJ4f+Ny?A~SnvP_8%v);9f}Oo z=bEjbegP_*1_ylT@8His6T1DYn!Q)A=oQc^rEAiB_|%~4pl^Kt8U#3$4xR36P`n0W zi-kV{o?~?NGV$OMwwk!LEATSl(5dUE`2g*r@reV55vYf>f&l7nuFfLs&VmPMFL~rW$JC3m9a&l8}vor#QyH50F6+ zL_D&ABD{4m70Vrse@)4%xEZ%FQTZ{NAL*{Z%L2bY`@KNzeXTrTY~Vo@>mjgXdOx==m3hhxM9-LEEj}8E*hp;Ku8tK+`Dd+w%Sf7wLhWaQ2(4!qsfKAJIj(4InrqKVs!cjA7a>}5ozV$;P=Z!uW^cd z^tRNef!A@`*ZHQ0FtW4T2Qx}dLd6#0pxmu{M_==t0=YH(C0c*$ zM(1_dAR^!}B>!)@!=Jme+!dnrt3!EeEEdl^<_~eJ@AwAP3Y-dcWvNTQ-)m@_T&reD z=1Kh`*drKpTtCV11hW$nGVA4NBjg_yvfYr*eMb6TqqI|;<(e!d7rUHNt`t+{#xK$_ zyQ-ygO$M$qD8lXn1|^JGQv8dsdHGveQ1gaa~8Ds0^ziXv$-`FLuGuY zG4%GBlkJ1f0KU%Dw$$(A*GLsHGEsZ(TH|>65XUAxkisdW{h_Tz5 zU^u&ao)rZg1J@7!#MDJI2@z}PQh^=TS1kp=MWZ9#z81HcdXn% z>YlxI_>F-AZne7L6WIV~72%NkTbBV8?x?1N9;N?@lH}zneRYVH-*UWaP=mvW9))ai zP!fQ^A(p4n?Bd(bQEdw>#|3|mbA8b;4_|0eL&3DRMN;DFw|~Qh&32x#TJBcEtLGPK z4}jB2^lL2TfIq>-32JuEfY*@#Fv)g{0kqLH;B5php0@N%_Cype6Enrur*AX_HqA;W zA}o8F)o?3uso92Q-?vkeB_D;IDi%o$l}po6yA5)zoebYR+)RLnckYEoN*+D%@pLfq zJBk(gIED<;Zd%fL|BQKJ?ak3M#wWQKBiiI4#pv#{&{Pn4)?F4F5UfN-WhEGWL9LB* zD;Mh!;a@e&0%{X6E%wDM6NZ^*uG>fE`wAoQ5(%_xk)U1srp3yN$b?e9f=Rwam7;2` z-n-Gju4~!weHAknlu)61{mT2Bk%Uu-4Pz4mr_Ee>q0QmC&t}+T{dwi0H8Oy}YN~hq za;0=KTsUs!?$TU`pcMhrO=`iu60w(0tCa3>;vo)GG3w9y8ONVfRwYHu`1LW1uYE52 zp!>!!^ddmf);wloj3QiyC3WWIN7wG{@Y|9M0rL`nX4OpOs0<2K;v<8u&om^pD^pbW zZ5MnKgN!@b&!>gtxtA9#cPEzWJlE1wqD;Y?8f4X5A0n|1sEO*)Zf0b|fAc9*kknX$ z%Gn0eoL19!>61)NmQ!JK(@U{|MonMhl{@K&4l80lQBg*Y6_GIaSzJ(ysmAs|6Oo>| zxu~Y7vdzo;JQwp?)sk6LzszvXdC}k48|oA))VI(^8r9hF;$E|B7%{0JCewHB6ve*x zDK@XyzG=w7TKx8P#A`^Sf-Y9E6mHnT{qoj+j~yt)8W}u^j1}zd*FwGKT$1rRB{`k4 zUFWxGcdqj|-+Vc0=fLYv;T19VlA_t^J=o>X@|ttYS6D#t9eIwf?u02)vNw@7O0h*P z`%jWI?KYmx?s4pODfR>;%+(?L1ENlJ^%}d%t1k)a+P+YzPyW0&1-lsD9+iD^@fo(_ zQy`}5aB3nwHFk@9PV0s2yi&+g_ST`xPrnLukLj5H(=0kfs&A~dL!w}IlWJA?YB3yv zjXRQTi~kb_XJC72#X5g?r&3Vzo>Sr+WDo*#KKOIV18SN2Gb8;N;>@zLp>)27k&!@r zC)J3iSyb~DM?mJ%Jzw|}DEH#zt3HGl& zSZg|!Uzrto*kbz&v)}(aa20VD_wf(4PbZ_$7EcN5=HZua!r#Y&@5sDDu{u8J?@_eWrH7|eE%iS$N+bd2b* zc^i9d`t2q*Hby?Tol?Jq_fJFFXfO+<>V_7gvWShfXJ&*83ntv6Kf+zMZ-yldvwo}y z%4^WvXmcGzI7P|J&b~bt<9;Kov8M5u=D|xhAgAL$1sBlw|EXgC7e8Fh@|M1Gs8E)D zO1bLs02WxlZt}$hgrxHHfSG5 z7`8ov>pp>6Re2;;N`Av%S92`AAG8S-`lscvuv(&u$+Fx6_-XvK){sJ9^vO}8s&XeC z=%1f>)3Cm!N)MsgsqFkaKS{Lz-4;&giQ{0~h8Z+#v%ZX!VddT72vJ5goM5HT5N7 zj68Mix!~;9y=f7qF>_pjVDmRGHFHbvu|bF~k5wuU>aseG6tYq+vVZW@4%PNDtOGA( z+~HLcRU4wcr(V=~ufn~q z@mW&Ws7%yV03QgQ9uOSxxc?%BKGXU!RF_xk^x?=a#RTcs%F{QPUxNz6EnR<~ps&ix zz+6+#_9+s~xmOw*_8t)m5leZpW_^V^kuW=c+?}=d=kNLx;6pMdvA}zW zYC2tAME}$A#9F%_Y!E+vIFz>WBx`g(cbEQBS$wzSzTCZ<$obtI|35g9 zy4GsBerg=wk9AgqHj*!Qebjwo-jz9-jQJl5dmqeCxMc@7*JQnkig6Z(N1)+Bgvxp8 zA~~yeAg+(V%Xx|;aAU^aiTeh@KmHFqZ@z?&i5iad3y}`hE+SZS5fAjJ2ar|JHw- KQ>O)~f&T%j25I;J literal 0 HcmV?d00001 diff --git a/data/sounds/gorilla-4.ogg b/data/sounds/gorilla-4.ogg new file mode 100644 index 0000000000000000000000000000000000000000..aa434e8034a0d940515597c75f5a09a9b38f5e6b GIT binary patch literal 19438 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 literal 0 HcmV?d00001 diff --git a/src/games/stendhal/client/actions/MuteAction.java b/src/games/stendhal/client/actions/MuteAction.java index 6abd6b43ac..749c600bf2 100644 --- a/src/games/stendhal/client/actions/MuteAction.java +++ b/src/games/stendhal/client/actions/MuteAction.java @@ -4,6 +4,7 @@ import games.stendhal.client.ClientSingletonRepository; import games.stendhal.client.gui.chatlog.StandardEventLine; import games.stendhal.client.gui.wt.core.WtWindowManager; import games.stendhal.client.sound.SoundSystemFacade; +import games.stendhal.client.sound.system.Time; /** @@ -25,7 +26,7 @@ class MuteAction implements SlashAction { boolean play = Boolean.parseBoolean(WtWindowManager.getInstance().getProperty("sound.play", "true")); play = !play; WtWindowManager.getInstance().setProperty("sound.play", Boolean.toString(play)); - SoundSystemFacade.get().setMute(!play); + SoundSystemFacade.get().mute(!play, new Time(2, Time.Unit.SEC)); if (play) { ClientSingletonRepository.getUserInterface().addEventLine(new StandardEventLine("Sounds are now on.")); } else { diff --git a/src/games/stendhal/client/entity/AudibleEntity.java b/src/games/stendhal/client/entity/AudibleEntity.java new file mode 100644 index 0000000000..0d035da4c2 --- /dev/null +++ b/src/games/stendhal/client/entity/AudibleEntity.java @@ -0,0 +1,90 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package games.stendhal.client.entity; + +import games.stendhal.client.sound.SoundSystemFacade; +import games.stendhal.client.sound.manager.AudibleCircleArea; +import games.stendhal.client.sound.manager.SoundFile.Type; +import games.stendhal.client.sound.manager.SoundManager.Sound; +import games.stendhal.client.sound.system.Time; +import games.stendhal.common.Rand; +import games.stendhal.common.math.Algebra; +import java.util.ArrayList; +import java.util.HashMap; + +/** + * + * @author silvio + */ +public abstract class AudibleEntity extends RPEntity { + + private AudibleCircleArea mAudibleArea = new AudibleCircleArea(Algebra.vecf(0, 0), 3, 20); + private HashMap> mSoundGroups = new HashMap>(); + private long mWaitTime = 0; + + protected void addSoundsToGroup(String groupName, String... soundNames) { + ArrayList soundNameList = mSoundGroups.get(groupName); + + if (soundNameList == null) { + soundNameList = new ArrayList(); + mSoundGroups.put(groupName, soundNameList); + } + + for (String name : soundNames) { + if (SoundSystemFacade.get().loadSound(name, "audio:/" + name + ".ogg", Type.OGG, false) != null) { + soundNameList.add(name); + } + } + } + + protected Sound getRandomSoundFromGroup(String groupName, boolean getCloned) { + ArrayList soundNameList = mSoundGroups.get(groupName); + + if (soundNameList != null) { + String name = soundNameList.get(Rand.rand(soundNameList.size())); + Sound sound = SoundSystemFacade.get().getSound(name); + + if (sound != null && getCloned) { + return sound.clone(); + } + } + + return null; + } + + protected Sound getSound(String soundName, boolean getCloned) { + Sound sound = SoundSystemFacade.get().getSound(soundName); + + if (sound != null && getCloned) { + sound = sound.clone(); + } + + return sound; + } + + @Override + protected void onPosition(double x, double y) { + super.onPosition(x, y); + mAudibleArea.setPosition(Algebra.vecf((float) x, (float) y)); + SoundSystemFacade.get().update(); + } + + protected void playRandomSoundFromGroup(String groupName, float volume) { + Sound sound = getRandomSoundFromGroup(groupName, true); + SoundSystemFacade.get().play(sound, volume, 0, mAudibleArea, false, new Time()); + } + + protected void playRandomSoundFromGroup(String groupName, float volume, long waitTimeInMilliSec) { + if (mWaitTime < System.currentTimeMillis() && Rand.rand(100) < 5) { + playRandomSoundFromGroup(groupName, volume); + mWaitTime = System.currentTimeMillis() + waitTimeInMilliSec; + } + } + + protected void playSound(String soundName, float volume) { + Sound sound = getSound(soundName, true); + SoundSystemFacade.get().play(sound, volume, 0, mAudibleArea, false, new Time()); + } +} diff --git a/src/games/stendhal/client/entity/Creature.java b/src/games/stendhal/client/entity/Creature.java index 3f24e13e12..0bf3df51b2 100644 --- a/src/games/stendhal/client/entity/Creature.java +++ b/src/games/stendhal/client/entity/Creature.java @@ -12,16 +12,12 @@ ***************************************************************************/ package games.stendhal.client.entity; -import games.stendhal.client.sound.SoundSystemFacade; -import games.stendhal.common.Rand; -import games.stendhal.common.constants.SoundLayer; - import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import marauroa.common.game.RPObject; -public class Creature extends RPEntity { +public class Creature extends AudibleEntity { /** * Debug property. */ @@ -102,95 +98,42 @@ public class Creature extends RPEntity { if (object.has("name")) { final String name = object.get("name"); + addSoundsToGroup("attack", + "punch-1" , "punch-2", "punch-3", + "punch-4" , "punch-5", "punch-6", + "swingaxe-1", "slap-1" , "arrow-1"); + if (type.startsWith("creature")) { if (name.equals("wolf")) { - moveSounds = new String[] { "bark-1", "howl-5", - "howl-2", "howl-11" }; - - } else if (name.equals("rat") || name.equals("caverat") - || name.equals("venomrat")) { - moveSounds = new String[2]; - moveSounds[0] = "rats-2"; - moveSounds[1] = "rats-41"; - // moveSounds[2]="rats-3"; - + addSoundsToGroup("move", "bark-1", "howl-5", "howl-2", "howl-11"); + } else if (name.equals("rat") || name.equals("caverat") || name.equals("venomrat")) { + addSoundsToGroup("move", "rats-2", "rats-41"/*, "rats-3*/); } else if (name.equals("razorrat")) { - moveSounds = new String[1]; - moveSounds[0] = "rats-1"; - + addSoundsToGroup("move", "rats-1"); } else if (name.equals("gargoyle")) { - moveSounds = new String[3]; - moveSounds[0] = "hyena-1"; - moveSounds[1] = "hyena-2"; - moveSounds[2] = "hyena-3"; - + addSoundsToGroup("move", "hyena-1", "hyena-2", "hyena-3"); } else if (name.equals("boar")) { - moveSounds = new String[2]; - moveSounds[0] = "pig-1"; - moveSounds[1] = "pig-2"; - + addSoundsToGroup("move", "pig-1", "pig-2"); } else if (name.equals("bear")) { - moveSounds = new String[3]; - moveSounds[0] = "bear-1"; - moveSounds[1] = "bear-2"; - moveSounds[2] = "bear-3"; - + addSoundsToGroup("move", "bear-1", "bear-2", "bear-3"); } else if (name.equals("giantrat")) { - moveSounds = new String[2]; - moveSounds[0] = "bobcat-1"; - moveSounds[1] = "leopard-11"; - + addSoundsToGroup("move", "bobcat-1", "leopard-11"); } else if (name.equals("cobra")) { - moveSounds = new String[1]; - moveSounds[0] = "snake-1"; - + addSoundsToGroup("move", "snake-1"); } else if (name.equals("kobold")) { - moveSounds = new String[4]; - moveSounds[0] = "panda-1"; - moveSounds[1] = "panda-2"; - moveSounds[2] = "racoon-1"; - moveSounds[3] = "lama-1"; - + addSoundsToGroup("move", "panda-1", "panda-2", "racoon-1", "lama-1"); } else if (name.equals("goblin")) { - moveSounds = new String[2]; - moveSounds[0] = "saur-3"; - moveSounds[1] = "saur-4"; - + addSoundsToGroup("move", "saur-3", "saur-4"); } else if (name.equals("troll")) { - moveSounds = new String[5]; - moveSounds[0] = "gorilla-1"; - moveSounds[1] = "gorilla-2"; - moveSounds[2] = "gorilla-3"; - moveSounds[3] = "gorilla-4"; - moveSounds[4] = "gorilla-5"; - + addSoundsToGroup("move", "gorilla-1", "gorilla-2", "gorilla-3", "gorilla-4", "gorilla-5"); } else if (name.equals("orc")) { - moveSounds = new String[2]; - moveSounds[0] = "lion-11"; - moveSounds[1] = "lion-22"; - + addSoundsToGroup("move", "lion-11", "lion-22"); } else if (name.equals("ogre")) { - moveSounds = new String[4]; - moveSounds[0] = "yell-1"; - moveSounds[1] = "groan-1"; - moveSounds[2] = "moan-1"; - moveSounds[3] = "fart-1"; - + addSoundsToGroup("move", "yell-1", "groan-1", "moan-1", "fart-1"); } else if (name.equals("skeleton")) { - moveSounds = new String[5]; - moveSounds[0] = "bones-1"; - moveSounds[1] = "evillaugh-3"; - moveSounds[2] = "evillaugh-5"; - moveSounds[3] = "ghost-1"; - moveSounds[4] = "ghost-2"; - + addSoundsToGroup("move", "bones-1", "evillaugh-3", "evillaugh-5", "ghost-1", "ghost-2"); } else if (name.equals("cyclops")) { - moveSounds = new String[4]; - moveSounds[0] = "laugh-33"; - moveSounds[1] = "evillaugh-4"; - moveSounds[2] = "grunt-1"; - moveSounds[3] = "grunt-2"; - + addSoundsToGroup("move", "yell-1", "laugh-33", "evillaugh-4", "grunt-1", "grunt-2"); } } } @@ -202,8 +145,6 @@ public class Creature extends RPEntity { } } - private long soundWait; - /** * When the entity's position changed. * @@ -215,16 +156,16 @@ public class Creature extends RPEntity { @Override protected void onPosition(final double x, final double y) { super.onPosition(x, y); - - if ((soundWait < System.currentTimeMillis()) && (Rand.rand(100) < 5)) { - if (moveSounds != null) { - SoundSystemFacade.get().play(moveSounds[Rand.rand(moveSounds.length)], x, y, SoundLayer.CREATURE_NOISE, 100); - } - - soundWait = System.currentTimeMillis() + 10000L; - } + playRandomSoundFromGroup("move", 1.0f, 10000); } + @Override + public void onDamaged(Entity attacker, int damage) { + super.onDamaged(attacker, damage); + playRandomSoundFromGroup("attack", 1.0f); + } + + // // RPObjectChangeListener // diff --git a/src/games/stendhal/client/entity/DomesticAnimal.java b/src/games/stendhal/client/entity/DomesticAnimal.java index a9ac6ac688..29fdc4332b 100644 --- a/src/games/stendhal/client/entity/DomesticAnimal.java +++ b/src/games/stendhal/client/entity/DomesticAnimal.java @@ -9,14 +9,12 @@ package games.stendhal.client.entity; // // -import games.stendhal.client.sound.SoundSystemFacade; -import games.stendhal.common.constants.SoundLayer; import marauroa.common.game.RPObject; /** * A domestic animal entity. */ -public abstract class DomesticAnimal extends RPEntity { +public abstract class DomesticAnimal extends AudibleEntity { /** * DomesticAnimal idea property. */ @@ -90,7 +88,8 @@ public abstract class DomesticAnimal extends RPEntity { @Override public void initialize(final RPObject object) { super.initialize(object); - + addSoundsToGroup("eat", "eat-1"); + /* * Idea */ @@ -145,7 +144,7 @@ public abstract class DomesticAnimal extends RPEntity { weight = changes.getInt("weight"); if (weight > oldWeight) { - SoundSystemFacade.get().play("eat-1", getX(), getY(), SoundLayer.CREATURE_NOISE, 100); + playRandomSoundFromGroup("eat", 1.0f); } fireChange(PROP_WEIGHT); diff --git a/src/games/stendhal/client/entity/Entity.java b/src/games/stendhal/client/entity/Entity.java index ee91c332b7..fb17f2d313 100644 --- a/src/games/stendhal/client/entity/Entity.java +++ b/src/games/stendhal/client/entity/Entity.java @@ -28,14 +28,6 @@ public class Entity implements RPObjectChangeListener, IEntity { * */ public final byte[] ID_Token = new byte[0]; - - /** - * an array of sounds. out of these randomnly chosen sounds are played while - * moving. - */ - protected String[] moveSounds; - - /** The current x location of this entity. */ protected double x; @@ -86,11 +78,6 @@ public class Entity implements RPObjectChangeListener, IEntity { */ protected String type; - /** - * Defines the distance in which the entity is heard by Player. - */ - protected double audibleRange = Double.POSITIVE_INFINITY; - /** * Quick work-around to prevent fireMovementEvent() from calling in * onChangedAdded() from other initialize() hack. @@ -270,26 +257,6 @@ public class Entity implements RPObjectChangeListener, IEntity { return !rpObject.isContained(); } - /* (non-Javadoc) - * @see games.stendhal.client.entity.IEntity#getAudibleArea() - */ - public Rectangle2D getAudibleArea() { - if (audibleRange == Double.POSITIVE_INFINITY) { - return null; - } - - final double tempWidth = audibleRange * 2; - return new Rectangle2D.Double(getX() - audibleRange, getY() - - audibleRange, tempWidth, tempWidth); - } - - /* (non-Javadoc) - * @see games.stendhal.client.entity.IEntity#setAudibleRange(double) - */ - public void setAudibleRange(final double range) { - audibleRange = range; - } - /** * Process attribute changes that may affect positioning. This is needed * because different entities may want to process coordinate changes more diff --git a/src/games/stendhal/client/entity/Food.java b/src/games/stendhal/client/entity/Food.java index 19cbe0e8c0..12dd1896fa 100644 --- a/src/games/stendhal/client/entity/Food.java +++ b/src/games/stendhal/client/entity/Food.java @@ -12,14 +12,12 @@ ***************************************************************************/ package games.stendhal.client.entity; -import games.stendhal.client.sound.SoundSystemFacade; -import games.stendhal.common.constants.SoundLayer; import marauroa.common.game.RPObject; /** * A food entity. */ -public abstract class Food extends Entity { +public abstract class Food extends AudibleEntity { /** * Amount property. */ @@ -64,6 +62,7 @@ public abstract class Food extends Entity { @Override public void initialize(final RPObject object) { super.initialize(object); + addSoundsToGroup("food", "pop-2"); if (object.has("amount")) { amount = object.getInt("amount"); @@ -95,7 +94,7 @@ public abstract class Food extends Entity { // TODO this causes problems because of unidentified content refresh // events (e.g. synchronizing) if (amount > oldAmount) { - SoundSystemFacade.get().play("pop-2", getX(), getY(), SoundLayer.CREATURE_NOISE, 100); + playRandomSoundFromGroup("food", 1.0f); } fireChange(PROP_AMOUNT); diff --git a/src/games/stendhal/client/entity/IEntity.java b/src/games/stendhal/client/entity/IEntity.java index 25b182e5c9..56fb98d45c 100644 --- a/src/games/stendhal/client/entity/IEntity.java +++ b/src/games/stendhal/client/entity/IEntity.java @@ -145,24 +145,6 @@ public interface IEntity { */ boolean isOnGround(); - /** - * @return the absolute world area (coordinates) to which audibility of - * entity sounds is confined. Returns null if confines do not exist - * (audible everywhere). - */ - Rectangle2D getAudibleArea(); - - /** - * Sets the audible range as radius distance from this entity's position, - * expressed in coordinate units. This reflects an abstract capacity of this - * unit to emit sounds and influences the result of - * getAudibleArea(). - * - * @param range - * double audibility area radius in coordinate units - */ - void setAudibleRange(final double range); - /** * Get the resistance this has on other entities (0-100). * diff --git a/src/games/stendhal/client/entity/LoopedSoundSource.java b/src/games/stendhal/client/entity/LoopedSoundSource.java index a075df0143..fc161f9901 100644 --- a/src/games/stendhal/client/entity/LoopedSoundSource.java +++ b/src/games/stendhal/client/entity/LoopedSoundSource.java @@ -24,31 +24,32 @@ package games.stendhal.client.entity; import games.stendhal.client.sound.SoundSystemFacade; +import games.stendhal.client.sound.manager.AudibleCircleArea; +import games.stendhal.client.sound.manager.SoundFile; import games.stendhal.client.sound.manager.SoundManager.Sound; +import games.stendhal.client.sound.system.Time; import games.stendhal.common.constants.SoundLayer; +import games.stendhal.common.math.Algebra; +import games.stendhal.common.math.Numeric; import marauroa.common.game.RPObject; public class LoopedSoundSource extends InvisibleEntity { - private String sound; + private Sound sound; private int radius; private int volume; private SoundLayer layer = SoundLayer.AMBIENT_SOUND; - private Sound soundObject; - @Override public void onChangedAdded(RPObject object, RPObject changes) { // stop the current sound - if (sound != null) { - SoundSystemFacade.get().stop(soundObject); - } + SoundSystemFacade.get().stop(sound, new Time(3, Time.Unit.SEC)); // udpate super.onChangedAdded(object, changes); + update(changes); - play(); } @@ -59,7 +60,8 @@ public class LoopedSoundSource extends InvisibleEntity { */ private void update(RPObject object) { if (object.has("sound")) { - sound = object.get("sound"); + String soundName = object.get("sound"); + sound = SoundSystemFacade.get().loadSound(soundName, "audio:/" + soundName + ".ogg", SoundFile.Type.OGG, true); } if (object.has("radius")) { radius = object.getInt("radius"); @@ -73,13 +75,21 @@ public class LoopedSoundSource extends InvisibleEntity { layer = SoundLayer.values()[idx]; } } + + if (object.has("sound") || object.has("layer")) { + if (layer != SoundLayer.BACKGROUND_MUSIC) { + sound = sound.clone(); + } + } } /** * plays the sound */ private void play() { - soundObject = SoundSystemFacade.get().start(sound, x, y, radius, layer, volume, true); + AudibleCircleArea area = new AudibleCircleArea(Algebra.vecf((float)x, (float)y), radius / 2.0f, radius); + float vol = Numeric.intToFloat(volume, 100.0f); + SoundSystemFacade.get().play(sound, vol, 0, area, true, new Time(3, Time.Unit.SEC)); } /** @@ -91,6 +101,6 @@ public class LoopedSoundSource extends InvisibleEntity { @Override public void release() { super.release(); - SoundSystemFacade.get().stop(soundObject); + SoundSystemFacade.get().stop(sound, new Time(3, Time.Unit.SEC)); } } diff --git a/src/games/stendhal/client/entity/NPC.java b/src/games/stendhal/client/entity/NPC.java index 36e72d4114..677de045f0 100644 --- a/src/games/stendhal/client/entity/NPC.java +++ b/src/games/stendhal/client/entity/NPC.java @@ -12,15 +12,12 @@ ***************************************************************************/ package games.stendhal.client.entity; -import games.stendhal.client.sound.SoundSystemFacade; -import games.stendhal.common.Rand; -import games.stendhal.common.constants.SoundLayer; import marauroa.common.game.RPObject; /** * An NPC entity. */ -public class NPC extends RPEntity { +public class NPC extends AudibleEntity { // // Entity // @@ -40,46 +37,20 @@ public class NPC extends RPEntity { final String type = getType(); if (type.startsWith("npc")) { - setAudibleRange(3); if (name.equals("Diogenes")) { - moveSounds = new String[2]; - moveSounds[0] = "laugh-1"; - moveSounds[1] = "laugh-2"; - // SoundSystem.startSoundCycle(this, "Diogenes-patrol", 10000, - // 20, 50, 100); + addSoundsToGroup("move", "laugh-1", "laugh-2"); } else if (name.equals("Carmen")) { - moveSounds = new String[2]; - moveSounds[0] = "giggle-1"; - moveSounds[1] = "giggle-2"; - - // SoundSystem.startSoundCycle(this, "Carmen-patrol", 60000, 20, - // 50, 75); + addSoundsToGroup("move", "giggle-1", "giggle-2"); } else if (name.equals("Nishiya")) { - moveSounds = new String[3]; - moveSounds[0] = "cough-11"; - moveSounds[1] = "cough-2"; - moveSounds[2] = "cough-3"; - // SoundSystem.startSoundCycle(this, "Nishiya-patrol", 40000, - // 20, 50, 80); + addSoundsToGroup("move", "cough-11", "cough-2", "cough-3"); } else if (name.equals("Margaret")) { - moveSounds = new String[3]; - moveSounds[0] = "hiccup-1"; - moveSounds[1] = "hiccup-2"; - moveSounds[2] = "hiccup-3"; - - // SoundSystem.startSoundCycle(this, "Margaret-patrol", 30000, - // 10, 30, 70); + addSoundsToGroup("move", "hiccup-1", "hiccup-2", "hiccup-3"); } else if (name.equals("Sato")) { - moveSounds = new String[1]; - moveSounds[0] = "sneeze-1"; - // SoundSystem.startSoundCycle(this, "Sato-patrol", 60000, 30, - // 50, 70); + addSoundsToGroup("move", "hiccup-1", "sneeze-1"); } } } - private long soundWait; - /** * When the entity's position changed. * @@ -91,13 +62,6 @@ public class NPC extends RPEntity { @Override protected void onPosition(final double x, final double y) { super.onPosition(x, y); - - if ((soundWait < System.currentTimeMillis()) && (Rand.rand(1000) < 5)) { - - if (moveSounds != null) { - SoundSystemFacade.get().play(moveSounds[Rand.rand(moveSounds.length)], x, y, SoundLayer.CREATURE_NOISE, 100); - } - soundWait = System.currentTimeMillis() + 2000L; - } + playRandomSoundFromGroup("move", 1.0f, 20000); } } diff --git a/src/games/stendhal/client/entity/Player.java b/src/games/stendhal/client/entity/Player.java index d69b2dff53..c05b51679e 100644 --- a/src/games/stendhal/client/entity/Player.java +++ b/src/games/stendhal/client/entity/Player.java @@ -16,7 +16,7 @@ import games.stendhal.common.NotificationType; import marauroa.common.game.RPObject; /** A Player entity. */ -public class Player extends RPEntity { +public class Player extends AudibleEntity { /** * Away property. @@ -129,6 +129,21 @@ public class Player extends RPEntity { } } + @Override + public void initialize(RPObject object) { + super.initialize(object); + + addSoundsToGroup("attack", + "punch-1" , "punch-2", "punch-3", + "punch-4" , "punch-5", "punch-6", + "swingaxe-1", "slap-1" , "arrow-1"); + } + + @Override + public void onDamaged(Entity attacker, int damage) { + super.onDamaged(attacker, damage); + playRandomSoundFromGroup("attack", 1.0f); + } // // RPObjectChangeListener diff --git a/src/games/stendhal/client/entity/RPEntity.java b/src/games/stendhal/client/entity/RPEntity.java index 7e3e77c88f..3580ed1610 100644 --- a/src/games/stendhal/client/entity/RPEntity.java +++ b/src/games/stendhal/client/entity/RPEntity.java @@ -18,12 +18,9 @@ import games.stendhal.client.stendhal; import games.stendhal.client.gui.chatlog.HeaderLessEventLine; import games.stendhal.client.gui.chatlog.StandardEventLine; import games.stendhal.client.gui.chatlog.StandardHeaderedEventLine; -import games.stendhal.client.sound.SoundSystemFacade; import games.stendhal.common.Grammar; import games.stendhal.common.ItemTools; import games.stendhal.common.NotificationType; -import games.stendhal.common.Rand; -import games.stendhal.common.constants.SoundLayer; import java.util.Collection; import java.util.Iterator; @@ -85,11 +82,11 @@ public abstract class RPEntity extends ActiveEntity { * The entities attacking this entity. */ protected List attackers; - +/* String[] attackSounds = { "punch-1", "punch-2", "punch-3", "punch-4", "punch-5", "punch-6", "swingaxe-1", "slap-1", "arrow-1" }; - + */ private boolean showBladeStrike; public enum Resolution { @@ -440,11 +437,11 @@ public abstract class RPEntity extends ActiveEntity { public void onDamaged(final Entity attacker, final int damage) { combatIconTime = System.currentTimeMillis(); resolution = Resolution.HIT; - try { + /*try { SoundSystemFacade.get().play(attackSounds[Rand.rand(attackSounds.length)], x, y, SoundLayer.CREATURE_NOISE, 100); } catch (final NullPointerException e) { // ignore errors - } + }*/ boolean showAttackInfoForPlayer = (this.isUser() || attacker.isUser()); showAttackInfoForPlayer = showAttackInfoForPlayer diff --git a/src/games/stendhal/client/entity/Sheep.java b/src/games/stendhal/client/entity/Sheep.java index cb397ea3f8..628615ec8f 100644 --- a/src/games/stendhal/client/entity/Sheep.java +++ b/src/games/stendhal/client/entity/Sheep.java @@ -12,9 +12,8 @@ ***************************************************************************/ package games.stendhal.client.entity; -import games.stendhal.client.sound.SoundSystemFacade; import games.stendhal.common.Rand; -import games.stendhal.common.constants.SoundLayer; +import marauroa.common.game.RPObject; /** A Sheep entity. */ public class Sheep extends DomesticAnimal { @@ -23,19 +22,20 @@ public class Sheep extends DomesticAnimal { // @Override - protected void probableChat(final int chance) { + public void initialize(RPObject object) { + super.initialize(object); + addSoundsToGroup("small", "sheep-2", "sheep-4"); + addSoundsToGroup("big" , "sheep-1", "sheep-3"); + } - final String[][] soundnames = { { "sheep-1", "sheep-3" }, - { "sheep-2", "sheep-4" } }; - final int which = Rand.rand(2); + @Override + protected void probableChat(final int chance) { if (Rand.rand(100) < chance) { - final String token; if (getWeight() > 50) { - token = soundnames[0][which]; + playRandomSoundFromGroup("big", 1.0f); } else { - token = soundnames[1][which]; + playRandomSoundFromGroup("small", 1.0f); } - SoundSystemFacade.get().play(token, x, y, SoundLayer.CREATURE_NOISE, 100); } } } diff --git a/src/games/stendhal/client/sound/SoundSystemFacade.java b/src/games/stendhal/client/sound/SoundSystemFacade.java index a404d2b55e..7de29a4376 100644 --- a/src/games/stendhal/client/sound/SoundSystemFacade.java +++ b/src/games/stendhal/client/sound/SoundSystemFacade.java @@ -6,6 +6,7 @@ import games.stendhal.client.gui.wt.core.WtWindowManager; import games.stendhal.client.sound.manager.AudibleArea; import games.stendhal.client.sound.manager.AudibleCircleArea; import games.stendhal.client.sound.manager.SoundFile; +import games.stendhal.client.sound.manager.SoundFile.Type; import games.stendhal.client.sound.manager.SoundManager; import games.stendhal.client.sound.system.Time; import games.stendhal.common.constants.SoundLayer; @@ -28,22 +29,21 @@ public class SoundSystemFacade extends SoundManager implements WorldListener { private static final Logger logger = Logger.getLogger(SoundSystemFacade.class); private static final SoundSystemFacade singletonInstance = new SoundSystemFacade(); - private static final Time fadingTime = new Time(100, Time.Unit.MILLI); private final HashMap sounds = new HashMap(); private final ResourceLocator resourceLocator = ResourceManager.get(); - private boolean mute = false; - + public static SoundSystemFacade get() { return singletonInstance; } private SoundSystemFacade() { - mute = !Boolean.parseBoolean(WtWindowManager.getInstance().getProperty("sound.play", "true")); + boolean mute = !Boolean.parseBoolean(WtWindowManager.getInstance().getProperty("sound.play", "true")); + super.mute(mute, null); } public void playerMoved() { float[] position = Algebra.vecf((float) User.get().getX(), (float) User.get().getY()); - setHearerPosition(position); + super.setHearerPosition(position); update(); } @@ -59,91 +59,52 @@ public class SoundSystemFacade extends SoundManager implements WorldListener { // exits the sound system } - public Sound start(String soundName, double x, double y, int radius, SoundLayer layer, int volume, boolean loop) { - if (!mute) { - Sound sound = prepareSound(soundName); - - AudibleArea area = new AudibleCircleArea(Algebra.vecf((float) x, (float) y), radius / 2.0f, radius); - Time myFadingTime = new Time(); - - if (loop) { - myFadingTime = fadingTime; - } - - float vol = Numeric.intToFloat(volume, 100.0f); - play(sound, vol, 0, area, loop, myFadingTime); - - // This is a work around because the music is played at 100% unless it is already playing otherwise. - changeVolume(sound, vol); - return sound; - } - return null; + public void stop(String soundName, Time fadeOutDuration) { + super.stop(getSound(soundName), fadeOutDuration); } - public void stop(Sound sound) { - stop(sound, fadingTime); - } - - private Sound setSound(String soundName, Sound sound) { - return sounds.put(soundName, sound); - } - - private Sound getSound(String soundName) { + public Sound getSound(String soundName) { return sounds.get(soundName); } - private Sound openSound(String fileURI, SoundFile.Type fileType) { + public Sound openSound(String fileURI, SoundFile.Type fileType) { return super.openSound(resourceLocator.getResource(fileURI), fileType); } - public void setMute(boolean mute) { - this.mute = mute; + public Sound openSound(String fileURI, SoundFile.Type fileType, int numSamplesPerChunk, boolean enableStreaming) { + return super.openSound(resourceLocator.getResource(fileURI), fileType, numSamplesPerChunk, enableStreaming); + } + + public Sound loadSound(String name, String fileURI, SoundFile.Type fileType, boolean enableStreaming) { + Sound sound = sounds.get(name); + + if(sound == null) { + sound = super.openSound(resourceLocator.getResource(fileURI), fileType, 256, enableStreaming); + + if(sound != null) { + sounds.put(name, sound); + } + } + + return sound; } public void play(final String soundName, final SoundLayer soundLayer, int volume) { AudibleArea area = SoundManager.INFINITE_AUDIBLE_AREA; - playNonLoopedSound(soundName, area, soundLayer.ordinal(), volume); + Sound sound = loadSound(soundName, "audio:/" + soundName + ".ogg", Type.OGG, false); + super.play(sound, Numeric.intToFloat(volume, 100.0f), 0, area, false, new Time()); } public void play(final String soundName, final double x, final double y, final SoundLayer soundLayer, int volume) { - AudibleArea area = new AudibleCircleArea(Algebra.vecf((float) x, (float) y), 3, 18); - playNonLoopedSound(soundName, area, soundLayer.ordinal(), volume); + AudibleArea area = new AudibleCircleArea(Algebra.vecf((float) x, (float) y), 3, 20); + Sound sound = loadSound(soundName, "audio:/" + soundName + ".ogg", Type.OGG, false); + super.play(sound, Numeric.intToFloat(volume, 100.0f), 0, area, false, new Time()); } public void play(final String soundName, final double x, final double y, int radius, final SoundLayer soundLayer, int volume) { AudibleArea area = new AudibleCircleArea(Algebra.vecf((float) x, (float) y), radius / 4.0f, radius); - playNonLoopedSound(soundName, area, soundLayer.ordinal(), volume); + Sound sound = loadSound(soundName, "audio:/" + soundName + ".ogg", Type.OGG, false); + super.play(sound, Numeric.intToFloat(volume, 100.0f), 0, area, false, new Time()); } - public void playNonLoopedSound(String soundName, AudibleArea area, int soundLayer, int volume) { - if (mute) { - return; - } - - SoundSystemFacade.Sound sound = prepareSound(soundName); - play(sound, Numeric.intToFloat(volume, 100.0f), 0, area, false, new Time()); - } - - public Sound prepareSound(String soundName) { - if (soundName == null) { - return null; - } - - Sound sound = getSound(soundName); - - if (sound == null) { - sound = openSound("audio:/" + soundName + ".ogg", SoundFile.Type.OGG); - setSound(soundName, sound); - } - - // TODO: Sound objects need to be cloned here to set individual properties - // But as long as that crashes the client because of OutOfMemoryErrors, - // we have to live with only one sound source per file doing the right thingy. - /* - if (sound != null) { - sound = sound.clone(); - }*/ - - return sound; - } } diff --git a/src/games/stendhal/client/sound/manager/SoundFile.java b/src/games/stendhal/client/sound/manager/SoundFile.java index 979cfd7e39..3bddccbd64 100644 --- a/src/games/stendhal/client/sound/manager/SoundFile.java +++ b/src/games/stendhal/client/sound/manager/SoundFile.java @@ -11,6 +11,7 @@ import games.stendhal.client.sound.system.processors.PCMStreamConverter; import games.stendhal.client.sound.system.SignalProcessor; import games.stendhal.common.resource.Resource; +import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import javax.sound.sampled.AudioInputStream; @@ -28,6 +29,7 @@ public class SoundFile extends SignalProcessor implements Cloneable private int mNumChannels; private int mSampleRate; private SignalProcessor mGenerator = null; + private Recorder mRecorder = null; private final Resource mResource; private final boolean mEnableStreaming; private final int mOutputNumSamples; @@ -52,7 +54,10 @@ public class SoundFile extends SignalProcessor implements Cloneable { assert resource != null; assert fileType != null; - + + if(!resource.exists()) + throw new IOException("audio resource doesn't exist: " + resource.getURI()); + mResource = resource; mFileType = fileType; mEnableStreaming = enableStreaming; @@ -60,7 +65,7 @@ public class SoundFile extends SignalProcessor implements Cloneable SignalProcessor decoder = chooseDecoder(resource, fileType, outputNumSamplesPerChannel); - if(decoder == null || !resource.exists()) + if(decoder == null) throw new IOException("could not load audio resource: " + resource.getURI()); if(enableStreaming) @@ -70,47 +75,81 @@ public class SoundFile extends SignalProcessor implements Cloneable } else { - Recorder recorder = new Recorder(outputNumSamplesPerChannel); - recorder.connectTo(decoder, false); + mRecorder = new Recorder(); + mRecorder.connectTo(decoder, false); - while(recorder.request()) + while(mRecorder.request()) /* pass */; - recorder.disconnect(); - recorder.trim(); - recorder.connectTo(mPropagator, true); - mGenerator = recorder; + mRecorder.disconnect(); + mRecorder.trim(); + + Recorder.Player player = mRecorder.createPlayer(outputNumSamplesPerChannel); + player.connectTo(mPropagator, true); + + mGenerator = player; } } + private SoundFile(Recorder recorder, Resource resource, Type fileType, int outputNumSamplesPerChannel) + { + mResource = resource; + mFileType = fileType; + mOutputNumSamples = outputNumSamplesPerChannel; + mEnableStreaming = false; + mRecorder = recorder; + mGenerator = recorder.createPlayer(outputNumSamplesPerChannel); + + mGenerator.connectTo(mPropagator, true); + } + public int getNumChannels() { return mNumChannels; } public int getSampleRate () { return mSampleRate; } + public void close() + { + if(mGenerator instanceof Recorder.Player) + { + mRecorder.clear(); + } + else if(mGenerator instanceof OggVorbisDecoder) + { + OggVorbisDecoder decoder = (OggVorbisDecoder)mGenerator; + decoder.close(); + } + else if(mGenerator instanceof PCMStreamConverter) + { + PCMStreamConverter converter = (PCMStreamConverter)mGenerator; + converter.close(); + } + } + @Override public SoundFile clone() { SoundFile file = null; - - try - { - file = new SoundFile(mResource, mFileType, mOutputNumSamples, mEnableStreaming); - } - catch(IOException exception) - { - assert false: "catched exception - " + exception; - } + if(mGenerator instanceof Recorder.Player) + { + file = new SoundFile(mRecorder, mResource, mFileType, mOutputNumSamples); + } + else + { + try + { + file = new SoundFile(mResource, mFileType, mOutputNumSamples, mEnableStreaming); + } + catch(IOException exception) + { + assert false: "catched exception - " + exception; + } + } return file; } public void restart() { - if(mGenerator.getClass() == Recorder.class) - { - Recorder recorder = (Recorder)mGenerator; - recorder.restart(); - } - else if(mGenerator.getClass() == OggVorbisDecoder.class) + if(mGenerator instanceof OggVorbisDecoder) { OggVorbisDecoder decoder = (OggVorbisDecoder)mGenerator; decoder.close(); @@ -122,7 +161,7 @@ public class SoundFile extends SignalProcessor implements Cloneable catch(IOException exception) { } } - else if(mGenerator.getClass() == PCMStreamConverter.class) + else if(mGenerator instanceof PCMStreamConverter) { PCMStreamConverter converter = (PCMStreamConverter)mGenerator; converter.close(); @@ -135,6 +174,11 @@ public class SoundFile extends SignalProcessor implements Cloneable catch(IOException exception) { } catch(UnsupportedAudioFileException exception) { } } + else if(mGenerator instanceof Recorder.Player) + { + Recorder.Player player = (Recorder.Player)mGenerator; + player.restart(); + } } private SignalProcessor chooseDecoder(Resource resource, Type fileType, int outputNumSamplesPerChannel) @@ -163,7 +207,7 @@ public class SoundFile extends SignalProcessor implements Cloneable case WAV: try { - AudioInputStream stream = AudioSystem.getAudioInputStream(resource.getInputStream()); + AudioInputStream stream = AudioSystem.getAudioInputStream(new BufferedInputStream(resource.getInputStream())); decoder = new PCMStreamConverter(stream, stream.getFormat(), outputNumSamplesPerChannel); mNumChannels = stream.getFormat().getChannels(); diff --git a/src/games/stendhal/client/sound/manager/SoundManager.java b/src/games/stendhal/client/sound/manager/SoundManager.java index 1561fcebb8..e46ac36c2a 100644 --- a/src/games/stendhal/client/sound/manager/SoundManager.java +++ b/src/games/stendhal/client/sound/manager/SoundManager.java @@ -7,7 +7,6 @@ package games.stendhal.client.sound.manager; import games.stendhal.client.sound.system.SignalProcessor; import games.stendhal.client.sound.system.SoundSystem; -import games.stendhal.client.sound.system.SoundSystemException; import games.stendhal.client.sound.system.Time; import games.stendhal.client.sound.system.processors.DirectedSound; import games.stendhal.client.sound.system.processors.Interruptor; @@ -17,6 +16,7 @@ import games.stendhal.common.math.Algebra; import games.stendhal.common.resource.Resource; import java.io.IOException; +import java.util.Iterator; import java.util.LinkedList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -34,7 +34,8 @@ public class SoundManager private final static Logger logger = Logger.getLogger(SoundManager.class); private final static int OUTPUT_NUM_SAMPLES = 256; - private final static int USE_NUM_MIXER_LINES = 15; + private final static int SOUND_CHANNEL_LIMIT = 50; + private final static int USE_NUM_MIXER_LINES = 0; private final static int DIMENSION = 2; private final static float[] HEARER_LOOKONG_DIRECTION = { 0.0f, 1.0f }; private final static AudioFormat AUDIO_FORMAT = new AudioFormat(44100, 16, 2, true, false); @@ -51,13 +52,12 @@ public class SoundManager { Sound sound = new Sound(); sound.file.set(file.get().clone()); - return sound; } public boolean isActive() { return channel.get() != null && channel.get().isActive(); } } - + private final class SoundChannel extends SignalProcessor { final float[] mSoundPosition = new float[DIMENSION]; @@ -67,9 +67,9 @@ public class SoundManager final Interruptor mInterruptor = new Interruptor(); final DirectedSound mDirectedSound = new DirectedSound(); final VolumeAdjustor mGlobalVolume = new VolumeAdjustor(); - SoundLayers.VolumeAdjustor mLayerVolume = null; - SoundSystem.Output mOutput = null; - Sound mSound = null; + final SoundLayers.VolumeAdjustor mLayerVolume; + final SoundSystem.Output mOutput; + Sound mSound = null; SoundChannel() { @@ -86,8 +86,9 @@ public class SoundManager void setLayer (int level) { mLayerVolume.setLayer(level); } void setAudibleArea(AudibleArea area) { mAudibleArea.set(area); } void resumePlayback() { mInterruptor.play(); } - - void playSound(Sound newSound, Time time) + void close () { mSoundSystem.closeOutput(mOutput); } + + void playSound(Sound newSound, float volume, Time time) { if(mSound != null) { @@ -104,7 +105,7 @@ public class SoundManager mInterruptor.play(); mGlobalVolume.setVolume(0.0f); - mGlobalVolume.startFading(1.0f, time); + mGlobalVolume.startFading(volume, time); newSound.channel.set(this); newSound.file.get().connectTo(mInterruptor, true); } @@ -115,6 +116,9 @@ public class SoundManager void stopPlayback(Time time) { + if(time == null) + time = ZERO_DURATION; + mAutoRepeat.set(false); mGlobalVolume.startFading(0.0f, time); mInterruptor.stop(time); @@ -137,7 +141,7 @@ public class SoundManager } else { - playSound(null, null); + playSound(null, 0, null); super.quit(); } } @@ -147,36 +151,29 @@ public class SoundManager private final float[] mHearerPosition = new float[DIMENSION]; private final SoundLayers mSoundLayers = new SoundLayers(); private SoundSystem mSoundSystem = null; + private boolean mMute = false; protected SoundManager() { Algebra.mov_Vecf(mHearerPosition, 0.0f); - try - { - mSoundSystem = new SoundSystem(AUDIO_FORMAT, new Time(70, Time.Unit.MILLI), USE_NUM_MIXER_LINES); - mSoundSystem.setDaemon(true); - mSoundSystem.start(); - } - catch(SoundSystemException exception) - { - mSoundSystem = null; - // TODO: write error message into logger - } - } - - public boolean isSoundSystemRunnig() - { - return mSoundSystem != null; + mSoundSystem = new SoundSystem(AUDIO_FORMAT, new Time(15, Time.Unit.MILLI), USE_NUM_MIXER_LINES); + mSoundSystem.setDaemon(true); + mSoundSystem.start(); } public Sound openSound(Resource resource, SoundFile.Type fileType) + { + return openSound(resource, fileType, OUTPUT_NUM_SAMPLES, true); + } + + public Sound openSound(Resource resource, SoundFile.Type fileType, int numSamplesPerChunk, boolean enableStreaming) { Sound sound = null; try { - SoundFile file = new SoundFile(resource, fileType, OUTPUT_NUM_SAMPLES, true); + SoundFile file = new SoundFile(resource, fileType, numSamplesPerChunk, enableStreaming); sound = new Sound(); sound.file.set(file); @@ -206,7 +203,7 @@ public class SoundManager public void play(Sound sound, float volume, int layerLevel, AudibleArea area, boolean autoRepeat, Time fadeInDuration) { - if(sound == null) + if(sound == null || mMute) return; if(sound.isActive()) @@ -222,13 +219,14 @@ public class SoundManager } else { - SoundChannel channel = findInactiveChannel(); + SoundChannel channel = getInactiveChannel(); channel.setAutoRepeat(autoRepeat); - channel.setVolume(volume); channel.setLayer(layerLevel); channel.setAudibleArea(area); - channel.playSound(sound, fadeInDuration); + channel.playSound(sound, volume, fadeInDuration); channel.update(); + + closeInactiveChannels(SOUND_CHANNEL_LIMIT); } } @@ -255,22 +253,49 @@ public class SoundManager if(sound != null && sound.isActive()) sound.channel.get().setAudibleArea(area); } + + public void mute(boolean turnMuteOn, Time turnOffDuration) + { + if(turnMuteOn && !mMute) + { + for(SoundChannel channel: mChannels) + channel.stopPlayback(turnOffDuration); + } + + mMute = turnMuteOn; + } public void close() { - if(isSoundSystemRunnig()) - { - mSoundSystem.close(); + mSoundSystem.close(); - try - { - mSoundSystem.join(); - } - catch(InterruptedException exception) { } - } + try + { + mSoundSystem.join(); + } + catch(InterruptedException exception) { } } - private SoundChannel findInactiveChannel() + private void closeInactiveChannels(int leaveNumChannelsOpen) + { + Iterator iChannel = mChannels.iterator(); + + while(iChannel.hasNext()) + { + if(mChannels.size() <= leaveNumChannelsOpen) + break; + + SoundChannel currChannel = iChannel.next(); + + if(!currChannel.isActive()) + { + currChannel.close(); + iChannel.remove(); + } + } + } + + private SoundChannel getInactiveChannel() { SoundChannel foundChannel = null; @@ -285,8 +310,8 @@ public class SoundManager if(foundChannel == null) { - mChannels.add(new SoundChannel()); - foundChannel = mChannels.getLast(); + foundChannel = new SoundChannel(); + mChannels.add(foundChannel); } return foundChannel; diff --git a/src/games/stendhal/client/sound/system/SoundSystem.java b/src/games/stendhal/client/sound/system/SoundSystem.java index 99d6249f27..92c060b5a7 100644 --- a/src/games/stendhal/client/sound/system/SoundSystem.java +++ b/src/games/stendhal/client/sound/system/SoundSystem.java @@ -5,7 +5,7 @@ package games.stendhal.client.sound.system; -import java.util.ArrayList; +import games.stendhal.common.memory.Field; import java.util.Arrays; import java.util.Comparator; import java.util.Iterator; @@ -21,145 +21,263 @@ import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.Mixer; import javax.sound.sampled.SourceDataLine; -import org.apache.log4j.Logger; - /** * * @author silvio */ public class SoundSystem extends Thread { - public final static class Output extends SignalProcessor - { - private SourceDataLine mLine = null; // the line we will write the PCM data to - private AudioFormat mAudioFormat = null; // the audio format the line was opened with - private float[] mUniformPCM = null; // the interleaved uniform PCM data. every samples value ranges form -1.0 to 1.0 - private byte[] mPCM = null; // the uniform PCM data converted to the format defined in "mAudioFormat" - private int mNumBytesWritten = 0; // number of bytes of "mPCM" we have written to "mLine" - private int mNumSamplesMixed = 0; // number of samples we have mixed into the line of "mMixedOutput" - private int mNumChannels = 0; - private int mNumSamples = 0; - private int mSampleRate = 0; - private boolean mPCMWasConverted = false; + public static abstract class Output extends SignalProcessor { } - private int mRemainingBytesToWritePerCycle = 0; + private static class DummyOutput extends Output { } - private int getRemainingBytesToWrite() { return mPCM.length - mNumBytesWritten; } - private int getRemainingSamplesToMix() { return mNumSamples - mNumSamplesMixed; } - private boolean receivedData () { return mUniformPCM != null; } - private boolean wasPCMConverted () { return mPCMWasConverted; } - private boolean isLineUsable () { return mLine != null; } - private boolean wasAllDataWritten () { return mNumBytesWritten >= mPCM.length; } - private boolean whereAllSamplesMixed () { return mNumSamplesMixed >= mNumSamples; } + private static class SystemOutput extends Output + { + final SourceDataLine mLine; // the line we will write the PCM data to + float[] mAudioBuffer = null; // the interleaved uniform PCM data + int mNumSamples = 0; // + byte[] mPCMBuffer = null; // the uniform PCM data converted to the format defined in "mAudioFormat" + int mPCMBufferSize = 0; // + int mNumBytesWritten = 0; // number of bytes from "mPCMBuffer" we have written to "mLine" + int mNumBytesToWrite = 0; - private int writeToLine(int numBytes) + SystemOutput(SourceDataLine line) + { + assert line != null; + assert line.isOpen(); + mLine = line; + mLine.start(); + } + + boolean isOpen () { return mLine.isOpen(); } + boolean receivedData () { return mNumSamples > 0; } + boolean isConverted () { return mPCMBufferSize > 0; } + AudioFormat getAudioFormat () { return mLine.getFormat(); } + float[] getBuffer () { return mAudioBuffer; } + int getNumSamples () { return mNumSamples; } + int getNumChannels () { return mLine.getFormat().getChannels(); } + int getSampleRate () { return (int)mLine.getFormat().getSampleRate(); } + int getNumBytesPerSample() { return mLine.getFormat().getSampleSizeInBits() / 8; } + int available () { return mLine.available(); } + int getNumBytesToWrite () { return mNumBytesToWrite; } + + void close() + { + mLine.close(); + mAudioBuffer = null; + mPCMBuffer = null; + reset(); + } + + void reset() + { + mNumBytesWritten = 0; + mNumSamples = 0; + mPCMBufferSize = 0; + } + + void setBuffer(float[] buffer, int numSamples) + { + assert numSamples <= buffer.length; + assert (numSamples % getNumChannels()) == 0; + + mAudioBuffer = buffer; + mNumSamples = numSamples; + } + + void setNumBytesToWrite(int numBytesToWrite) + { + int frameSize = getNumBytesPerSample() * getNumChannels(); + + numBytesToWrite /= frameSize; + numBytesToWrite *= frameSize; + mNumBytesToWrite = numBytesToWrite; + } + + void convert() { - assert mAudioFormat.getChannels() == mNumChannels; - assert (int)mAudioFormat.getSampleRate() == mSampleRate; + assert (mLine.getFormat().getSampleSizeInBits() % 8) == 0; - int written = mLine.write(mPCM, mNumBytesWritten, numBytes); - mNumBytesWritten += written; - return written; + int numBytesPerSample = getNumBytesPerSample(); + int numBytes = numBytesPerSample * mNumSamples; + + mPCMBuffer = Field.expand(mPCMBuffer, numBytes, false); + mPCMBuffer = SoundSystem.convertUniformPCM(mPCMBuffer, mAudioBuffer, mNumSamples, numBytesPerSample); + mPCMBufferSize = numBytes; } - private int mixToOutput(Output output, int offsetInSamples, int numSamplesToMix) + boolean write(int numBytes) { - assert output.mAudioFormat.getChannels() == mNumChannels; - assert (int)output.mAudioFormat.getSampleRate() == mSampleRate; + int frameSize = getNumBytesPerSample() * getNumChannels(); + int numRemainingBytesInBuffer = mPCMBufferSize - mNumBytesWritten; - SoundSystem.mixUniformPCM(output.mUniformPCM, offsetInSamples*mNumChannels, mUniformPCM, mNumSamplesMixed*mNumChannels, numSamplesToMix*mNumChannels); - mNumSamplesMixed += numSamplesToMix; - return numSamplesToMix; + numBytes = Math.min(numBytes, numRemainingBytesInBuffer); + numBytes = Math.min(numBytes, mNumBytesToWrite ); + numBytes = Math.min(numBytes, mLine.available() ); + numBytes /= frameSize; + numBytes *= frameSize; + + numBytes = mLine.write(mPCMBuffer, mNumBytesWritten, numBytes); + + mNumBytesWritten += numBytes; + mNumBytesToWrite -= numBytes; + numRemainingBytesInBuffer -= numBytes; + + if(numRemainingBytesInBuffer < frameSize) + reset(); + + if(mNumBytesToWrite < frameSize) + return false; + + return true; } - private void convertPCM() + @Override + protected void modify(float[] buffer, int frames, int channels, int rate) { - assert (mAudioFormat.getSampleSizeInBits() % 8) == 0; - - int numBytesPerSample = mAudioFormat.getSampleSizeInBits() / 8; - mPCM = SoundSystem.convertUniformPCM(mPCM, mUniformPCM, mNumSamples * mNumChannels, numBytesPerSample); - mPCMWasConverted = true; - } - - private void clearData() - { - mNumBytesWritten = 0; - mNumSamplesMixed = 0; - mUniformPCM = null; - mPCMWasConverted = false; - } - - @Override - protected void modify(float[] buffer, int samples, int channels, int rate) - { - if(buffer != null && samples > 0 && channels > 0 && rate > 0) + if(buffer != null && frames > 0 && channels > 0 && rate > 0) { - assert samples <= buffer.length; + assert frames <= buffer.length; + buffer = SoundSystem.convertChannels(buffer, frames, channels, getNumChannels()); - mUniformPCM = buffer; - mNumChannels = channels; - mNumSamples = samples; - mSampleRate = rate; - - if(!SoundSystem.convertChannels(this)) + if(buffer != null) { - assert false: "could not convert channels"; - - mUniformPCM = null; - mNumChannels = 0; - mNumSamples = 0; - mSampleRate = 0; + setBuffer(buffer, (frames * getNumChannels())); } + else assert false: "could not convert channels"; - if(!SoundSystem.convertSampleRate(this)) - { - assert false: "could not convert sample rate"; + buffer = SoundSystem.convertSampleRate(buffer, (frames * channels), channels, rate, getSampleRate()); - mUniformPCM = null; - mNumChannels = 0; - mNumSamples = 0; - mSampleRate = 0; - } + if(buffer != null) + { + float ratio = (float)frames / (float)rate; + setBuffer(buffer, (int)(ratio * getSampleRate() * channels)); + } + else assert false: "could not convert sample rate"; } } - } + } - private final static Logger logger = Logger.getLogger(SoundSystem.class); - private final ArrayList mOutputs = new ArrayList(); - private final Output mMixOutput = new Output(); - private Mixer mMixer = null; - private Time mBufferDuration = null; - private final AtomicBoolean mSystemIsRunning = new AtomicBoolean(false); - private final AtomicBoolean mUseDynamicLoadScaling = new AtomicBoolean(false); - private final int mMaxNumLines; + private static class MixerOutput extends Output + { + AudioFormat mAudioFormat; + float[] mAudioBuffer = null; // the interleaved uniform PCM data + int mNumSamples = 0; // + int mNumSamplesMixed = 0; + + MixerOutput(AudioFormat format) + { + assert format != null; + mAudioFormat = format; + } + + boolean receivedData () { return mNumSamples > 0; } + int getNumChannels() { return mAudioFormat.getChannels(); } + int getSampleRate () { return (int)mAudioFormat.getSampleRate(); } + + void reset() + { + mNumSamples = 0; + mNumSamplesMixed = 0; + } + + void setBuffer(float[] buffer, int numSamples) + { + assert numSamples <= buffer.length; + assert (numSamples % getNumChannels()) == 0; + + mAudioBuffer = buffer; + mNumSamples = numSamples; + } + + boolean mix(float[] buffer, int size) + { + int offset = 0; + int numSamplesToMix = size; + + while(numSamplesToMix > 0) + { + if(!receivedData()) + request(); + + if(!receivedData()) + return false; + + int numSamples = mNumSamples - mNumSamplesMixed; + numSamples = Math.min(numSamples, numSamplesToMix); + + SoundSystem.mixUniformPCM(buffer, offset, mAudioBuffer, mNumSamplesMixed, numSamples); + + offset += numSamples; + mNumSamplesMixed += numSamples; + numSamplesToMix -= numSamples; + + if(mNumSamples == mNumSamplesMixed) + reset(); + } + + return true; + } + + @Override + protected void modify(float[] buffer, int frames, int channels, int rate) + { + if(buffer != null && frames > 0 && channels > 0 && rate > 0) + { + assert frames <= buffer.length; + buffer = SoundSystem.convertChannels(buffer, frames, channels, getNumChannels()); + + if(buffer != null) + { + setBuffer(buffer, (frames * getNumChannels())); + } + else assert false: "could not convert channels"; + + buffer = SoundSystem.convertSampleRate(buffer, (frames * channels), channels, rate, getSampleRate()); + + if(buffer != null) + { + float ratio = (float)frames / (float)rate; + setBuffer(buffer, (int)(ratio * getSampleRate() * channels)); + } + else assert false: "could not convert sample rate"; + } + } + } + + private final LinkedList mSystemOutputs = new LinkedList(); + private final LinkedList mMixerOutputs = new LinkedList(); + private SystemOutput mMixSystemOutput = null; + private Mixer mSystemMixer = null; + private Time mBufferDuration = null; + private final AtomicBoolean mSystemIsRunning = new AtomicBoolean(false); + private final AtomicBoolean mUseDynamicLoadScaling = new AtomicBoolean(false); + float[] mMixBuffer = null; + private final int mMaxNumLines; - public SoundSystem(AudioFormat audioFormat, Time bufferDuration, int useMaxMixerLines) throws SoundSystemException + public SoundSystem(AudioFormat audioFormat, Time bufferDuration, int useMaxMixerLines) { assert audioFormat != null; assert bufferDuration != null; - mMixer = tryToFindMixer(audioFormat); + mSystemMixer = tryToFindMixer(audioFormat); mBufferDuration = bufferDuration; mMaxNumLines = useMaxMixerLines; - if(mMixer == null) + if(mSystemMixer == null) { DataLine.Info datalineInfo = new DataLine.Info(SourceDataLine.class, audioFormat, AudioSystem.NOT_SPECIFIED); try { - mMixOutput.mLine = (SourceDataLine)AudioSystem.getLine(datalineInfo); - - if(!AudioSystem.isLineSupported(datalineInfo)) - throw new SoundSystemException("line is not supported - " + audioFormat.toString()); - - mMixOutput.mAudioFormat = audioFormat; - mMixOutput.mLine.open(); + SourceDataLine line = (SourceDataLine)AudioSystem.getLine(datalineInfo); + line.open(); + + mMixSystemOutput = new SystemOutput(line); } catch(LineUnavailableException exception) { - mMixOutput.mLine.close(); - throw new SoundSystemException("line is unavailable - " + exception.toString()); + // TODO: logging } } else @@ -168,16 +286,15 @@ public class SoundSystem extends Thread try { - mMixOutput.mLine = (SourceDataLine)mMixer.getLine(info); - mMixOutput.mAudioFormat = audioFormat; - mMixOutput.mLine.open(); + SourceDataLine line = (SourceDataLine)mSystemMixer.getLine(info); + line.open(); + + mMixSystemOutput = new SystemOutput(line); } catch(LineUnavailableException e) - { - mMixOutput.mLine.close(); - mMixOutput.mLine = null; - mMixOutput.mAudioFormat = null; - } + { + // TODO: logging + } } } @@ -187,7 +304,7 @@ public class SoundSystem extends Thread assert mixer != null; assert bufferDuration != null; - mMixer = mixer; + mSystemMixer = mixer; mBufferDuration = bufferDuration; mMaxNumLines = useMaxMixerLines; @@ -195,23 +312,25 @@ public class SoundSystem extends Thread try { - mMixOutput.mLine = (SourceDataLine)mMixer.getLine(info); - mMixOutput.mAudioFormat = audioFormat; - mMixOutput.mLine.open(); + SourceDataLine line = (SourceDataLine)mSystemMixer.getLine(info); + line.open(); + + mMixSystemOutput = new SystemOutput(line); } catch(LineUnavailableException e) { - mMixOutput.mLine.close(); - mMixOutput.mLine = null; - mMixOutput.mAudioFormat = null; + // TODO: logging } } - public SoundSystem(SourceDataLine outputLine, Time bufferDuration) throws SoundSystemException + public SoundSystem(SourceDataLine outputLine, Time bufferDuration) { assert outputLine != null; assert bufferDuration != null; + mMaxNumLines = 0; + mBufferDuration = bufferDuration; + if(!outputLine.isOpen()) { try @@ -220,93 +339,77 @@ public class SoundSystem extends Thread } catch(LineUnavailableException e) { - throw new SoundSystemException(e.toString()); + // TODO: logging + return; } } - - mMaxNumLines = 0; - mMixOutput.mLine = outputLine; - mMixOutput.mAudioFormat = outputLine.getFormat(); - mMixOutput.mNumChannels = mMixOutput.mAudioFormat.getChannels(); - mMixOutput.mSampleRate = (int)mMixOutput.mAudioFormat.getSampleRate(); - mBufferDuration = bufferDuration; + + mMixSystemOutput = new SystemOutput(outputLine); } - public Output openOutput(AudioFormat audioFormat) + public Output openOutput(AudioFormat audioFormat) { - Output output = new Output(); - DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat, AudioSystem.NOT_SPECIFIED); - boolean lineUnavailable = false; - - if(mMixer != null && mMixer.isLineSupported(info) && mOutputs.size() < mMaxNumLines) + DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat, AudioSystem.NOT_SPECIFIED); + + if(mSystemMixer != null && mSystemMixer.isLineSupported(info) && mSystemOutputs.size() < mMaxNumLines) { try { - output.mLine = (SourceDataLine)mMixer.getLine(info); - output.mAudioFormat = audioFormat; - output.mLine.open(); + SourceDataLine line = (SourceDataLine)mSystemMixer.getLine(info); + line.open(); + + SystemOutput output = new SystemOutput(line); + + synchronized(mSystemOutputs) + { + mSystemOutputs.add(output); + } + + return output; } - catch(LineUnavailableException e) - { - output.mLine.close(); - output.mLine = null; - output.mAudioFormat = null; - lineUnavailable = true; - } - } - else - { - lineUnavailable = true; + catch(LineUnavailableException e) { } } - if(lineUnavailable && mMixOutput.isLineUsable()) - output.mAudioFormat = mMixOutput.mAudioFormat; + if(mMixSystemOutput != null) + { + MixerOutput output = new MixerOutput(mMixSystemOutput.getAudioFormat()); - synchronized(this) - { - mOutputs.add(output); - } - - return output; - } + synchronized(mMixerOutputs) + { + mMixerOutputs.add(output); + } + + return output; + } + + return new DummyOutput(); + } public synchronized void closeOutput(Output output) { - if(output.isLineUsable()) - { - output.mLine.close(); - output.mLine = null; - } + output.disconnect(); - output.clearData(); - output.disconnect(); + if(output instanceof SystemOutput) + { + SystemOutput systemOutput = (SystemOutput)output; + systemOutput.close(); + mSystemOutputs.remove(systemOutput); + } - mOutputs.remove(output); + if(output instanceof MixerOutput) + { + MixerOutput mixerOutput = (MixerOutput)output; + mMixerOutputs.remove(mixerOutput); + } } - public synchronized void closeAllOutputs() + public void closeAllOutputs() { - for(Output output: mOutputs) - { - if(output.isLineUsable()) - { - output.mLine.close(); - output.mLine = null; - } + for(SystemOutput output: mSystemOutputs) + closeOutput(output); - output.clearData(); - output.disconnect(); - } - - mOutputs.clear(); - - if(mMixOutput.isLineUsable()) - { - mMixOutput.mLine.stop(); - mMixOutput.mLine.close(); - mMixOutput.mLine = null; - mMixOutput.clearData(); - } + for(MixerOutput output: mMixerOutputs) + closeOutput(output); } public void close() @@ -320,21 +423,14 @@ public class SoundSystem extends Thread mSystemIsRunning.set(true); double averageTimeToProcessSound = mBufferDuration.getInNanoSeconds(); - double multiplicator = 0.995; + double multiplicator = 0.900; while(mSystemIsRunning.get()) { long duration = System.nanoTime(); - try - { - processOutputs(); - } - catch(RuntimeException e) - { - logger.warn(e, e); - } - + processOutputs(); + duration = System.nanoTime() - duration; averageTimeToProcessSound = (averageTimeToProcessSound + duration) / 2.0; @@ -349,135 +445,82 @@ public class SoundSystem extends Thread } closeAllOutputs(); + closeOutput(mMixSystemOutput); } - private int min(int a, int b, int c) - { - return Math.min(a, Math.min(b,c)); - } - - private void prepareManualMixing() - { - int numBytesPerSample = mMixOutput.mAudioFormat.getSampleSizeInBits() / 8; - int numChannels = mMixOutput.mAudioFormat.getChannels(); - int sampleRate = (int)mMixOutput.mAudioFormat.getSampleRate(); - int numSamples = (int)mBufferDuration.getInSamples(sampleRate); + @SuppressWarnings("unchecked") + private void processOutputs() + { + LinkedList sysOutputs; + LinkedList mixOutputs; - if(mMixOutput.mUniformPCM == null || mMixOutput.mUniformPCM.length < (numSamples * numChannels)) - mMixOutput.mUniformPCM = new float[numSamples * numChannels]; + synchronized(mSystemOutputs) + { + sysOutputs = (LinkedList)mSystemOutputs.clone(); + } - mMixOutput.mNumSamples = numSamples; - mMixOutput.mRemainingBytesToWritePerCycle = numSamples * numChannels * numBytesPerSample; - Arrays.fill(mMixOutput.mUniformPCM, 0, numSamples, 0.0f); - } - - private void processOutputs() - { - LinkedList outputsWithUsableLines = new LinkedList(); + synchronized(mMixerOutputs) + { + mixOutputs = (LinkedList)mMixerOutputs.clone(); + } - if(mMixOutput.isLineUsable()) - { - prepareManualMixing(); - outputsWithUsableLines.add(mMixOutput); - } + if(mMixSystemOutput != null) + sysOutputs.add(mMixSystemOutput); - synchronized(this) - { - for(Output output: mOutputs) - { - /* happens for example if the audio device is in use by an other applicatin */ - if(output.mAudioFormat == null) { - continue; - }//*/ + for(SystemOutput output: sysOutputs) + { + int sampleRate = output.getSampleRate(); + int numBytesPerSample = output.getAudioFormat().getSampleSizeInBits() / 8; + int numChannels = output.getNumChannels(); + int numBytesToWrite = (int)(mBufferDuration.getInSamples(sampleRate) * numChannels * numBytesPerSample); - int numBytesPerSample = output.mAudioFormat.getSampleSizeInBits() / 8; - int numChannels = output.mAudioFormat.getChannels(); - int sampleRate = (int)output.mAudioFormat.getSampleRate(); + output.setNumBytesToWrite(numBytesToWrite); + } - if(output.isLineUsable()) - { - output.mRemainingBytesToWritePerCycle = - (int)mBufferDuration.getInSamples(sampleRate) * numChannels * numBytesPerSample; + if(mMixSystemOutput != null) + { + int numSamples = mMixSystemOutput.getNumBytesToWrite() / mMixSystemOutput.getNumBytesPerSample(); + mMixBuffer = Field.expand(mMixBuffer, numSamples, false); + Arrays.fill(mMixBuffer, 0, numSamples, 0.0f); - outputsWithUsableLines.add(output); - } - else if(mMixOutput.isLineUsable()) - { - int remainingSamplesToMix = mMixOutput.mNumSamples; - int numSmplesMixed = 0; + for(MixerOutput output: mixOutputs) + output.mix(mMixBuffer, numSamples); - while(remainingSamplesToMix > 0) - { - if(!output.receivedData()) - output.request(); // if we got no sound data we request it + mMixSystemOutput.setBuffer(mMixBuffer, numSamples); + } + + while(!sysOutputs.isEmpty()) + { + boolean buffersAreFull = true; - if(output.receivedData()) - { - int numSamplesToMix = Math.min(output.getRemainingSamplesToMix(), remainingSamplesToMix); - int count = output.mixToOutput(mMixOutput, numSmplesMixed, numSamplesToMix); + for(Iterator iOutput = sysOutputs.iterator(); iOutput.hasNext(); ) + { + SystemOutput output = iOutput.next(); - remainingSamplesToMix -= count; - numSmplesMixed += count; + if(output.isOpen()) + { + if(!output.receivedData()) + output.request(); // if we got no sound data we request it - if(output.whereAllSamplesMixed()) - output.clearData(); - } - else break; - } - } - } - } + if(output.receivedData()) + { + if(!output.isConverted()) + output.convert(); - while(!outputsWithUsableLines.isEmpty()) - { - boolean lineBuffersAreFull = true; + buffersAreFull = buffersAreFull && (output.available() == 0); - for(Iterator iOutput = outputsWithUsableLines.iterator(); iOutput.hasNext(); ) - { - Output output = iOutput.next(); + if(output.write(256)) + continue; + } + } - if(!output.receivedData()) - output.request(); // if we got no sound data we request it + iOutput.remove(); + } - if(output.receivedData()) - { - if(!output.mLine.isRunning()) - output.mLine.start(); - - if(!output.wasPCMConverted()) - output.convertPCM(); - - assert output.getRemainingBytesToWrite() != 0; - assert output.mRemainingBytesToWritePerCycle != 0; - - lineBuffersAreFull = lineBuffersAreFull && (output.mLine.available() == 0); - - int numBytesWritable = - min(output.mLine.available(), output.getRemainingBytesToWrite(), output.mRemainingBytesToWritePerCycle); - - output.mRemainingBytesToWritePerCycle -= output.writeToLine(numBytesWritable); - - if(output.wasAllDataWritten()) - output.clearData(); - - if(output.mRemainingBytesToWritePerCycle <= 0) - iOutput.remove(); - } - else - { - // if after we requested data we still don't have any, we quit processing of this output - iOutput.remove(); - break; - } - } - - if(lineBuffersAreFull) - { - if(!mUseDynamicLoadScaling.get()) - suspendThread(50); - } - } - } + if(buffersAreFull && !mUseDynamicLoadScaling.get()) + suspendThread(50); + } + } @Override public String toString() @@ -568,11 +611,9 @@ public class SoundSystem extends Thread private static byte[] convertUniformPCM(byte[] pcmBuffer, float[] uniformSamples, int numUniformSamples, int numBytesPerSample) { int numBitsPerSample = numBytesPerSample * 8; + long maxValue = (long)((Math.pow(2, numBitsPerSample) - 1.0) / 2.0); - if(pcmBuffer == null || pcmBuffer.length < (numBytesPerSample * numUniformSamples)) - pcmBuffer = new byte[numBytesPerSample * numUniformSamples]; - - long maxValue = (long)((Math.pow(2, numBitsPerSample) - 1.0) / 2.0); + pcmBuffer = Field.expand(pcmBuffer, (numBytesPerSample * numUniformSamples), false); for(int i=0; i numRequiredChannels) + if(numChannels > numRequiredChannels) { // stereo/multichannel to mono - maybe this won't work properly for more than 2 channels // - ## NEEDS CONFIRMATION ## if(numRequiredChannels == 1) { - for(int i=0; i= mNumSamplesBuffered; } + public synchronized int getNumChannels () { return mNumChannels; } + public synchronized int getSampleRate () { return mSampleRate; } + public synchronized int getNumSamples () { return mNumSamplesBuffered / mNumChannels; } + + @Override + protected synchronized boolean generate() + { + if(reachedEndOfStream()) + { + super.quit(); + return false; + } + + int outputBufferSize = mOutputBuffer.length; + int numSamplesAvailable = mNumSamplesBuffered - mNumSamplesRead; + int numSamples = Math.min(outputBufferSize, numSamplesAvailable); + + System.arraycopy(mData, mNumSamplesRead, mOutputBuffer, 0, numSamples); + mNumSamplesRead += numSamples; + + super.propagate(mOutputBuffer, (numSamples / mNumChannels), mNumChannels, mSampleRate); + return true; + } + } + private float[] mData = null; - private float[] mOutputBuffer = null; private int mNumChannels = 1; private int mSampleRate = 0; private int mNumSamplesBuffered = 0; - private int mNumSamplesRead = 0; - private int mOutputNumSamples; - public Recorder(int outputNumSamplesPerChannel) - { - mOutputNumSamples = outputNumSamplesPerChannel; - } + public Player createPlayer(int outputNumSamplesPerChannel) + { + return new Player(outputNumSamplesPerChannel); + } public synchronized void clear() { mNumSamplesBuffered = 0; - mNumSamplesRead = 0; mData = null; - mOutputBuffer = null; } - public synchronized void restart () { mNumSamplesRead = 0; } - public synchronized boolean reachedEndOfStream() { return mNumSamplesRead >= mNumSamplesBuffered; } - public synchronized int getNumChannels () { return mNumChannels; } - public synchronized int getSampleRate () { return mSampleRate; } - public synchronized int getNumSamples () { return mNumSamplesBuffered / mNumChannels; } - + public synchronized int getNumChannels() { return mNumChannels; } + public synchronized int getSampleRate () { return mSampleRate; } + public synchronized int getNumSamples () { return mNumSamplesBuffered / mNumChannels; } public synchronized void trim() { @@ -78,38 +108,11 @@ public class Recorder extends SignalProcessor // if the buffer is to small to hold the whole data, we expand it if(remainingBufferSpace < requiredBufferSpace) - { - float[] newData = new float[(mNumSamplesBuffered + requiredBufferSpace) * 2]; - System.arraycopy(mData, 0, newData, 0, mNumSamplesBuffered); - mData = newData; - } + mData = Field.expand(mData, (mNumSamplesBuffered + requiredBufferSpace) * 2, true); System.arraycopy(data, 0, mData, mNumSamplesBuffered, requiredBufferSpace); mNumSamplesBuffered += requiredBufferSpace; super.propagate(data, samples, channels, rate); } - - @Override - protected boolean generate() - { - if(reachedEndOfStream()) - { - super.quit(); - return false; - } - - int numSamplesToRead = mOutputNumSamples * mNumChannels; - int numSamplesAvailable = mNumSamplesBuffered - mNumSamplesRead; - int numSamples = Math.min(numSamplesToRead, numSamplesAvailable); - - if(mOutputBuffer == null) - mOutputBuffer = new float[numSamplesToRead]; - - System.arraycopy(mData, mNumSamplesRead, mOutputBuffer, 0, numSamples); - mNumSamplesRead += numSamples; - - super.propagate(mOutputBuffer, (numSamples / mNumChannels), mNumChannels, mSampleRate); - return true; - } } diff --git a/src/games/stendhal/common/memory/Field.java b/src/games/stendhal/common/memory/Field.java new file mode 100644 index 0000000000..a8206dbb2c --- /dev/null +++ b/src/games/stendhal/common/memory/Field.java @@ -0,0 +1,94 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package games.stendhal.common.memory; + +/** + * + * @author silvio + */ +public class Field +{ + /** + * This method will return a new allocated array of size newSize if newSize + * is greater than array.length. + * Tt will return the same array otherwise + * Only if keepData is set to true, the data of the array will be copied to the + * new allocated array + * + * @param array + * @param newSize + * @param keepData + * @return - new or old array + */ + public static byte[] expand(byte[] array, int newSize, boolean keepData) + { + if(array == null || array.length < newSize) + { + byte[] newArray = new byte[newSize]; + + if(keepData && array != null) + System.arraycopy(array, 0, newArray, 0, array.length); + + return newArray; + } + + return array; + } + + /** + * This method will return a new allocated array of size newSize if newSize + * is greater than array.length. + * Tt will return the same array otherwise + * Only if keepData is set to true, the data of the array will be copied to the + * new allocated array + * + * @param array + * @param newSize + * @param keepData + * @return - new or old array + */ + public static int[] expand(int[] array, int newSize, boolean keepData) + { + if(array == null || array.length < newSize) + { + int[] newArray = new int[newSize]; + + if(keepData && array != null) + System.arraycopy(array, 0, newArray, 0, array.length); + + return newArray; + } + + return array; + } + + /** + * This method will return a new allocated array of size newSize if newSize + * is greater than array.length. + * Tt will return the same array otherwise + * Only if keepData is set to true, the data of the array will be copied to the + * new allocated array + * + * @param array + * @param newSize + * @param keepData + * @return - new or old array + */ + public static float[] expand(float[] array, int newSize, boolean keepData) + { + if(array == null || array.length < newSize) + { + float[] newArray = new float[newSize]; + + if(keepData && array != null) + System.arraycopy(array, 0, newArray, 0, array.length); + + return newArray; + } + + return array; + } +} From b8b9e40ef4f1f3caeee6e19db7a0ea4fe3c9e29d Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Fri, 19 Feb 2010 19:14:50 +0000 Subject: [PATCH 20/44] backported sound system changes by plassy --- .../stendhal/client/entity/AudibleEntity.java | 2 +- .../client/entity/LoopedSoundSource.java | 41 +++--- .../client/sound/SoundSystemFacade.java | 8 +- .../client/sound/manager/SoundManager.java | 51 +++++-- .../client/sound/system/SoundSystem.java | 136 ++++++++++++------ 5 files changed, 153 insertions(+), 85 deletions(-) diff --git a/src/games/stendhal/client/entity/AudibleEntity.java b/src/games/stendhal/client/entity/AudibleEntity.java index 0d035da4c2..9c11340326 100644 --- a/src/games/stendhal/client/entity/AudibleEntity.java +++ b/src/games/stendhal/client/entity/AudibleEntity.java @@ -20,7 +20,7 @@ import java.util.HashMap; */ public abstract class AudibleEntity extends RPEntity { - private AudibleCircleArea mAudibleArea = new AudibleCircleArea(Algebra.vecf(0, 0), 3, 20); + private AudibleCircleArea mAudibleArea = new AudibleCircleArea(Algebra.vecf(0, 0), 1.5f, 23); private HashMap> mSoundGroups = new HashMap>(); private long mWaitTime = 0; diff --git a/src/games/stendhal/client/entity/LoopedSoundSource.java b/src/games/stendhal/client/entity/LoopedSoundSource.java index fc161f9901..4c3b4a8e6b 100644 --- a/src/games/stendhal/client/entity/LoopedSoundSource.java +++ b/src/games/stendhal/client/entity/LoopedSoundSource.java @@ -7,20 +7,19 @@ * Created 21.01.2006 * Version * - This program is free software. You can use, redistribute and/or modify it under - the terms of the GNU General Public License as published by the Free Software - Foundation, version 2 of the License. +This program is free software. You can use, redistribute and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, version 2 of the License. - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 Temple - Place - Suite 330, Boston, MA 02111-1307, USA, or go to - http://www.gnu.org/copyleft/gpl.html. +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place - Suite 330, Boston, MA 02111-1307, USA, or go to +http://www.gnu.org/copyleft/gpl.html. */ - package games.stendhal.client.entity; import games.stendhal.client.sound.SoundSystemFacade; @@ -33,22 +32,22 @@ import games.stendhal.common.math.Algebra; import games.stendhal.common.math.Numeric; import marauroa.common.game.RPObject; - public class LoopedSoundSource extends InvisibleEntity { private Sound sound; private int radius; private int volume; private SoundLayer layer = SoundLayer.AMBIENT_SOUND; + private Time fadingDuration = new Time(); @Override public void onChangedAdded(RPObject object, RPObject changes) { // stop the current sound - SoundSystemFacade.get().stop(sound, new Time(3, Time.Unit.SEC)); + SoundSystemFacade.get().stop(sound, fadingDuration); // udpate super.onChangedAdded(object, changes); - + update(changes); play(); } @@ -74,6 +73,12 @@ public class LoopedSoundSource extends InvisibleEntity { if (idx < SoundLayer.values().length) { layer = SoundLayer.values()[idx]; } + + if (layer == SoundLayer.BACKGROUND_MUSIC) { + fadingDuration.set(3, Time.Unit.SEC); + } else { + fadingDuration.set(100, Time.Unit.MILLI); + } } if (object.has("sound") || object.has("layer")) { @@ -87,9 +92,9 @@ public class LoopedSoundSource extends InvisibleEntity { * plays the sound */ private void play() { - AudibleCircleArea area = new AudibleCircleArea(Algebra.vecf((float)x, (float)y), radius / 2.0f, radius); - float vol = Numeric.intToFloat(volume, 100.0f); - SoundSystemFacade.get().play(sound, vol, 0, area, true, new Time(3, Time.Unit.SEC)); + AudibleCircleArea area = new AudibleCircleArea(Algebra.vecf((float) x, (float) y), radius / 2.0f, radius); + float vol = Numeric.intToFloat(volume, 100.0f); + SoundSystemFacade.get().play(sound, vol, 0, area, true, fadingDuration); } /** @@ -101,6 +106,6 @@ public class LoopedSoundSource extends InvisibleEntity { @Override public void release() { super.release(); - SoundSystemFacade.get().stop(sound, new Time(3, Time.Unit.SEC)); + SoundSystemFacade.get().stop(sound, fadingDuration); } } diff --git a/src/games/stendhal/client/sound/SoundSystemFacade.java b/src/games/stendhal/client/sound/SoundSystemFacade.java index 7de29a4376..848a5b2bdd 100644 --- a/src/games/stendhal/client/sound/SoundSystemFacade.java +++ b/src/games/stendhal/client/sound/SoundSystemFacade.java @@ -27,7 +27,6 @@ import org.apache.log4j.Logger; */ public class SoundSystemFacade extends SoundManager implements WorldListener { private static final Logger logger = Logger.getLogger(SoundSystemFacade.class); - private static final SoundSystemFacade singletonInstance = new SoundSystemFacade(); private final HashMap sounds = new HashMap(); private final ResourceLocator resourceLocator = ResourceManager.get(); @@ -55,10 +54,6 @@ public class SoundSystemFacade extends SoundManager implements WorldListener { // ignored } - public void exit() { - // exits the sound system - } - public void stop(String soundName, Time fadeOutDuration) { super.stop(getSound(soundName), fadeOutDuration); } @@ -90,9 +85,8 @@ public class SoundSystemFacade extends SoundManager implements WorldListener { } public void play(final String soundName, final SoundLayer soundLayer, int volume) { - AudibleArea area = SoundManager.INFINITE_AUDIBLE_AREA; Sound sound = loadSound(soundName, "audio:/" + soundName + ".ogg", Type.OGG, false); - super.play(sound, Numeric.intToFloat(volume, 100.0f), 0, area, false, new Time()); + super.play(sound, Numeric.intToFloat(volume, 100.0f), 0, null, false, new Time()); } public void play(final String soundName, final double x, final double y, final SoundLayer soundLayer, int volume) { diff --git a/src/games/stendhal/client/sound/manager/SoundManager.java b/src/games/stendhal/client/sound/manager/SoundManager.java index e46ac36c2a..0e5830e545 100644 --- a/src/games/stendhal/client/sound/manager/SoundManager.java +++ b/src/games/stendhal/client/sound/manager/SoundManager.java @@ -31,15 +31,14 @@ import org.apache.log4j.Logger; */ public class SoundManager { - private final static Logger logger = Logger.getLogger(SoundManager.class); - + private final static Logger logger = Logger.getLogger(SoundManager.class); private final static int OUTPUT_NUM_SAMPLES = 256; private final static int SOUND_CHANNEL_LIMIT = 50; private final static int USE_NUM_MIXER_LINES = 0; private final static int DIMENSION = 2; private final static float[] HEARER_LOOKONG_DIRECTION = { 0.0f, 1.0f }; private final static AudioFormat AUDIO_FORMAT = new AudioFormat(44100, 16, 2, true, false); - public final static InfiniteAudibleArea INFINITE_AUDIBLE_AREA = new InfiniteAudibleArea(); + private final static InfiniteAudibleArea INFINITE_AUDIBLE_AREA = new InfiniteAudibleArea(); public final static Time ZERO_DURATION = new Time(); public final static class Sound implements Cloneable @@ -84,10 +83,17 @@ public class SoundManager void setVolume (float volume) { mGlobalVolume.setVolume(volume); } void startFading (float volume, Time duration) { mGlobalVolume.startFading(volume, duration); } void setLayer (int level) { mLayerVolume.setLayer(level); } - void setAudibleArea(AudibleArea area) { mAudibleArea.set(area); } void resumePlayback() { mInterruptor.play(); } void close () { mSoundSystem.closeOutput(mOutput); } - + + void setAudibleArea(AudibleArea area) + { + if(area == null) + area = INFINITE_AUDIBLE_AREA; + + mAudibleArea.set(area); + } + void playSound(Sound newSound, float volume, Time time) { if(mSound != null) @@ -150,8 +156,8 @@ public class SoundManager private final LinkedList mChannels = new LinkedList(); private final float[] mHearerPosition = new float[DIMENSION]; private final SoundLayers mSoundLayers = new SoundLayers(); - private SoundSystem mSoundSystem = null; private boolean mMute = false; + private SoundSystem mSoundSystem; protected SoundManager() { @@ -174,13 +180,12 @@ public class SoundManager try { SoundFile file = new SoundFile(resource, fileType, numSamplesPerChunk, enableStreaming); - sound = new Sound(); sound.file.set(file); } catch(IOException exception) { - assert false: exception; + logger.warn(exception); return null; } @@ -254,31 +259,40 @@ public class SoundManager sound.channel.get().setAudibleArea(area); } - public void mute(boolean turnMuteOn, Time turnOffDuration) + public void mute(boolean turnOffSound, Time turnOffDuration) { - if(turnMuteOn && !mMute) + if(turnOffSound && !mMute) { + logger.info("turning off audio"); + for(SoundChannel channel: mChannels) channel.stopPlayback(turnOffDuration); } + + if(!turnOffSound && mMute) + logger.info("turning on audio"); - mMute = turnMuteOn; + mMute = turnOffSound; } - public void close() + public void exit() { - mSoundSystem.close(); + mSoundSystem.exit(); try { mSoundSystem.join(); } - catch(InterruptedException exception) { } + catch(InterruptedException exception) + { + logger.warn("joining sound system thread was interrupted: " + exception); + } } private void closeInactiveChannels(int leaveNumChannelsOpen) { - Iterator iChannel = mChannels.iterator(); + int numChannels = mChannels.size(); + Iterator iChannel = mChannels.iterator(); while(iChannel.hasNext()) { @@ -293,6 +307,11 @@ public class SoundManager iChannel.remove(); } } + + numChannels -= mChannels.size(); + + if(numChannels > 0) + logger.debug("close " + numChannels + " inactive sound channels"); } private SoundChannel getInactiveChannel() @@ -312,6 +331,8 @@ public class SoundManager { foundChannel = new SoundChannel(); mChannels.add(foundChannel); + + logger.debug("open new sound channel (number " + mChannels.size() + ")"); } return foundChannel; diff --git a/src/games/stendhal/client/sound/system/SoundSystem.java b/src/games/stendhal/client/sound/system/SoundSystem.java index 92c060b5a7..17999db1bd 100644 --- a/src/games/stendhal/client/sound/system/SoundSystem.java +++ b/src/games/stendhal/client/sound/system/SoundSystem.java @@ -20,6 +20,7 @@ import javax.sound.sampled.Line; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.Mixer; import javax.sound.sampled.SourceDataLine; +import org.apache.log4j.Logger; /** * @@ -89,9 +90,9 @@ public class SoundSystem extends Thread { int frameSize = getNumBytesPerSample() * getNumChannels(); - numBytesToWrite /= frameSize; - numBytesToWrite *= frameSize; - mNumBytesToWrite = numBytesToWrite; + mNumBytesToWrite = numBytesToWrite; + mNumBytesToWrite /= frameSize; + mNumBytesToWrite *= frameSize; } void convert() @@ -116,8 +117,7 @@ public class SoundSystem extends Thread numBytes = Math.min(numBytes, mLine.available() ); numBytes /= frameSize; numBytes *= frameSize; - - numBytes = mLine.write(mPCMBuffer, mNumBytesWritten, numBytes); + numBytes = mLine.write(mPCMBuffer, mNumBytesWritten, numBytes); mNumBytesWritten += numBytes; mNumBytesToWrite -= numBytes; @@ -137,14 +137,18 @@ public class SoundSystem extends Thread { if(buffer != null && frames > 0 && channels > 0 && rate > 0) { - assert frames <= buffer.length; + assert (frames * channels) <= buffer.length; buffer = SoundSystem.convertChannels(buffer, frames, channels, getNumChannels()); if(buffer != null) { setBuffer(buffer, (frames * getNumChannels())); } - else assert false: "could not convert channels"; + else + { + setBuffer(null, 0); + //assert false: "could not convert channels"; + } buffer = SoundSystem.convertSampleRate(buffer, (frames * channels), channels, rate, getSampleRate()); @@ -153,7 +157,11 @@ public class SoundSystem extends Thread float ratio = (float)frames / (float)rate; setBuffer(buffer, (int)(ratio * getSampleRate() * channels)); } - else assert false: "could not convert sample rate"; + else + { + setBuffer(null, 0); + //assert false: "could not convert sample rate"; + } } } } @@ -224,14 +232,18 @@ public class SoundSystem extends Thread { if(buffer != null && frames > 0 && channels > 0 && rate > 0) { - assert frames <= buffer.length; + assert (frames * channels) <= buffer.length; buffer = SoundSystem.convertChannels(buffer, frames, channels, getNumChannels()); if(buffer != null) { setBuffer(buffer, (frames * getNumChannels())); } - else assert false: "could not convert channels"; + else + { + setBuffer(null, 0); + //assert false: "could not convert channels"; + } buffer = SoundSystem.convertSampleRate(buffer, (frames * channels), channels, rate, getSampleRate()); @@ -240,11 +252,16 @@ public class SoundSystem extends Thread float ratio = (float)frames / (float)rate; setBuffer(buffer, (int)(ratio * getSampleRate() * channels)); } - else assert false: "could not convert sample rate"; + else + { + setBuffer(null, 0); + //assert false: "could not convert sample rate"; + } } } } + private final static Logger logger = Logger.getLogger(SoundSystem.class); private final LinkedList mSystemOutputs = new LinkedList(); private final LinkedList mMixerOutputs = new LinkedList(); private SystemOutput mMixSystemOutput = null; @@ -257,8 +274,12 @@ public class SoundSystem extends Thread public SoundSystem(AudioFormat audioFormat, Time bufferDuration, int useMaxMixerLines) { - assert audioFormat != null; - assert bufferDuration != null; + if(audioFormat == null) + throw new IllegalArgumentException("audioFormat argument must not be null"); + if(bufferDuration == null) + throw new IllegalArgumentException("bufferDuration argument must not be null"); + + logger.info("opening sound system and trying to find optimal system mixer device / output line"); mSystemMixer = tryToFindMixer(audioFormat); mBufferDuration = bufferDuration; @@ -266,6 +287,8 @@ public class SoundSystem extends Thread if(mSystemMixer == null) { + logger.warn("cannot find a system mixer device. manual mixing will be the only option"); + DataLine.Info datalineInfo = new DataLine.Info(SourceDataLine.class, audioFormat, AudioSystem.NOT_SPECIFIED); try @@ -275,9 +298,9 @@ public class SoundSystem extends Thread mMixSystemOutput = new SystemOutput(line); } - catch(LineUnavailableException exception) + catch(LineUnavailableException e) { - // TODO: logging + logger.warn("cannot open output line for manual mixing of audio data: \"" + e + "\""); } } else @@ -293,16 +316,21 @@ public class SoundSystem extends Thread } catch(LineUnavailableException e) { - // TODO: logging + logger.warn("cannot open output line for manual mixing of audio data: \"" + e + "\""); } } } public SoundSystem(Mixer mixer, AudioFormat audioFormat, Time bufferDuration, int useMaxMixerLines) { - assert audioFormat != null; - assert mixer != null; - assert bufferDuration != null; + if(mixer == null) + throw new IllegalArgumentException("mixer argument must not be null"); + if(audioFormat == null) + throw new IllegalArgumentException("audioFormat argument must not be null"); + if(bufferDuration == null) + throw new IllegalArgumentException("bufferDuration argument must not be null"); + + logger.info("opening sound system using specified system mixer device"); mSystemMixer = mixer; mBufferDuration = bufferDuration; @@ -319,14 +347,18 @@ public class SoundSystem extends Thread } catch(LineUnavailableException e) { - // TODO: logging + logger.warn("cannot open output line for manual mixing of audio data: \"" + e + "\""); } } public SoundSystem(SourceDataLine outputLine, Time bufferDuration) { - assert outputLine != null; - assert bufferDuration != null; + if(outputLine == null) + throw new IllegalArgumentException("outputLine argument must not be null"); + if(bufferDuration == null) + throw new IllegalArgumentException("bufferDuration argument must not be null"); + + logger.info("opening sound system"); mMaxNumLines = 0; mBufferDuration = bufferDuration; @@ -339,16 +371,19 @@ public class SoundSystem extends Thread } catch(LineUnavailableException e) { - // TODO: logging - return; + logger.warn("cannot open output line for manual mixing of audio data: \"" + e + "\""); + return; } } - + mMixSystemOutput = new SystemOutput(outputLine); } public Output openOutput(AudioFormat audioFormat) { + if(audioFormat == null) + throw new IllegalArgumentException("audioFormat argument must not be null"); + DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat, AudioSystem.NOT_SPECIFIED); if(mSystemMixer != null && mSystemMixer.isLineSupported(info) && mSystemOutputs.size() < mMaxNumLines) @@ -364,7 +399,8 @@ public class SoundSystem extends Thread { mSystemOutputs.add(output); } - + + logger.debug("opening a system output (using a system mixer device)"); return output; } catch(LineUnavailableException e) { } @@ -379,41 +415,53 @@ public class SoundSystem extends Thread mMixerOutputs.add(output); } + logger.debug("opening a mixer output (using manual mixing)"); return output; } - + + logger.debug("opening a dummy output (no output line could be received)"); return new DummyOutput(); } public synchronized void closeOutput(Output output) { - output.disconnect(); - - if(output instanceof SystemOutput) + if(output != null) { - SystemOutput systemOutput = (SystemOutput)output; - systemOutput.close(); - mSystemOutputs.remove(systemOutput); - } + output.disconnect(); - if(output instanceof MixerOutput) - { - MixerOutput mixerOutput = (MixerOutput)output; - mMixerOutputs.remove(mixerOutput); + if(output instanceof SystemOutput) + { + logger.debug("closing a system output"); + + SystemOutput systemOutput = (SystemOutput)output; + systemOutput.close(); + mSystemOutputs.remove(systemOutput); + } + + if(output instanceof MixerOutput) + { + logger.debug("closing a mixer output"); + + MixerOutput mixerOutput = (MixerOutput)output; + mMixerOutputs.remove(mixerOutput); + } } } - public void closeAllOutputs() + public synchronized void closeAllOutputs() { + logger.debug("closing all outputs excluding the output for manual mixing"); + for(SystemOutput output: mSystemOutputs) - closeOutput(output); + output.close(); - for(MixerOutput output: mMixerOutputs) - closeOutput(output); + mSystemOutputs.clear(); + mMixerOutputs.clear(); } - public void close() + public void exit() { + logger.info("stopping sound system"); mSystemIsRunning.set(false); } @@ -423,7 +471,7 @@ public class SoundSystem extends Thread mSystemIsRunning.set(true); double averageTimeToProcessSound = mBufferDuration.getInNanoSeconds(); - double multiplicator = 0.900; + double multiplicator = 0.990; while(mSystemIsRunning.get()) { From a7360314911a9ee9aa27b79d3cbefa481a05c4a6 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Sun, 21 Feb 2010 16:49:27 +0000 Subject: [PATCH 21/44] 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 8c7326a308..a365d00a46 100644 --- a/build.ant.properties +++ b/build.ant.properties @@ -76,7 +76,7 @@ version_server = http://arianne.sourceforge.net/stendhal.version # current version of stendhal version.old = 0.80 -version = 0.81 +version = 0.81.1 # javac options javac.deprecation = true diff --git a/runserver.bat b/runserver.bat index d2b7f24467..de4bf2374e 100644 --- a/runserver.bat +++ b/runserver.bat @@ -1,3 +1,3 @@ -set STENDHAL_VERSION=0.81 +set STENDHAL_VERSION=0.81.1 set LOCALCLASSPATH=.;data\script;data\conf;stendhal-server-%STENDHAL_VERSION%.jar;marauroa.jar;mysql-connector.jar;log4j.jar;commons-lang.jar java -Xmx400m -cp "%LOCALCLASSPATH%" marauroa.server.marauroad -c server.ini -l diff --git a/runserver.sh b/runserver.sh index d7c4649055..20b1b469b5 100644 --- a/runserver.sh +++ b/runserver.sh @@ -1,5 +1,5 @@ #!/bin/sh -STENDHAL_VERSION="0.81" +STENDHAL_VERSION="0.81.1" LOCALCLASSPATH=.:data/script/:data/conf/:stendhal-server-$STENDHAL_VERSION.jar:marauroa.jar:mysql-connector.jar:log4j.jar:commons-lang.jar diff --git a/src/games/stendhal/client/update/Version.java b/src/games/stendhal/client/update/Version.java index 4a93e59d07..31170e1e86 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.81"; + public static final String VERSION = "0.81.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 d2532e8d8b..df87ed071a 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.81"; + String VERSION = "0.81.1"; /** diff --git a/src/games/stendhal/server/core/engine/GenerateINI.java b/src/games/stendhal/server/core/engine/GenerateINI.java index bde9912492..72903b5205 100644 --- a/src/games/stendhal/server/core/engine/GenerateINI.java +++ b/src/games/stendhal/server/core/engine/GenerateINI.java @@ -233,7 +233,7 @@ public class GenerateINI { out.println(); out.println("server_typeGame=" + gameName); out.println("server_name=" + gameName + " Marauroa server"); - out.println("server_version=0.81"); + out.println("server_version=0.81.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 b4065356d5..f8b0f1e845 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 3af7a3de819ed8c548854421fe910090fa1bbcc6 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Sun, 21 Feb 2010 16:50:11 +0000 Subject: [PATCH 22/44] add . to classpath --- build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.xml b/build.xml index e8c059fa97..52e5e46a2d 100644 --- a/build.xml +++ b/build.xml @@ -214,7 +214,7 @@ - + From 77c090b02710cd7819d59399d6021b46abaf2fd5 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Sun, 21 Feb 2010 16:51:16 +0000 Subject: [PATCH 23/44] added h2.jar to classpath --- runserver.bat | 2 +- runserver.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runserver.bat b/runserver.bat index de4bf2374e..bcb8d06c82 100644 --- a/runserver.bat +++ b/runserver.bat @@ -1,3 +1,3 @@ set STENDHAL_VERSION=0.81.1 -set LOCALCLASSPATH=.;data\script;data\conf;stendhal-server-%STENDHAL_VERSION%.jar;marauroa.jar;mysql-connector.jar;log4j.jar;commons-lang.jar +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 20b1b469b5..53083230e6 100644 --- a/runserver.sh +++ b/runserver.sh @@ -1,7 +1,7 @@ #!/bin/sh STENDHAL_VERSION="0.81.1" -LOCALCLASSPATH=.:data/script/:data/conf/:stendhal-server-$STENDHAL_VERSION.jar:marauroa.jar:mysql-connector.jar:log4j.jar:commons-lang.jar +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 From 4f368781a5c7074db6866d1033e4d5423d99e9b4 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Sun, 21 Feb 2010 17:02:10 +0000 Subject: [PATCH 24/44] backported using of admins.txt instead of admins.list by kymara --- build.xml | 5 ++++- data/conf/admins.txt | 0 .../core/engine/StendhalRPRuleProcessor.java | 16 ++++++++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 data/conf/admins.txt diff --git a/build.xml b/build.xml index 52e5e46a2d..9f58a72e88 100644 --- a/build.xml +++ b/build.xml @@ -514,10 +514,13 @@ - + + + + diff --git a/data/conf/admins.txt b/data/conf/admins.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/games/stendhal/server/core/engine/StendhalRPRuleProcessor.java b/src/games/stendhal/server/core/engine/StendhalRPRuleProcessor.java index 1924055fad..dfeba4287c 100644 --- a/src/games/stendhal/server/core/engine/StendhalRPRuleProcessor.java +++ b/src/games/stendhal/server/core/engine/StendhalRPRuleProcessor.java @@ -388,14 +388,22 @@ public class StendhalRPRuleProcessor implements IRPRuleProcessor { if (adminNames == null) { adminNames = new LinkedList(); - final String adminFilename = "data/conf/admins.list"; - + String adminFilename = "data/conf/admins.txt"; + final String adminFilenameAlt = "data/conf/admins.list"; + try { - final InputStream is = player.getClass().getClassLoader().getResourceAsStream( + InputStream is = player.getClass().getClassLoader().getResourceAsStream( adminFilename); if (is == null) { - logger.info("data/conf/admins.list does not exist."); + // backwards compatibility for those who used to have admins.list + is = player.getClass().getClassLoader().getResourceAsStream( + adminFilenameAlt); + if (is == null) { + logger.info("Neither " + adminFilename + " nor " + adminFilenameAlt + " exist."); + } + // update filename for any error messages + adminFilename = adminFilenameAlt; } else { final BufferedReader in = new BufferedReader( From 4ce712f90f7906fb18ba7cfe931dd75aa116f4dc Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Mon, 22 Feb 2010 20:02:41 +0000 Subject: [PATCH 25/44] prevent crash on empty soundNameList (thanks to samsat for reporting it) --- src/games/stendhal/client/entity/AudibleEntity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/stendhal/client/entity/AudibleEntity.java b/src/games/stendhal/client/entity/AudibleEntity.java index 9c11340326..bf9ee703e6 100644 --- a/src/games/stendhal/client/entity/AudibleEntity.java +++ b/src/games/stendhal/client/entity/AudibleEntity.java @@ -42,7 +42,7 @@ public abstract class AudibleEntity extends RPEntity { protected Sound getRandomSoundFromGroup(String groupName, boolean getCloned) { ArrayList soundNameList = mSoundGroups.get(groupName); - if (soundNameList != null) { + if ((soundNameList != null) && !soundNameList.isEmpty()) { String name = soundNameList.get(Rand.rand(soundNameList.size())); Sound sound = SoundSystemFacade.get().getSound(name); From 573e7525e1c5131003c988cd4aef7e48e5b66714 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Mon, 22 Feb 2010 20:07:50 +0000 Subject: [PATCH 26/44] prevent crash on empty soundNameList (thanks to samsat for reporting it) --- doc/CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/CHANGES.txt b/doc/CHANGES.txt index e9ac1a93e9..e8700760c9 100644 --- a/doc/CHANGES.txt +++ b/doc/CHANGES.txt @@ -1,5 +1,11 @@ Changelog --------- +0.81.1 +*bug fixes* +- prevent client crash on empty soundNameList +- renamed admins.list to admins.txt to simplify installation on windows with hidden file name extensions +- fixed a server side classpath issue + 0.81 *features* - player stats moved from the character window to the side panel From 47489f880549c67d20747fa3c60b4bae84c9bf1d Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Tue, 23 Feb 2010 21:05:37 +0000 Subject: [PATCH 27/44] updated marauroa.jar to 3.5 --- libs/marauroa.jar | Bin 256666 -> 258555 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/libs/marauroa.jar b/libs/marauroa.jar index 23c72925e242dcf9f852cc704f59b1e812456c6e..adfaec91c935cbae1995860c143e95bd9b36b8e4 100644 GIT binary patch delta 44961 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 u92%bdCm0@23`qNgNC1~lh$NO2> Date: Tue, 23 Feb 2010 21:07:57 +0000 Subject: [PATCH 28/44] - updated to Marauroa 3.5 to fix an issue with null-values in the timedate columns in gameEvents and account --- doc/CHANGES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/CHANGES.txt b/doc/CHANGES.txt index e8700760c9..16653782d0 100644 --- a/doc/CHANGES.txt +++ b/doc/CHANGES.txt @@ -5,6 +5,7 @@ Changelog - prevent client crash on empty soundNameList - renamed admins.list to admins.txt to simplify installation on windows with hidden file name extensions - fixed a server side classpath issue +- updated to Marauroa 3.5 to fix an issue with null-values in the timedate columns in gameEvents and account 0.81 *features* From 7f39d3f3a44c666b102c6fe049b966266eb4658d Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Tue, 23 Feb 2010 21:45:14 +0000 Subject: [PATCH 29/44] changed base version for update to 0.81 --- build.ant.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.ant.properties b/build.ant.properties index a365d00a46..c4e887de8c 100644 --- a/build.ant.properties +++ b/build.ant.properties @@ -75,7 +75,7 @@ updates_server = http://arianne.sourceforge.net/stendhal/updates version_server = http://arianne.sourceforge.net/stendhal.version # current version of stendhal -version.old = 0.80 +version.old = 0.81 version = 0.81.1 # javac options From 47af4d3b8261820693d3e3420f596beeca91dd49 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Wed, 24 Feb 2010 01:38:21 +0000 Subject: [PATCH 30/44] increase 0 hp to 1 hp on login (fixes #2955566) --- .../stendhal/server/entity/player/UpdateConverter.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/games/stendhal/server/entity/player/UpdateConverter.java b/src/games/stendhal/server/entity/player/UpdateConverter.java index 2053fe69a6..97df42f598 100644 --- a/src/games/stendhal/server/entity/player/UpdateConverter.java +++ b/src/games/stendhal/server/entity/player/UpdateConverter.java @@ -17,7 +17,10 @@ import java.util.List; import marauroa.common.game.RPObject; import marauroa.common.game.RPSlot; +import org.apache.log4j.Logger; + public abstract class UpdateConverter { + private static Logger logger = Logger.getLogger(UpdateConverter.class); private static final List ITEM_NAMES_OLD = Arrays.asList( "flail_+2", "leather_armor_+1", "leather_cuirass_+1", @@ -212,6 +215,12 @@ public abstract class UpdateConverter { // port to 0.66 transformKillSlot(object); + + // port to 0.81 because of a bug in 0.80 which allowed 0 hp by double killing on logout during dying + if (object.getInt("hp") <= 0) { + logger.warn("Setting hp to 1 for player " + object); + object.put("hp", 1); + } } /** From acd2dfa173db23ca6582a1d43e036dddd0055d0a Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Wed, 24 Feb 2010 01:43:57 +0000 Subject: [PATCH 31/44] updated CHANGES.txt --- doc/CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/CHANGES.txt b/doc/CHANGES.txt index 16653782d0..80aeae5021 100644 --- a/doc/CHANGES.txt +++ b/doc/CHANGES.txt @@ -2,11 +2,14 @@ Changelog --------- 0.81.1 *bug fixes* +- fixed an issue with 0 hp created by logging out while dying (thanks to Andrzej KofaƄski) - prevent client crash on empty soundNameList - renamed admins.list to admins.txt to simplify installation on windows with hidden file name extensions - fixed a server side classpath issue - updated to Marauroa 3.5 to fix an issue with null-values in the timedate columns in gameEvents and account + + 0.81 *features* - player stats moved from the character window to the side panel From bbbce085523e1973a2c9accc1619e2d868956c7f Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Tue, 2 Mar 2010 20:02:16 +0000 Subject: [PATCH 32/44] don't crash on exception thrown by the sound system on init. --- src/games/stendhal/client/gui/j2DClient.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/games/stendhal/client/gui/j2DClient.java b/src/games/stendhal/client/gui/j2DClient.java index e0c2ce4d1d..13b569439c 100644 --- a/src/games/stendhal/client/gui/j2DClient.java +++ b/src/games/stendhal/client/gui/j2DClient.java @@ -410,7 +410,11 @@ public class j2DClient implements UserInterface { SlashActionRepository.register(); checkAndComplainAboutJavaImplementation(); - WorldObjects.addWorldListener(SoundSystemFacade.get()); + try { + WorldObjects.addWorldListener(SoundSystemFacade.get()); + } catch (RuntimeException e) { + logger.error(e, e); + } } // constructor private void checkAndComplainAboutJavaImplementation() { From db5314d95cf81c0ce3a987f72db8dd4f3004ff09 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Thu, 4 Mar 2010 21:01:15 +0000 Subject: [PATCH 33/44] backported try-catch-block around view.draw() --- src/games/stendhal/client/GameScreen.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/games/stendhal/client/GameScreen.java b/src/games/stendhal/client/GameScreen.java index d4dad6d76f..2a04cf8590 100644 --- a/src/games/stendhal/client/GameScreen.java +++ b/src/games/stendhal/client/GameScreen.java @@ -56,6 +56,8 @@ import org.apache.log4j.Logger; * can not be used for anything but trivial cases, so using Canvas instead */ public class GameScreen implements PositionChangeListener, IGameScreen { + private static Logger logger = Logger.getLogger(GameScreen.class); + /** * Comparator used to sort entities to display. */ @@ -594,7 +596,11 @@ public class GameScreen implements PositionChangeListener, IGameScreen { */ private void drawEntities(final Graphics2D g) { for (final EntityView view : views) { - view.draw(g); + try { + view.draw(g); + } catch (RuntimeException e) { + logger.error(e, e); + } } } From 5481e959ea1b018f314a414ba959db44a426f741 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Thu, 4 Mar 2010 21:06:39 +0000 Subject: [PATCH 34/44] backported try-catch blocks --- src/games/stendhal/client/gui/j2DClient.java | 262 ++++++++++--------- 1 file changed, 133 insertions(+), 129 deletions(-) diff --git a/src/games/stendhal/client/gui/j2DClient.java b/src/games/stendhal/client/gui/j2DClient.java index 13b569439c..4b74759e32 100644 --- a/src/games/stendhal/client/gui/j2DClient.java +++ b/src/games/stendhal/client/gui/j2DClient.java @@ -476,141 +476,145 @@ public class j2DClient implements UserInterface { boolean canExit = false; while (!canExit) { - fps++; - // figure out what time it is right after the screen flip then - // later we can figure out how long we have been doing redrawing - // / networking, then we know how long we need to sleep to make - // the next flip happen at the right time + try { + fps++; + // figure out what time it is right after the screen flip then + // later we can figure out how long we have been doing redrawing + // / networking, then we know how long we need to sleep to make + // the next flip happen at the right time - screen.nextFrame(); - final long now = System.currentTimeMillis(); - final int delta = (int) (now - refreshTime); - refreshTime = now; - - logger.debug("Move objects"); - gameObjects.update(delta); - - if (!client.isInBatchUpdate() && gameLayers.changedArea()) { - /* - * Update the screen - */ - screen.setMaxWorldSize(gameLayers.getWidth(), - gameLayers.getHeight()); - screen.center(); - - // [Re]create the map + screen.nextFrame(); + final long now = System.currentTimeMillis(); + final int delta = (int) (now - refreshTime); + refreshTime = now; - final CollisionDetection cd = gameLayers.getCollisionDetection(); - final CollisionDetection pd = gameLayers.getProtectionDetection(); - - if (cd != null) { - minimap.update(cd, pd, - screen.getComponent().getGraphicsConfiguration(), - gameLayers.getArea()); - } - gameLayers.resetChangedArea(); - } - - final User user = User.get(); - - if (user != null) { - // check if the player object has changed. - // Note: this is an exact object reference check - if (user != lastuser) { - character.setPlayer(user); - keyring.setSlot(user, "keyring", gameScreen); - inventory.setSlot(user, "bag", gameScreen); - - lastuser = user; - } - } - - if (!client.isInBatchUpdate()) { - if (mainFrame.getMainFrame().getState() != Frame.ICONIFIED) { - logger.debug("Draw screen"); - screen.draw(); - minimap.refresh(); - } - } - - logger.debug("Query network"); - - if (client.loop(0)) { - lastMessageHandle = refreshTime; - } - - /* - * Process delayed direction release - */ - if ((directionRelease != null) && directionRelease.hasExpired()) { - client.removeDirection(directionRelease.getDirection(), - directionRelease.isFacing()); - - directionRelease = null; - } - - if (logger.isDebugEnabled()) { - if ((refreshTime - lastFpsTime) >= 1000L) { - logger.debug("FPS: " + fps); - final long freeMemory = Runtime.getRuntime().freeMemory() / 1024; - final long totalMemory = Runtime.getRuntime().totalMemory() / 1024; - - logger.debug("Total/Used memory: " + totalMemory + "/" - + (totalMemory - freeMemory)); - - fps = 0; - lastFpsTime = refreshTime; - } - } - - // Shows a offline icon if no messages are received in 120 seconds. - if ((refreshTime - lastMessageHandle > 120000L) - || !client.getConnectionState()) { - setOffline(true); - } else { - setOffline(false); - } - - logger.debug("Start sleeping"); - // we know how long we want per screen refresh (40ms) then - // we add the refresh time and subtract the current time - // leaving us with the amount we still need to sleep. - long wait = frameLength + refreshTime - System.currentTimeMillis(); - - if (wait > 0) { - if (wait > 100L) { - logger.info("Waiting " + wait + " ms"); - wait = 100L; - } - - try { - Thread.sleep(wait); - } catch (final InterruptedException e) { - } - } - - logger.debug("End sleeping"); - - if (!gameRunning) { - logger.info("Request logout"); - try { + logger.debug("Move objects"); + gameObjects.update(delta); + + if (!client.isInBatchUpdate() && gameLayers.changedArea()) { /* - * We request server permision to logout. Server can deny - * it. + * Update the screen */ - if (client.logout()) { - canExit = true; - } else { - logger.warn("You can't logout now."); - gameRunning = true; + screen.setMaxWorldSize(gameLayers.getWidth(), + gameLayers.getHeight()); + screen.center(); + + // [Re]create the map + + final CollisionDetection cd = gameLayers.getCollisionDetection(); + final CollisionDetection pd = gameLayers.getProtectionDetection(); + + if (cd != null) { + minimap.update(cd, pd, + screen.getComponent().getGraphicsConfiguration(), + gameLayers.getArea()); + } + gameLayers.resetChangedArea(); + } + + final User user = User.get(); + + if (user != null) { + // check if the player object has changed. + // Note: this is an exact object reference check + if (user != lastuser) { + character.setPlayer(user); + keyring.setSlot(user, "keyring", gameScreen); + inventory.setSlot(user, "bag", gameScreen); + + lastuser = user; } - } catch (final Exception e) { - /* - * If we get a timeout exception we accept exit request. - */ - canExit = true; - logger.error(e, e); } + + if (!client.isInBatchUpdate()) { + if (mainFrame.getMainFrame().getState() != Frame.ICONIFIED) { + logger.debug("Draw screen"); + screen.draw(); + minimap.refresh(); + } + } + + logger.debug("Query network"); + + if (client.loop(0)) { + lastMessageHandle = refreshTime; + } + + /* + * Process delayed direction release + */ + if ((directionRelease != null) && directionRelease.hasExpired()) { + client.removeDirection(directionRelease.getDirection(), + directionRelease.isFacing()); + + directionRelease = null; + } + + if (logger.isDebugEnabled()) { + if ((refreshTime - lastFpsTime) >= 1000L) { + logger.debug("FPS: " + fps); + final long freeMemory = Runtime.getRuntime().freeMemory() / 1024; + final long totalMemory = Runtime.getRuntime().totalMemory() / 1024; + + logger.debug("Total/Used memory: " + totalMemory + "/" + + (totalMemory - freeMemory)); + + fps = 0; + lastFpsTime = refreshTime; + } + } + + // Shows a offline icon if no messages are received in 120 seconds. + if ((refreshTime - lastMessageHandle > 120000L) + || !client.getConnectionState()) { + setOffline(true); + } else { + setOffline(false); + } + + logger.debug("Start sleeping"); + // we know how long we want per screen refresh (40ms) then + // we add the refresh time and subtract the current time + // leaving us with the amount we still need to sleep. + long wait = frameLength + refreshTime - System.currentTimeMillis(); + + if (wait > 0) { + if (wait > 100L) { + logger.info("Waiting " + wait + " ms"); + wait = 100L; + } + + try { + Thread.sleep(wait); + } catch (final InterruptedException e) { + } + } + + logger.debug("End sleeping"); + + if (!gameRunning) { + logger.info("Request logout"); + try { + /* + * We request server permision to logout. Server can deny + * it. + */ + if (client.logout()) { + canExit = true; + } else { + logger.warn("You can't logout now."); + gameRunning = true; + } + } catch (final Exception e) { + /* + * If we get a timeout exception we accept exit request. + */ + canExit = true; + logger.error(e, e); + } + } + } catch (RuntimeException e) { + logger.error(e, e); } } From 9c7e4016a2c284d9ba0e3ae7c58e6812a686ec2d Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Thu, 4 Mar 2010 21:09:09 +0000 Subject: [PATCH 35/44] fixed NullPointerException on failing ImageIO.read for existing files. --- src/games/stendhal/client/sprite/SpriteStore.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/games/stendhal/client/sprite/SpriteStore.java b/src/games/stendhal/client/sprite/SpriteStore.java index a895b0510d..c29417359f 100644 --- a/src/games/stendhal/client/sprite/SpriteStore.java +++ b/src/games/stendhal/client/sprite/SpriteStore.java @@ -206,6 +206,7 @@ public class SpriteStore { // avoid infinite loop and stack overflow in case of missing // failsafe icon if (ref.equals(FAILSAFE_ICON_REF)) { + logger.error("Cannot find FAILSAFE_ICON_REF: " + FAILSAFE_ICON_REF); return null; } else { return getFailsafe(); @@ -215,8 +216,14 @@ public class SpriteStore { // use ImageIO to read the image in sourceImage = ImageIO.read(url); } catch (final IOException e) { - logger.error("Failed to load: " + ref, e); - return null; + logger.error("Failed to read: " + ref, e); + + if (ref.equals(FAILSAFE_ICON_REF)) { + logger.error("Cannot read FAILSAFE_ICON_REF: " + FAILSAFE_ICON_REF); + return null; + } else { + return getFailsafe(); + } } // create an accelerated image of the right size to store our sprite in From 72e5f94fc2806da867807e81c0e926af749d229f Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Thu, 4 Mar 2010 21:13:08 +0000 Subject: [PATCH 36/44] added try catch blocks --- .../client/sound/SoundSystemFacade.java | 95 ++++++++++++++----- 1 file changed, 69 insertions(+), 26 deletions(-) diff --git a/src/games/stendhal/client/sound/SoundSystemFacade.java b/src/games/stendhal/client/sound/SoundSystemFacade.java index 848a5b2bdd..940c8fcd88 100644 --- a/src/games/stendhal/client/sound/SoundSystemFacade.java +++ b/src/games/stendhal/client/sound/SoundSystemFacade.java @@ -36,14 +36,22 @@ public class SoundSystemFacade extends SoundManager implements WorldListener { } private SoundSystemFacade() { - boolean mute = !Boolean.parseBoolean(WtWindowManager.getInstance().getProperty("sound.play", "true")); - super.mute(mute, null); + try { + boolean mute = !Boolean.parseBoolean(WtWindowManager.getInstance().getProperty("sound.play", "true")); + super.mute(mute, null); + } catch (RuntimeException e) { + logger.error(e, e); + } } public void playerMoved() { - float[] position = Algebra.vecf((float) User.get().getX(), (float) User.get().getY()); - super.setHearerPosition(position); - update(); + try { + float[] position = Algebra.vecf((float) User.get().getX(), (float) User.get().getY()); + super.setHearerPosition(position); + update(); + } catch (RuntimeException e) { + logger.error(e, e); + } } public void zoneEntered(String zoneName) { @@ -55,50 +63,85 @@ public class SoundSystemFacade extends SoundManager implements WorldListener { } public void stop(String soundName, Time fadeOutDuration) { - super.stop(getSound(soundName), fadeOutDuration); + try { + super.stop(getSound(soundName), fadeOutDuration); + } catch (RuntimeException e) { + logger.error(e, e); + } } public Sound getSound(String soundName) { - return sounds.get(soundName); + try { + return sounds.get(soundName); + } catch (RuntimeException e) { + logger.error(e, e); + } + return null; } public Sound openSound(String fileURI, SoundFile.Type fileType) { - return super.openSound(resourceLocator.getResource(fileURI), fileType); + try { + return super.openSound(resourceLocator.getResource(fileURI), fileType); + } catch (RuntimeException e) { + logger.error(e, e); + } + return null; } public Sound openSound(String fileURI, SoundFile.Type fileType, int numSamplesPerChunk, boolean enableStreaming) { - return super.openSound(resourceLocator.getResource(fileURI), fileType, numSamplesPerChunk, enableStreaming); + try { + return super.openSound(resourceLocator.getResource(fileURI), fileType, numSamplesPerChunk, enableStreaming); + } catch (RuntimeException e) { + logger.error(e, e); + } + return null; } public Sound loadSound(String name, String fileURI, SoundFile.Type fileType, boolean enableStreaming) { - Sound sound = sounds.get(name); - - if(sound == null) { - sound = super.openSound(resourceLocator.getResource(fileURI), fileType, 256, enableStreaming); - - if(sound != null) { - sounds.put(name, sound); + try { + Sound sound = sounds.get(name); + + if(sound == null) { + sound = super.openSound(resourceLocator.getResource(fileURI), fileType, 256, enableStreaming); + + if(sound != null) { + sounds.put(name, sound); + } } + return sound; + } catch (RuntimeException e) { + logger.error(e, e); } - - return sound; + return null; } public void play(final String soundName, final SoundLayer soundLayer, int volume) { - Sound sound = loadSound(soundName, "audio:/" + soundName + ".ogg", Type.OGG, false); - super.play(sound, Numeric.intToFloat(volume, 100.0f), 0, null, false, new Time()); + try { + Sound sound = loadSound(soundName, "audio:/" + soundName + ".ogg", Type.OGG, false); + super.play(sound, Numeric.intToFloat(volume, 100.0f), 0, null, false, new Time()); + } catch (RuntimeException e) { + logger.error(e, e); + } } public void play(final String soundName, final double x, final double y, final SoundLayer soundLayer, int volume) { - AudibleArea area = new AudibleCircleArea(Algebra.vecf((float) x, (float) y), 3, 20); - Sound sound = loadSound(soundName, "audio:/" + soundName + ".ogg", Type.OGG, false); - super.play(sound, Numeric.intToFloat(volume, 100.0f), 0, area, false, new Time()); + try { + AudibleArea area = new AudibleCircleArea(Algebra.vecf((float) x, (float) y), 3, 20); + Sound sound = loadSound(soundName, "audio:/" + soundName + ".ogg", Type.OGG, false); + super.play(sound, Numeric.intToFloat(volume, 100.0f), 0, area, false, new Time()); + } catch (RuntimeException e) { + logger.error(e, e); + } } public void play(final String soundName, final double x, final double y, int radius, final SoundLayer soundLayer, int volume) { - AudibleArea area = new AudibleCircleArea(Algebra.vecf((float) x, (float) y), radius / 4.0f, radius); - Sound sound = loadSound(soundName, "audio:/" + soundName + ".ogg", Type.OGG, false); - super.play(sound, Numeric.intToFloat(volume, 100.0f), 0, area, false, new Time()); + try { + AudibleArea area = new AudibleCircleArea(Algebra.vecf((float) x, (float) y), radius / 4.0f, radius); + Sound sound = loadSound(soundName, "audio:/" + soundName + ".ogg", Type.OGG, false); + super.play(sound, Numeric.intToFloat(volume, 100.0f), 0, area, false, new Time()); + } catch (RuntimeException e) { + logger.error(e, e); + } } } From 68b202feab88f44f9e2a44bf702938fdf4099919 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Thu, 4 Mar 2010 21:24:50 +0000 Subject: [PATCH 37/44] log residual entities as debug --- src/games/stendhal/client/GameObjects.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/games/stendhal/client/GameObjects.java b/src/games/stendhal/client/GameObjects.java index 9b88c14678..ae00632fcf 100644 --- a/src/games/stendhal/client/GameObjects.java +++ b/src/games/stendhal/client/GameObjects.java @@ -110,7 +110,7 @@ public class GameObjects implements RPObjectChangeListener, Iterable { while (it.hasNext()) { final IEntity entity = it.next(); - logger.error("Residual entity: " + entity); + logger.debug("Residual entity: " + entity); entity.release(); } From b9f9da1b2bc4d92af33af07a8486146543fb2080 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Thu, 4 Mar 2010 21:35:32 +0000 Subject: [PATCH 38/44] log uncaught exceptions (fixes #2963720) --- .../client/LogUncaughtExceptionHandler.java | 47 +++++++++++++++++++ src/games/stendhal/client/stendhal.java | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/games/stendhal/client/LogUncaughtExceptionHandler.java diff --git a/src/games/stendhal/client/LogUncaughtExceptionHandler.java b/src/games/stendhal/client/LogUncaughtExceptionHandler.java new file mode 100644 index 0000000000..e2a95dd63a --- /dev/null +++ b/src/games/stendhal/client/LogUncaughtExceptionHandler.java @@ -0,0 +1,47 @@ +/* $Id$ */ +/*************************************************************************** + * (C) Copyright 2003-2010 - Marauroa * + *************************************************************************** + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +package games.stendhal.client; + +import marauroa.common.Log4J; +import marauroa.common.Logger; + +/** + * logs uncaught exceptions to the logging system before + * the exception is propagated to the Java VM which will + * kill the thread. The Java VM only logs to stderr so + * there would be no information in the logfile without + * this class. + */ +public class LogUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { + private static Logger logger = Log4J.getLogger(LogUncaughtExceptionHandler.class); + private Thread.UncaughtExceptionHandler next; + + public void uncaughtException(Thread thread, Throwable exception) { + logger.error("Exception in thread " + thread.getName(), exception); + System.err.println("Exception in thread " + thread.getName()); + exception.printStackTrace(); + if (next != null) { + next.uncaughtException(thread, exception); + } + } + + /** + * installs this uncaught exception handler + */ + public static void setup() { + LogUncaughtExceptionHandler handler = new LogUncaughtExceptionHandler(); + handler.next = Thread.getDefaultUncaughtExceptionHandler(); + Thread.setDefaultUncaughtExceptionHandler(handler); + } + +} diff --git a/src/games/stendhal/client/stendhal.java b/src/games/stendhal/client/stendhal.java index b21c027dd1..6bed1c5723 100644 --- a/src/games/stendhal/client/stendhal.java +++ b/src/games/stendhal/client/stendhal.java @@ -110,7 +110,7 @@ public class stendhal { logger.info("Java-VM: " + System.getProperty("java.vm.vendor") + " " + System.getProperty("java.vm.name") + " " + System.getProperty("java.vm.version")); - + LogUncaughtExceptionHandler.setup(); } /** From b9f1705f98bb945c480eace6a8e0ded22dc76ee4 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Thu, 4 Mar 2010 21:41:21 +0000 Subject: [PATCH 39/44] updated marauroa --- libs/marauroa.jar | Bin 258555 -> 258676 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/libs/marauroa.jar b/libs/marauroa.jar index adfaec91c935cbae1995860c143e95bd9b36b8e4..c6e67ed8dd5c099d5da4ed3f8bdb04e876e03d21 100644 GIT binary patch delta 29869 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 Lv~=D1qn(m=SoZG%#{xy4;~obpHayBa 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 Y!ggQrW{Sj7-Ewi%Gb9=LKp~?40Z8p&`~Uy| delta 29802 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 From 33bd04089d3406bc550a5069d2eed36e328c35cf Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Thu, 4 Mar 2010 21:43:41 +0000 Subject: [PATCH 40/44] updated 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 c4e887de8c..345c0582ec 100644 --- a/build.ant.properties +++ b/build.ant.properties @@ -76,7 +76,7 @@ version_server = http://arianne.sourceforge.net/stendhal.version # current version of stendhal version.old = 0.81 -version = 0.81.1 +version = 0.81.2 # javac options javac.deprecation = true diff --git a/runserver.bat b/runserver.bat index bcb8d06c82..48e3fbbdb8 100644 --- a/runserver.bat +++ b/runserver.bat @@ -1,3 +1,3 @@ -set STENDHAL_VERSION=0.81.1 +set STENDHAL_VERSION=0.81.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 53083230e6..1fb0590251 100644 --- a/runserver.sh +++ b/runserver.sh @@ -1,5 +1,5 @@ #!/bin/sh -STENDHAL_VERSION="0.81.1" +STENDHAL_VERSION="0.81.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 31170e1e86..78ff38f1b5 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.81.1"; + public static final String VERSION = "0.81.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 df87ed071a..2731b49ec8 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.81.1"; + String VERSION = "0.81.2"; /** diff --git a/src/games/stendhal/server/core/engine/GenerateINI.java b/src/games/stendhal/server/core/engine/GenerateINI.java index 72903b5205..d1baddf911 100644 --- a/src/games/stendhal/server/core/engine/GenerateINI.java +++ b/src/games/stendhal/server/core/engine/GenerateINI.java @@ -233,7 +233,7 @@ public class GenerateINI { out.println(); out.println("server_typeGame=" + gameName); out.println("server_name=" + gameName + " Marauroa server"); - out.println("server_version=0.81.1"); + out.println("server_version=0.81.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 f8b0f1e845..407800abc8 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 d266544259cb2b20ffae95ec4f3d5b600f8475da Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Thu, 4 Mar 2010 22:52:36 +0000 Subject: [PATCH 41/44] change log for 0.81.2 --- doc/CHANGES.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/CHANGES.txt b/doc/CHANGES.txt index 80aeae5021..6e8c96a587 100644 --- a/doc/CHANGES.txt +++ b/doc/CHANGES.txt @@ -1,5 +1,19 @@ Changelog --------- +0.81.2 +*bug fixes* +- fixed a crash on Linux using alsa (non pulse) audio drivers and Sun Java (not OpenJDK) + if all channels are in use by another application +- fixed rare InvalidVersionExceptions in the network code on high latency connections + (for example for people living outside Europe to an server in Europe) +- handle failure to load sprite images more gracefully +- improved logging of uncaught exceptions + +0.81.2 contains the first results of the Client Quality Weeks. Thanks everyone for providing +your error log files and pleace continue to do so. + + + 0.81.1 *bug fixes* - fixed an issue with 0 hp created by logging out while dying (thanks to Andrzej KofaƄski) From 0d96d840e15ae18ab67707b553b0b42976913c76 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Tue, 16 Mar 2010 17:31:07 +0000 Subject: [PATCH 42/44] prevent crash on "No line matching interface" (fixes #2970406) --- .../client/sound/SoundSystemFacade.java | 7 +++++-- .../client/sound/manager/SoundManager.java | 18 +++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/games/stendhal/client/sound/SoundSystemFacade.java b/src/games/stendhal/client/sound/SoundSystemFacade.java index 940c8fcd88..b1d1070c6e 100644 --- a/src/games/stendhal/client/sound/SoundSystemFacade.java +++ b/src/games/stendhal/client/sound/SoundSystemFacade.java @@ -27,12 +27,15 @@ import org.apache.log4j.Logger; */ public class SoundSystemFacade extends SoundManager implements WorldListener { private static final Logger logger = Logger.getLogger(SoundSystemFacade.class); - private static final SoundSystemFacade singletonInstance = new SoundSystemFacade(); + private static SoundSystemFacade instance; private final HashMap sounds = new HashMap(); private final ResourceLocator resourceLocator = ResourceManager.get(); public static SoundSystemFacade get() { - return singletonInstance; + if (instance == null) { + instance = new SoundSystemFacade(); + } + return instance; } private SoundSystemFacade() { diff --git a/src/games/stendhal/client/sound/manager/SoundManager.java b/src/games/stendhal/client/sound/manager/SoundManager.java index 0e5830e545..b92de05bd8 100644 --- a/src/games/stendhal/client/sound/manager/SoundManager.java +++ b/src/games/stendhal/client/sound/manager/SoundManager.java @@ -159,14 +159,18 @@ public class SoundManager private boolean mMute = false; private SoundSystem mSoundSystem; - protected SoundManager() - { - Algebra.mov_Vecf(mHearerPosition, 0.0f); + protected SoundManager() + { + try { + Algebra.mov_Vecf(mHearerPosition, 0.0f); - mSoundSystem = new SoundSystem(AUDIO_FORMAT, new Time(15, Time.Unit.MILLI), USE_NUM_MIXER_LINES); - mSoundSystem.setDaemon(true); - mSoundSystem.start(); - } + mSoundSystem = new SoundSystem(AUDIO_FORMAT, new Time(15, Time.Unit.MILLI), USE_NUM_MIXER_LINES); + mSoundSystem.setDaemon(true); + mSoundSystem.start(); + } catch (RuntimeException e) { + logger.error(e, e); + } + } public Sound openSound(Resource resource, SoundFile.Type fileType) { From 63f75892e1b41a0af4f61a3ea970862658f418b5 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Tue, 16 Mar 2010 17:33:31 +0000 Subject: [PATCH 43/44] added 0.81.3 change log entry: prevent crash on "No line matching interface" (fixes #2970406) --- doc/CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/CHANGES.txt b/doc/CHANGES.txt index 6e8c96a587..a9df5c322c 100644 --- a/doc/CHANGES.txt +++ b/doc/CHANGES.txt @@ -1,5 +1,8 @@ Changelog --------- +0.81.3 +- prevent crash on "No line matching interface" (fixes #2970406) + 0.81.2 *bug fixes* - fixed a crash on Linux using alsa (non pulse) audio drivers and Sun Java (not OpenJDK) From d122d2f312ea7d3d4f1547c46bdeefc032538e11 Mon Sep 17 00:00:00 2001 From: Hendrik Brummermann Date: Tue, 16 Mar 2010 17:36:42 +0000 Subject: [PATCH 44/44] set version number to 0.81.3 --- 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 345c0582ec..05921d96de 100644 --- a/build.ant.properties +++ b/build.ant.properties @@ -76,7 +76,7 @@ version_server = http://arianne.sourceforge.net/stendhal.version # current version of stendhal version.old = 0.81 -version = 0.81.2 +version = 0.81.3 # javac options javac.deprecation = true diff --git a/runserver.bat b/runserver.bat index 48e3fbbdb8..c4c01fee41 100644 --- a/runserver.bat +++ b/runserver.bat @@ -1,3 +1,3 @@ -set STENDHAL_VERSION=0.81.2 +set STENDHAL_VERSION=0.81.3 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 1fb0590251..79f67f0fba 100644 --- a/runserver.sh +++ b/runserver.sh @@ -1,5 +1,5 @@ #!/bin/sh -STENDHAL_VERSION="0.81.2" +STENDHAL_VERSION="0.81.3" 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 78ff38f1b5..8044205536 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.81.2"; + public static final String VERSION = "0.81.3"; /** * 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 2731b49ec8..3c666dfcfc 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.81.2"; + String VERSION = "0.81.3"; /** diff --git a/src/games/stendhal/server/core/engine/GenerateINI.java b/src/games/stendhal/server/core/engine/GenerateINI.java index d1baddf911..5a583ac14b 100644 --- a/src/games/stendhal/server/core/engine/GenerateINI.java +++ b/src/games/stendhal/server/core/engine/GenerateINI.java @@ -233,7 +233,7 @@ public class GenerateINI { out.println(); out.println("server_typeGame=" + gameName); out.println("server_name=" + gameName + " Marauroa server"); - out.println("server_version=0.81.2"); + out.println("server_version=0.81.3"); 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 407800abc8..683f6dddce 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 - +