Compare commits
25 commits
master
...
VERSION_01
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
785675f13d | ||
|
|
2e9ade5a23 | ||
|
|
b8359f3a81 | ||
|
|
1ff055b2f0 | ||
|
|
ab5a10400a | ||
|
|
c8eb546590 | ||
|
|
14fa450dfd | ||
|
|
8241fc9686 | ||
|
|
328ec57136 | ||
|
|
92da86aef6 | ||
|
|
6e3cb4b3bd | ||
|
|
423f94f25e | ||
|
|
010375d6d5 | ||
|
|
17864b85c7 | ||
|
|
ba585d7a91 | ||
|
|
a68991e38b | ||
|
|
e56d8680d9 | ||
|
|
68f21d5eeb | ||
|
|
8af5ae1bbb | ||
|
|
22fa54ab6a | ||
|
|
6b57ebe3f8 | ||
|
|
f1523798c7 | ||
|
|
4fb31e2a7d | ||
|
|
0b619f9d8c | ||
|
|
edf4297854 |
55 changed files with 431 additions and 110 deletions
|
|
@ -25,5 +25,5 @@
|
|||
<classpathentry kind="lib" path="libs/jakarta.annotation-api-2.1.1.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="libs/tomcat-embed-core-10.1.13.jar"/>
|
||||
<classpathentry kind="lib" path="libs/tomcat-embed-websocket-10.1.13.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
<classpathentry kind="output" path="build/eclipse"/>
|
||||
</classpath>
|
||||
|
|
|
|||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -40,7 +40,6 @@ javadocs
|
|||
statserver_stats.xml
|
||||
/*.ks
|
||||
build_client_data
|
||||
/bin
|
||||
.byecycle
|
||||
build_server_xmlconf
|
||||
*.umlproject
|
||||
|
|
@ -51,3 +50,4 @@ build_server_xmlconf
|
|||
/node_modules/
|
||||
/log/
|
||||
/build-archive/
|
||||
/srcjs/contributors.html
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ android {
|
|||
applicationId namespace
|
||||
minSdk 21
|
||||
targetSdk 32
|
||||
versionCode 1045005
|
||||
versionName "1.45.5"
|
||||
versionCode 1046000
|
||||
versionName "1.46"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
targetSdkVersion 32
|
||||
minSdkVersion 21
|
||||
|
|
|
|||
|
|
@ -130,9 +130,9 @@ public class ClientView extends WebView {
|
|||
viewSettings.setLoadWithOverviewMode(true);
|
||||
viewSettings.setUseWideViewPort(true);
|
||||
|
||||
// disable zoom
|
||||
viewSettings.setSupportZoom(false);
|
||||
viewSettings.setBuiltInZoomControls(false);
|
||||
// zoom controls
|
||||
viewSettings.setSupportZoom(true);
|
||||
viewSettings.setBuiltInZoomControls(true);
|
||||
viewSettings.setDisplayZoomControls(false);
|
||||
|
||||
// allow autoplay of music
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ public class Menu {
|
|||
}
|
||||
});
|
||||
|
||||
/*
|
||||
final Button btn_about = (Button) activity.findViewById(R.id.btn_about);
|
||||
btn_about.setOnClickListener(new ClickListener() {
|
||||
@Override
|
||||
|
|
@ -244,6 +245,7 @@ public class Menu {
|
|||
builder.create().show();
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
final Button btn_quit = (Button) activity.findViewById(R.id.btn_quit);
|
||||
btn_quit.setOnClickListener(new ClickListener() {
|
||||
|
|
|
|||
1
app/android/client/src/main/play/contact-email.txt
Normal file
1
app/android/client/src/main/play/contact-email.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
https://sourceforge.net/projects/arianne/support
|
||||
1
app/android/client/src/main/play/contact-website.txt
Normal file
1
app/android/client/src/main/play/contact-website.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
https://stendhalgame.org/
|
||||
1
app/android/client/src/main/play/default-language.txt
Normal file
1
app/android/client/src/main/play/default-language.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
en-US
|
||||
|
|
@ -0,0 +1 @@
|
|||
Stendhal ist ein Multiplayer-Adventure mit klassischer 2D-Grafik. Es ist vollständig Open Source.
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
Stendhal has a huge and rich world. You can explore cities, forest, mountains, plains and dungeons.
|
||||
You can fight monsters and become a hero.
|
||||
|
||||
You will meet a wide variety of characters. Many will give you tasks and quests for valuable
|
||||
experience. You may be asked to help protect land, feed the hungry, heal the sick, make someone
|
||||
happy, solve a puzzle or simply lend a hand.
|
||||
|
||||
So what are you waiting for? A whole new world awaits... And if you like, get the source code, and
|
||||
add your own ideas!
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 505 KiB |
|
|
@ -0,0 +1 @@
|
|||
Stendhal is a multiplayer adventure with classic 2D graphics. It is completely open source.
|
||||
|
|
@ -0,0 +1 @@
|
|||
Stendhal Game
|
||||
|
|
@ -0,0 +1 @@
|
|||
Stendhal es una aventura multijugador con gráficos 2D clásicos. Es completamente de código abierto.
|
||||
|
|
@ -0,0 +1 @@
|
|||
Stendhal est une aventure multijoueur avec des graphismes 2D classiques. C'est complètement open source.
|
||||
|
|
@ -0,0 +1 @@
|
|||
Stendhal è un'avventura multiplayer con la classica grafica 2D. È completamente open source.
|
||||
|
|
@ -0,0 +1 @@
|
|||
Stendhal é uma aventura multijogador com gráficos 2D clássicos. É totalmente de código aberto.
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
|
||||
1.46
|
||||
|
||||
*world*
|
||||
- renamed items:
|
||||
- "courgette" to "zucchini"
|
||||
- "iron" to "iron bar"
|
||||
- "salad" to "lettuce"
|
||||
- fixed many NPCs not responding to certain chat options
|
||||
- normalized spelling of some words to American English in most NPC dialogues
|
||||
- "colour" -> "color"
|
||||
- "defence" -> "defense"
|
||||
- "favour" -> "favor"
|
||||
- "favourite" -> "favorite"
|
||||
- "fulfil" -> "fulfill"
|
||||
- "organise" -> "organize"
|
||||
- "recognise" -> "rocognize"
|
||||
- Orchiwald will stop after entity collision instead of reversing path
|
||||
- foghorn sounds plays when ferry arrives at mainland & island
|
||||
- added commerce sound to more NPCs when exchanging money for items/services
|
||||
- seeds can be used from inventory
|
||||
|
||||
*graphics*
|
||||
- redrawn placeholder tiles in Oni Palace
|
||||
- fixed some outfit errors
|
||||
- disabled unfinished weapon-style attack sprites
|
||||
|
||||
*web client*
|
||||
- improved movement handling with on-screen joystick & direction pad
|
||||
- alternate "floating" menu style
|
||||
- alternate "floating" chat panel style
|
||||
- software keyboard is automatically hidden after sending chat message
|
||||
- optional activity indicator for corpses & some signs
|
||||
- immediate configuration changes affect only the active client/browser tab
|
||||
- application menu dialog doesn't close when clicking on background
|
||||
- correct NPC title is displayed in chat options dialog
|
||||
- disabled highlighting joystick/d-pad button on mouse double-click & drag
|
||||
- joystick/d-pad isn't shown until user interface is ready
|
||||
- character name in stats panel uses default font size
|
||||
- fixed chest default open/close behavior (clicking on open chest opens inventory window instead of closing)
|
||||
- doesn't attempt to open corpse/chest inventory windows when character not in range
|
||||
- fixed chat history duplicates
|
||||
- chat options dialog remains open until NPC is no longer attending or player closes
|
||||
- fixed continuous movement state not always updated at startup
|
||||
- supports displaying members' HP status in group panel
|
||||
- fixed group panel not always showing membership after login
|
||||
- added support for touch drag-and-drop
|
||||
- fixed weather drawing to not appear to move with player
|
||||
- fixed subsequent single clicks on items to not count as double after double click
|
||||
- fixed deathmatch scrying orbs
|
||||
- fixed portal default action when on a collision tile
|
||||
- added autocomplete support
|
||||
- fixed positioning of door sprites (-2_orril_lich_palace 84 108)
|
||||
- optional click/touch indicator
|
||||
- fixed difficult to move small floating windows
|
||||
- supports chat commands tab completion
|
||||
- supports text highlighting in speech bubbles
|
||||
- fixed opening chat log context menu with touch
|
||||
- supports continued zone music when changed zone matches
|
||||
|
||||
*Android*
|
||||
- added option to clear WebView cache
|
||||
- added option to lock orientation
|
||||
- fixes for using the correct software keyboard
|
||||
- app ID changed to conform with F-Droid standards
|
||||
|
|
@ -75,6 +75,7 @@
|
|||
android:background="#00000000"
|
||||
/>
|
||||
|
||||
<!--
|
||||
<Button
|
||||
android:id="@+id/btn_about"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -82,6 +83,7 @@
|
|||
android:text="About"
|
||||
android:background="#00000000"
|
||||
/>
|
||||
-->
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_quit"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@
|
|||
<string name="app_name">Stendhal</string>
|
||||
<string name="intent_url_scheme">stendhalprod8gps5y99pu</string>
|
||||
<string name="build_type">prod</string>
|
||||
<string name="build_version">1.45.5</string>
|
||||
<string name="build_version">1.46</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=91a239400bb638f36a1795d8fdf7939d532cdc7d794d1119b7261aac158b1e60
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
@echo off
|
||||
|
||||
set STENDHAL_VERSION=1.45.5
|
||||
set STENDHAL_VERSION=1.46
|
||||
set SERVER_JAR=stendhal-server-%STENDHAL_VERSION%.jar
|
||||
|
||||
:: change to server directory
|
||||
2
sbin/runserver.sh → bin/runserver.sh
Executable file → Normal file
2
sbin/runserver.sh → bin/runserver.sh
Executable file → Normal file
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
STENDHAL_VERSION="1.45.5"
|
||||
STENDHAL_VERSION="1.46"
|
||||
SERVER_JAR="stendhal-server-${STENDHAL_VERSION}.jar"
|
||||
|
||||
# change to server directory
|
||||
|
|
@ -92,9 +92,9 @@ version_server = http://arianne.sourceforge.net/stendhal.version
|
|||
|
||||
# current version of stendhal
|
||||
version.old = 1.45
|
||||
version = 1.45.5
|
||||
version = 1.46
|
||||
# FIXME: dynamic method to set this property?
|
||||
version.android = 1045005
|
||||
version.android = 1046000
|
||||
|
||||
# javac options
|
||||
javac.deprecation = true
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@
|
|||
|
||||
<copy todir="${buildroot}/stendhal-${version}-src" file="README.md"/>
|
||||
<copy todir="${buildroot}/stendhal-${version}-src" file="LICENSE.txt"/>
|
||||
<copy todir="${buildroot}/stendhal-${version}-src/sbin" file="sbin/runserver.bat"/>
|
||||
<copy todir="${buildroot}/stendhal-${version}-src/sbin" file="sbin/runserver.sh"/>
|
||||
<copy todir="${buildroot}/stendhal-${version}-src/bin" file="bin/runserver.bat"/>
|
||||
<copy todir="${buildroot}/stendhal-${version}-src/bin" file="bin/runserver.sh"/>
|
||||
<copy todir="${buildroot}/stendhal-${version}-src/lib">
|
||||
<fileset dir="libs">
|
||||
<include name="*.txt"/>
|
||||
|
|
@ -359,8 +359,8 @@
|
|||
<copy todir="${buildroot}/stendhal-server-${version}" file="${lib}/${server_jarname}"/>
|
||||
<copy todir="${buildroot}/stendhal-server-${version}" file="${lib}/${maps_jarname}"/>
|
||||
<copy todir="${buildroot}/stendhal-server-${version}" file="${lib}/${xmlconf_jarname}"/>
|
||||
<copy todir="${buildroot}/stendhal-server-${version}" file="sbin/runserver.sh"/>
|
||||
<copy todir="${buildroot}/stendhal-server-${version}" file="sbin/runserver.bat"/>
|
||||
<copy todir="${buildroot}/stendhal-server-${version}" file="bin/runserver.sh"/>
|
||||
<copy todir="${buildroot}/stendhal-server-${version}" file="bin/runserver.bat"/>
|
||||
<copy todir="${buildroot}/stendhal-server-${version}/libs">
|
||||
<fileset dir="libs"/>
|
||||
</copy>
|
||||
|
|
@ -664,6 +664,23 @@
|
|||
|
||||
<!-- START: web client -->
|
||||
|
||||
<target name="js-prepare-contribs">
|
||||
<!-- convert contributors markdown to HTML -->
|
||||
<exec executable="npm${executable.suffix}" failonerror="true">
|
||||
<arg value="install"/>
|
||||
<arg value="showdown"/>
|
||||
<arg value="--no-save"/>
|
||||
</exec>
|
||||
<exec executable="npx${executable.suffix}" failonerror="true">
|
||||
<arg value="showdown"/>
|
||||
<arg value="makehtml"/>
|
||||
<arg value="--input"/>
|
||||
<arg value="doc/contributors.md"/>
|
||||
<arg value="--output"/>
|
||||
<arg value="${srcjs}/contributors.html"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="js-prepare-marauroa">
|
||||
<mkdir dir="build/js"/>
|
||||
<unzip dest="build" src="libs/marauroa.jar">
|
||||
|
|
@ -688,7 +705,7 @@
|
|||
</target>
|
||||
|
||||
|
||||
<extension-point name="js-prepare" depends="js-prepare-marauroa,js-prepare-build,js-prepare-node"/>
|
||||
<extension-point name="js-prepare" depends="js-prepare-contribs,js-prepare-marauroa,js-prepare-build,js-prepare-node"/>
|
||||
|
||||
|
||||
<target name="js-prepare-node">
|
||||
|
|
@ -795,6 +812,7 @@
|
|||
<include name="stendhal-compiled.js"/>
|
||||
<include name="LICENSE.html"/>
|
||||
<include name="favicon.ico"/>
|
||||
<include name="contributors.html"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@
|
|||
match="out.println\("server_version=.*"\);"
|
||||
replace="out.println("server_version=${version}");"
|
||||
byline="true"/>
|
||||
<replaceregexp file="sbin/runserver.bat"
|
||||
<replaceregexp file="bin/runserver.bat"
|
||||
match="STENDHAL_VERSION=.*"
|
||||
replace="STENDHAL_VERSION=${version}"
|
||||
byline="true"/>
|
||||
<replaceregexp file="sbin/runserver.sh"
|
||||
<replaceregexp file="bin/runserver.sh"
|
||||
match="STENDHAL_VERSION ?= ?".*""
|
||||
replace="STENDHAL_VERSION="${version}""
|
||||
byline="true"/>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
site_name: Stendhal 1.45.5 Reference Documentation
|
||||
site_name: Stendhal 1.46 Reference Documentation
|
||||
site_description: A fun, friendly, & free multiplayer online adventure game.
|
||||
copyright: Copyright © 2003-2024 Stendhal
|
||||
site_url: https://stendhalgame.org/
|
||||
|
|
|
|||
|
|
@ -58,7 +58,11 @@ Changelog
|
|||
- fixed difficult to move small floating windows
|
||||
- supports chat commands tab completion
|
||||
- supports text highlighting in speech bubbles
|
||||
- fixed multi-touch support for item inventories
|
||||
- fixed opening chat log context menu with touch
|
||||
- supports continued zone music when changed zone matches
|
||||
|
||||
*desktop client (Java)*
|
||||
- supports continued zone music when changed zone matches
|
||||
|
||||
*desktop client (non-Java)*
|
||||
- experimental desktop interface for the web client using Neutralinojs
|
||||
|
|
@ -72,14 +76,12 @@ Changelog
|
|||
*backend/build*
|
||||
- Android build no longer depends on Marauroa
|
||||
- updated & fixed `runserver` scripts
|
||||
- update converter can handle quest slot sections delimited by commas
|
||||
|
||||
|
||||
1.45
|
||||
*changes*
|
||||
*website*
|
||||
- look and website now show the effective def attribute (the hidden factors have been made transparent)
|
||||
|
||||
|
||||
|
||||
1.45
|
||||
|
||||
*world*
|
||||
|
|
|
|||
|
|
@ -1,4 +1,12 @@
|
|||
|
||||
app/android/client/src/main/res/raw/
|
||||
|
||||
title_01.ogg (Treasure Hunter) Tad Miller (TAD); CC0; https://opengameart.org/node/127124
|
||||
title_02.ogg (Woodland Fantasy) Matthew Pablo; CC BY 3.0; https://opengameart.org/node/31929, https://matthewpablo.com/
|
||||
title_03.ogg (Land of Fearless) Alexandr Zhelanov; CC BY 4.0; https://opengameart.org/node/79931, https://soundcloud.com/alexandr-zhelanov
|
||||
title_04.ogg (Rejoicing) RandomMind; CC0; https://opengameart.org/node/100213
|
||||
title_05.ogg (The Old Tower Inn) RandomMind; CC0; https://opengameart.org/node/87510
|
||||
|
||||
data/music/
|
||||
|
||||
a_weird_place.ogg Storyteller; GPL
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2003-2011 - Stendhal *
|
||||
* (C) Copyright 2003-2024 - Stendhal *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -234,6 +234,20 @@ public class Zone {
|
|||
}
|
||||
}
|
||||
readableName = obj.get("readable_name");
|
||||
|
||||
// *** zone music ***
|
||||
final String music = obj.get("music");
|
||||
float musicVolume = 1.0f;
|
||||
final String mTemp = obj.get("music_volume");
|
||||
try {
|
||||
if (mTemp != null) {
|
||||
musicVolume = Float.parseFloat(mTemp);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
Logger.getLogger(Zone.class).warn("Invalid volume level: " + mTemp, e);
|
||||
}
|
||||
zoneInfo.setSingleGlobalizedMusic(music, musicVolume);
|
||||
|
||||
// OK to try validating after this
|
||||
requireData = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2003-2011 - Stendhal *
|
||||
* (C) Copyright 2003-2024 - Stendhal *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -14,6 +14,10 @@ package games.stendhal.client;
|
|||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
|
||||
import games.stendhal.client.sound.facade.Time;
|
||||
import games.stendhal.client.sound.manager.SoundManagerNG.Sound;
|
||||
import games.stendhal.common.constants.SoundLayer;
|
||||
|
||||
/**
|
||||
* General information about the current zone.
|
||||
*/
|
||||
|
|
@ -28,6 +32,11 @@ public class ZoneInfo {
|
|||
/** Color for the current zone, or <code>null</code>. */
|
||||
private Color color;
|
||||
|
||||
/** Music instance played globally. */
|
||||
private static Sound globalMusic = null;
|
||||
private static final Time fadeTime = new Time(1, Time.Unit.SEC);
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ZoneInfo.
|
||||
*/
|
||||
|
|
@ -109,4 +118,32 @@ public class ZoneInfo {
|
|||
public Color getZoneColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops a sound with uniform volume that continues playing across zone changes.
|
||||
*
|
||||
* Any currently playing instance will be stopped before starting a new one. Also, calling without
|
||||
* parameters will stop current instance if playing.
|
||||
*
|
||||
* @param name
|
||||
* Sound file basename. If value is `null` music will be stopped.
|
||||
* @param volume
|
||||
* Volume level between 0.0 and 1.0.
|
||||
*/
|
||||
public void setSingleGlobalizedMusic(final String musicName, final float volume) {
|
||||
if (ZoneInfo.globalMusic != null && ZoneInfo.globalMusic.getName().equals(musicName)) {
|
||||
// music is already playing so don't restart
|
||||
return;
|
||||
}
|
||||
if (ZoneInfo.globalMusic != null) {
|
||||
// stop previously playing
|
||||
ClientSingletonRepository.getSound().stop(ZoneInfo.globalMusic, ZoneInfo.fadeTime);
|
||||
}
|
||||
ZoneInfo.globalMusic = null;
|
||||
if (musicName != null) {
|
||||
ZoneInfo.globalMusic = (Sound) ClientSingletonRepository.getSound()
|
||||
.getGroup(SoundLayer.BACKGROUND_MUSIC.groupName)
|
||||
.play(musicName, volume, 0, null, ZoneInfo.fadeTime, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id$ */
|
||||
/***************************************************************************
|
||||
* (C) Copyright 2003-2023 - Stendhal *
|
||||
* (C) Copyright 2003-2024 - Stendhal *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -236,4 +236,14 @@ public class SoundFile extends SignalProcessor implements Cloneable {
|
|||
{
|
||||
return mPropagator.request();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves audio resource name.
|
||||
*
|
||||
* @return
|
||||
* Filename of audio resource.
|
||||
*/
|
||||
public String getName() {
|
||||
return mAudioResource.getName();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id$ */
|
||||
/***************************************************************************
|
||||
* (C) Copyright 2003-2010 - Stendhal *
|
||||
* (C) Copyright 2003-2024 - Stendhal *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -87,6 +87,13 @@ public class SoundManagerNG {
|
|||
public void setAttachment(Object obj) {
|
||||
object = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves sound filename (excluding ogg suffix).
|
||||
*/
|
||||
public String getName() {
|
||||
return file.get().getName().replaceAll("\\.ogg$", "");
|
||||
}
|
||||
}
|
||||
|
||||
private final class SoundChannel extends SignalProcessor {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public class Debug {
|
|||
|
||||
/** version. */
|
||||
// Note: This line is updated by build.xml using a regexp so be sure to adjust it in case you modify this line.
|
||||
public static final String VERSION = "1.45.5";
|
||||
public static final String VERSION = "1.46";
|
||||
|
||||
/** pre release suffix */
|
||||
// Note: This line is updated by build.xml using a regexp so be sure to adjust it in case you modify this line.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ package games.stendhal.server.entity.player;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
|
@ -522,62 +523,80 @@ public abstract class UpdateConverter {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts old object names to their new representation with correct grammar and without
|
||||
* underscores.
|
||||
*
|
||||
* @param contents
|
||||
* Value of quest slot section (slots are delimited by semicolon).
|
||||
* @return
|
||||
* Updated value for section.
|
||||
*/
|
||||
private static String updateQuestSection(final String contents) {
|
||||
final EntityManager entityMgr = SingletonRepository.getEntityManager();
|
||||
|
||||
// object names slot section represents (may be delimited by comma to represent multiple
|
||||
// objects in a section)
|
||||
final List<String> names = new LinkedList<>();
|
||||
if (contents.contains(",")) {
|
||||
names.addAll(Arrays.asList(contents.split(",")));
|
||||
} else {
|
||||
names.add(contents);
|
||||
}
|
||||
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
for (int idx = 0; idx < names.size(); idx++) {
|
||||
final String oldName = names.get(idx);
|
||||
String newName = UpdateConverter.updateItemName(oldName);
|
||||
// check for valid item and creature names if the update converter changed the name
|
||||
if (!newName.equals(oldName)) {
|
||||
// some quest slots use key=value pairs
|
||||
String actualNewName = newName;
|
||||
if (newName.contains("=")) {
|
||||
actualNewName = newName.substring(0, newName.indexOf("="));
|
||||
}
|
||||
if (!entityMgr.isCreature(actualNewName) && !entityMgr.isItem(actualNewName)) {
|
||||
// only valid item & creature names can be changed
|
||||
newName = oldName;
|
||||
}
|
||||
}
|
||||
if (buffer.length() > 0) {
|
||||
// reinstate delimiter
|
||||
buffer.append(',');
|
||||
}
|
||||
buffer.append(newName);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the quest slot to the current version.
|
||||
*
|
||||
* @param player
|
||||
* Player instance being updated.
|
||||
*/
|
||||
public static void updateQuests(final Player player) {
|
||||
final EntityManager entityMgr = SingletonRepository.getEntityManager();
|
||||
|
||||
// rename old quest slot "Valo_concoct_potion" to "valo_concoct_potion"
|
||||
// We avoid to lose potion in case there is an entry with the old and the new name at the same
|
||||
// time by combining them by calculating the minimum of the two times and the sum of the two amounts.
|
||||
migrateSumTimedQuestSlot(player, "Valo_concoct_potion", "valo_concoct_potion");
|
||||
|
||||
// From 0.66 to 0.67
|
||||
// update quest slot content,
|
||||
// replace "_" with " ", for item/creature names
|
||||
// 1.46: handle key=value pairs in quest slot strings
|
||||
// From 0.66 to 0.67:
|
||||
// - update quest slot content
|
||||
// - replace "_" with " ", for item/creature names
|
||||
// 1.46:
|
||||
// - handle key=value pairs in quest slot strings
|
||||
// - handle slot sections delimited by ","
|
||||
for (final String questSlot : player.getQuests()) {
|
||||
|
||||
if (player.hasQuest(questSlot)) {
|
||||
final String itemString = player.getQuest(questSlot);
|
||||
|
||||
final String[] parts = itemString.split(";");
|
||||
|
||||
final String[] parts = player.getQuest(questSlot).split(";");
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
boolean first = true;
|
||||
|
||||
for (int i = 0; i < parts.length; ++i) {
|
||||
final String oldName = parts[i];
|
||||
|
||||
// Convert old item names to their new representation with correct grammar
|
||||
// and without underscores.
|
||||
String newName = UpdateConverter.updateItemName(oldName);
|
||||
|
||||
// check for valid item and creature names if the update converter changed the name
|
||||
if (!newName.equals(oldName)) {
|
||||
// some quest slots use key=value pairs
|
||||
String actualNewName = newName;
|
||||
if (newName.contains("=")) {
|
||||
actualNewName = newName.substring(0, newName.indexOf("="));
|
||||
}
|
||||
|
||||
if (!entityMgr.isCreature(actualNewName) && !entityMgr.isItem(actualNewName)) {
|
||||
newName = oldName;
|
||||
}
|
||||
}
|
||||
|
||||
if (first) {
|
||||
buffer.append(newName);
|
||||
first = false;
|
||||
} else {
|
||||
if (buffer.length() > 0) {
|
||||
buffer.append(';');
|
||||
buffer.append(newName);
|
||||
}
|
||||
buffer.append(UpdateConverter.updateQuestSection(parts[i]));
|
||||
}
|
||||
|
||||
player.setQuest(questSlot, buffer.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,6 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* disable double-tap zoom in browsers that support it */
|
||||
html {
|
||||
touch-action: pan-x pan-y; /* manipulation does not work in Chrome */
|
||||
}
|
||||
|
||||
/* disable pull down refresh in browsers that support it */
|
||||
html, body {
|
||||
overscroll-behavior: none;
|
||||
|
|
@ -660,7 +655,8 @@ img#click-indicator {
|
|||
.limitedsize {
|
||||
max-width: 70vw;
|
||||
max-height: 70vh;
|
||||
overflow: scroll;
|
||||
overflow-x: auto;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
|
|
|
|||
|
|
@ -129,11 +129,12 @@
|
|||
</template>
|
||||
|
||||
<template id="aboutdialog-template">
|
||||
<div>
|
||||
<div class="limitedsize">
|
||||
<div class="verticalgroup">
|
||||
<div id="aboutdialog-content">
|
||||
<p>Stendhal is an open source project, written and released under the <a href="https://www.gnu.org/licenses/agpl-3.0.html">GNU AGPL license</a> by the <a href="https://arianne-project.org">Arianne project</a>.
|
||||
<p>Do you want to contribute? Have a look at <a href="/development/introduction.html">Development section</a> to join the <a href="https://github.com/arianne/stendhal/blob/master/doc/contributors.md">List of contributors</a>.
|
||||
<div id="license"></div>
|
||||
<p>Do you want to contribute? Have a look at <a href="/development/introduction.html">Development section</a> to join the list of contributors.
|
||||
<div id="license" class="limitedsize"></div>
|
||||
<div id="contributors" class="limitedsize"></div>
|
||||
</div>
|
||||
<div class="horizontalgroup dialogbuttons">
|
||||
<button id="btn_config_close">Close</button>
|
||||
|
|
@ -278,6 +279,7 @@
|
|||
<label class="checksetting"><input type="checkbox" id="chk_activityindicator">Object activity indicator</label>
|
||||
<label class="checksetting"><input type="checkbox" id="chk_floatchat">Floating chat panel</label>
|
||||
<label class="checksetting"><input type="checkbox" id="chk_hidechat" class="experimental">Auto-hide chat panel</label>
|
||||
<label class="checksetting"><input type="checkbox" id="chk_zoom">Touch zoom</label>
|
||||
</div>
|
||||
<div id="settings_panel2" class="verticalgroup vgroupcol">
|
||||
<label class="checksetting"><input type="checkbox" id="chk_dblclick">Double-click items</label>
|
||||
|
|
|
|||
|
|
@ -506,6 +506,8 @@ export class SoundManager {
|
|||
/**
|
||||
* Stops all currently playing sounds.
|
||||
*
|
||||
* NOTE: this if for map changes & should not include single global music instance
|
||||
*
|
||||
* @param includeGui {boolean}
|
||||
* If `true`, sounds on the gui layer will stopped as well (default: false).
|
||||
* @return {boolean}
|
||||
|
|
@ -541,6 +543,11 @@ export class SoundManager {
|
|||
muted = muted && snd.muted;
|
||||
}
|
||||
}
|
||||
// global music is not tracked in layer array
|
||||
if (this.globalMusic) {
|
||||
this.globalMusic.muted = true;
|
||||
muted = muted && this.globalMusic.muted;
|
||||
}
|
||||
return muted;
|
||||
}
|
||||
|
||||
|
|
@ -558,6 +565,11 @@ export class SoundManager {
|
|||
unmuted = unmuted && !snd.paused && !snd.muted;
|
||||
}
|
||||
}
|
||||
// global music is not tracked in layer array
|
||||
if (this.globalMusic) {
|
||||
this.globalMusic.muted = false;
|
||||
unmuted = unmuted && !this.globalMusic.paused && !this.globalMusic.muted;
|
||||
}
|
||||
return unmuted;
|
||||
}
|
||||
|
||||
|
|
@ -680,6 +692,10 @@ export class SoundManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
// global music is not tracked in layer array
|
||||
if (this.globalMusic && (layerName === "music" || layerName === "master")) {
|
||||
this.applyAdjustedVolume(layerName, this.globalMusic);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ export class ViewPort {
|
|||
(ui.get(UIComponentEnum.PlayerEquipment) as PlayerEquipmentComponent).update();
|
||||
}
|
||||
}
|
||||
setTimeout(function() {
|
||||
window.setTimeout(function() {
|
||||
stendhal.ui.gamewindow.draw.apply(stendhal.ui.gamewindow, arguments);
|
||||
}, Math.max((1000/20) - (new Date().getTime()-startTime), 1));
|
||||
}
|
||||
|
|
@ -174,10 +174,10 @@ export class ViewPort {
|
|||
* FIXME:
|
||||
* - colors are wrong
|
||||
* - doesn't support "blend" layers
|
||||
* - very slow
|
||||
*/
|
||||
applyFilter() {
|
||||
if (this.filter && stendhal.config.getBoolean("effect.lighting")) {
|
||||
// FIXME: wrong colors
|
||||
this.ctx.filter = this.filter;
|
||||
}
|
||||
}
|
||||
|
|
@ -755,7 +755,7 @@ export class ViewPort {
|
|||
joystickButton.update();
|
||||
}
|
||||
|
||||
if (!stendhal.config.getBoolean("joystick")) {
|
||||
if (!stendhal.session.joystickEnabled()) {
|
||||
this.removeJoystick();
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,16 @@ export class ChatLogComponent extends Component {
|
|||
this.componentElement.addEventListener("mouseup", (evt: MouseEvent) => {
|
||||
this.onContextMenu(evt)
|
||||
});
|
||||
this.componentElement.addEventListener("touchstart", (evt: TouchEvent) => {
|
||||
const pos = stendhal.ui.html.extractPosition(evt);
|
||||
stendhal.ui.touch.onTouchStart(pos.pageX, pos.pageY);
|
||||
});
|
||||
this.componentElement.addEventListener("touchend", (evt: TouchEvent) => {
|
||||
stendhal.ui.touch.onTouchEnd();
|
||||
this.onContextMenu(evt)
|
||||
// clean up
|
||||
stendhal.ui.touch.unsetOrigin();
|
||||
});
|
||||
|
||||
this.scrollListener = (evt: Event) => {
|
||||
this.onScroll();
|
||||
|
|
@ -439,9 +449,21 @@ export class ChatLogComponent extends Component {
|
|||
|
||||
/**
|
||||
* Handles creating a custom context menu with options "Clear" & "Copy".
|
||||
*
|
||||
* FIXME: text highlighting interferes with opening context menu with touch
|
||||
*
|
||||
* @param evt {any}
|
||||
* Mouse or touch event.
|
||||
*/
|
||||
private onContextMenu(evt: MouseEvent) {
|
||||
if (!evt || evt.button != 2 || stendhal.ui.actionContextMenu.isOpen()) {
|
||||
private onContextMenu(evt: any) {
|
||||
if (!evt || stendhal.ui.actionContextMenu.isOpen()) {
|
||||
return;
|
||||
}
|
||||
if (evt.type === "mouseup" && evt.button != 2) {
|
||||
return;
|
||||
}
|
||||
if (evt.type === "touchend" && !stendhal.ui.touch.isLongTouch(evt)) {
|
||||
evt.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -298,9 +298,6 @@ export class ItemContainerImplementation {
|
|||
}
|
||||
}
|
||||
|
||||
// clean up item held via touch
|
||||
stendhal.ui.touch.setHolding(false);
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
|
@ -338,10 +335,10 @@ export class ItemContainerImplementation {
|
|||
}
|
||||
|
||||
// workaround to prevent accidentally using items when disengaging joystick
|
||||
// no longer needed after fixing multi-touch support (tested on Windows touch-enabled device)
|
||||
//~ if (stendhal.ui.gamewindow.joystick && stendhal.ui.gamewindow.joystick.isEngaged()) {
|
||||
//~ return;
|
||||
//~ }
|
||||
// FIXME: a global solution would be better
|
||||
if (stendhal.ui.gamewindow.joystick && stendhal.ui.gamewindow.joystick.isEngaged()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let event = stendhal.ui.html.extractPosition(evt);
|
||||
if ((event.target as any).dataItem) {
|
||||
|
|
@ -401,23 +398,19 @@ export class ItemContainerImplementation {
|
|||
}
|
||||
|
||||
private onTouchStart(evt: TouchEvent) {
|
||||
// prevent default "mousedown" so we can call its handler manually
|
||||
evt.preventDefault();
|
||||
|
||||
const pos = stendhal.ui.html.extractPosition(evt);
|
||||
stendhal.ui.touch.onTouchStart(pos.pageX, pos.pageY);
|
||||
this.onMouseDown(evt);
|
||||
}
|
||||
|
||||
private onTouchEnd(evt: TouchEvent) {
|
||||
// prevent default "mouseup" so we can call its handler manually
|
||||
evt.preventDefault();
|
||||
|
||||
stendhal.ui.touch.onTouchEnd();
|
||||
if (stendhal.ui.touch.holding()) {
|
||||
this.onDrop(evt);
|
||||
} else {
|
||||
if (stendhal.ui.touch.isLongTouch(evt) && !stendhal.ui.touch.holding()) {
|
||||
this.onMouseUp(evt);
|
||||
} else if (stendhal.ui.touch.holding()) {
|
||||
evt.preventDefault();
|
||||
|
||||
this.onDrop(evt);
|
||||
stendhal.ui.touch.setHolding(false);
|
||||
}
|
||||
// clean up touch handler
|
||||
stendhal.ui.touch.unsetOrigin();
|
||||
|
|
@ -433,6 +426,11 @@ export class ItemContainerImplementation {
|
|||
*/
|
||||
private updateCursor(target: HTMLElement, item?: Item) {
|
||||
if (item) {
|
||||
if (this.slot === "content" && stendhal.config.getBoolean("inventory.quick-pickup")) {
|
||||
target.style.cursor = "url(" + stendhal.paths.sprites
|
||||
+ "/cursor/itempickupfromslot.png) 1 3, auto";
|
||||
return;
|
||||
}
|
||||
target.style.cursor = item.getCursor(0, 0);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
***************************************************************************/
|
||||
|
||||
import { DialogContentComponent } from "../toolkit/DialogContentComponent";
|
||||
import { Panel } from "../toolkit/Panel";
|
||||
import { TabPanelComponent } from "../toolkit/TabPanelComponent";
|
||||
|
||||
|
||||
export class AboutDialog extends DialogContentComponent {
|
||||
|
|
@ -19,6 +21,16 @@ export class AboutDialog extends DialogContentComponent {
|
|||
this.child("#btn_config_close")!.addEventListener("click", () => {
|
||||
this.close();
|
||||
});
|
||||
|
||||
const tabs = new TabPanelComponent();
|
||||
tabs.addTab("License");
|
||||
const licenseTab = new Panel(this.child("#license")!);
|
||||
tabs.add(licenseTab);
|
||||
tabs.addTab("Contributors");
|
||||
const contribsTab = new Panel(this.child("#contributors")!);
|
||||
tabs.add(contribsTab);
|
||||
this.child("#aboutdialog-content")!.appendChild(tabs.componentElement);
|
||||
|
||||
this.load();
|
||||
}
|
||||
|
||||
|
|
@ -26,6 +38,10 @@ export class AboutDialog extends DialogContentComponent {
|
|||
let response = await fetch("LICENSE.html");
|
||||
let content = await response.text();
|
||||
this.child("#license")!.innerHTML = content;
|
||||
|
||||
let response2 = await fetch("contributors.html");
|
||||
let content2 = await response2.text();
|
||||
this.child("#contributors")!.innerHTML = content2;
|
||||
}
|
||||
|
||||
public override getConfigId(): string {
|
||||
|
|
|
|||
|
|
@ -102,6 +102,14 @@ export class SettingsDialog extends DialogContentComponent {
|
|||
this.createCheckBox("chk_hidechat", "chat.autohide",
|
||||
"Chat panel will be hidden after sending text", "Chat panel will remain on-screen");
|
||||
|
||||
// FIXME: are there unique properties for pinch & tap zooming?
|
||||
this.createCheckBox("chk_zoom", "zoom.touch",
|
||||
"Touch zooming enabled (may not work with all browsers)",
|
||||
"Touch zooming disabled (may not work with all browsers)",
|
||||
function() {
|
||||
stendhal.session.update();
|
||||
});
|
||||
|
||||
|
||||
/* *** center panel *** */
|
||||
|
||||
|
|
@ -234,6 +242,7 @@ export class SettingsDialog extends DialogContentComponent {
|
|||
sel_joystick.disabled = !chk_joystick.checked;
|
||||
stendhal.ui.gamewindow.updateJoystick();
|
||||
});
|
||||
chk_joystick.checked = stendhal.session.joystickEnabled();
|
||||
sel_joystick.disabled = !chk_joystick.checked;
|
||||
|
||||
// joystck positioning
|
||||
|
|
|
|||
|
|
@ -22,10 +22,24 @@ export abstract class Component {
|
|||
private visibleDisplay: string;
|
||||
|
||||
|
||||
constructor(id: string, themable=false) {
|
||||
let element = document.getElementById(id);
|
||||
if (!element) {
|
||||
throw new Error("Cannot create component because there is no HTML element with id " + id);
|
||||
/**
|
||||
* Creates a new component.
|
||||
*
|
||||
* @param el
|
||||
* DOM element or ID of HTML element or template.
|
||||
* @param themable
|
||||
* Inherits theming visuals (default: `false`).
|
||||
*/
|
||||
constructor(el: string|HTMLElement, themable=false) {
|
||||
let element: HTMLElement|null;
|
||||
if (typeof(el) === "string") {
|
||||
const id = el as string;
|
||||
element = document.getElementById(id);
|
||||
if (!element) {
|
||||
throw new Error("Cannot create component because there is no HTML element with id " + id);
|
||||
}
|
||||
} else {
|
||||
element = el as HTMLElement;
|
||||
}
|
||||
|
||||
if (element instanceof HTMLTemplateElement) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2015-2023 - Faiumoni e. V. *
|
||||
* (C) Copyright 2015-2024 - Faiumoni e. V. *
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
|
@ -20,13 +20,15 @@ export class Panel extends Component {
|
|||
protected children: Component[] = [];
|
||||
|
||||
/**
|
||||
* creates a new panel
|
||||
* Creates a new panel.
|
||||
*
|
||||
* @param id id of HTML element or template
|
||||
* @param el
|
||||
* DOM element or ID of HTML element or template.
|
||||
* @param themable
|
||||
* Inherits theming visuals (default: `false`).
|
||||
*/
|
||||
constructor(id: string, themable=false) {
|
||||
super(id, themable);
|
||||
constructor(el: string|HTMLElement, themable=false) {
|
||||
super(el, themable);
|
||||
this.containerElement = this.componentElement;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,8 @@ export class ConfigManager {
|
|||
"window.settings": "20,20",
|
||||
"window.shortcuts": "20,20",
|
||||
"window.trade": "200,100",
|
||||
"window.travel-log": "160,50"
|
||||
"window.travel-log": "160,50",
|
||||
"zoom.touch": "false"
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -265,6 +266,18 @@ export class ConfigManager {
|
|||
return Object.keys(this.defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a key has been changed from the default value.
|
||||
*
|
||||
* @param key {string}
|
||||
* `string` identifier.
|
||||
* @return {boolean}
|
||||
* `true` if key is found in local storage.
|
||||
*/
|
||||
isSet(key: string): boolean {
|
||||
return window.localStorage.getItem("client." + key) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a configuration setting.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -75,6 +75,8 @@ export class SessionManager {
|
|||
}
|
||||
this.set(key, value);
|
||||
}
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -175,6 +177,19 @@ export class SessionManager {
|
|||
return this.charname || "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs inteface with updated settings.
|
||||
*/
|
||||
update() {
|
||||
if (stendhal.config.getBoolean("zoom.touch")) {
|
||||
document.documentElement.style.removeProperty("touch-action");
|
||||
} else {
|
||||
// disable double-tap zoom in browsers that support it
|
||||
// NOTE: "manipulation" does not work in Chrome
|
||||
document.documentElement.style.setProperty("touch-action", "pan-x pan-y");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects if test client is being used based on data path.
|
||||
*
|
||||
|
|
@ -196,4 +211,18 @@ export class SessionManager {
|
|||
isServerDefault(): boolean {
|
||||
return this.server_default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if joystick/direction pad should be visible.
|
||||
*
|
||||
* @return {boolean}
|
||||
* `true` if joystick property has been enabled manually or if no pointer device is detected.
|
||||
*/
|
||||
joystickEnabled(): boolean {
|
||||
if (!stendhal.config.isSet("joystick") && !window.matchMedia("(pointer: fine)").matches) {
|
||||
// display by default if a pointer device is not detected from the system
|
||||
return true;
|
||||
}
|
||||
return stendhal.config.getBoolean("joystick");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue