Compare commits

...
Sign in to create a new pull request.

25 commits

Author SHA1 Message Date
Jordan Irwin
785675f13d Show joystick/d-pad by default if pointer device is not detected
Some checks failed
Java CI / build (push) Has been cancelled
2024-04-20 23:59:14 +02:00
Jordan Irwin
2e9ade5a23 Add option to config manager to check if a key value is set 2024-04-20 23:54:42 +02:00
Jordan Irwin
b8359f3a81
Add Gradle wrapper SHA-256 checksum info recommend by F-Droid
https://gitlab.com/fdroid/fdroiddata/-/merge_requests/14774#note_1837005543
2024-04-04 01:39:26 -07:00
Jordan Irwin
1ff055b2f0
Update description for F-Droid 2024-04-04 01:24:04 -07:00
Jordan Irwin
ab5a10400a
Add Android meta data for F-Droid 2024-03-30 16:29:28 -07:00
Jordan Irwin
c8eb546590
Fix changes 2024-03-26 19:14:56 -07:00
Jordan Irwin
14fa450dfd
Add support for single globalized zone music to Java client
Doesn't restart if changed zone uses same music.
2024-03-26 19:07:03 -07:00
Jordan Irwin
8241fc9686
Fix changes 2024-03-26 19:06:46 -07:00
Hendrik Brummermann
328ec57136
fixed compiler error 2024-03-24 16:30:24 -07:00
Jordan Irwin
92da86aef6
Update changes 2024-03-21 15:03:31 -07:00
Jordan Irwin
6e3cb4b3bd
Fix update converter to handle quest slot sections containing...
...multiple object names delimited by commas

https://github.com/arianne/stendhal/issues/691
2024-03-21 15:01:35 -07:00
Jordan Irwin
423f94f25e Move sbin scripts to bin
https://github.com/arianne/stendhal/issues/628
2024-03-19 20:22:11 +01:00
Jordan Irwin
010375d6d5 Change Eclipse's build output directory to build/eclipse
https://github.com/arianne/stendhal/issues/628
2024-03-19 20:19:54 +01:00
Jordan Irwin
17864b85c7
Add tab to about dialog to display contributor information
https://github.com/arianne/stendhal/issues/651
2024-03-18 22:04:22 -07:00
Jordan Irwin
ba585d7a91
Allow passing element to Component & Panel constructors 2024-03-18 22:04:01 -07:00
Jordan Irwin
a68991e38b
Convert contributors.md to HTML for use in web client 2024-03-18 22:03:48 -07:00
Jordan Irwin
e56d8680d9
Disable Android built-in about dialog
Web client now has about dialog.
2024-03-18 12:53:29 -07:00
Jordan Irwin
68f21d5eeb
Support opening chat log context menu with touch
Closes: https://github.com/arianne/stendhal/issues/603
2024-03-18 03:34:52 -07:00
Jordan Irwin
8af5ae1bbb
Add option to enable/disable pinch & double-tap zoom
Closes: https://github.com/arianne/stendhal/issues/687
2024-03-18 03:07:04 -07:00
Jordan Irwin
22fa54ab6a
Fix controlling mute & volume level of single global music instance
Closes: https://github.com/arianne/stendhal/issues/688
2024-03-18 01:32:27 -07:00
Jordan Irwin
6b57ebe3f8
Update changes 2024-03-17 00:52:08 -07:00
Jordan Irwin
f1523798c7
Fix redundant check 2024-03-17 00:38:18 -07:00
Jordan Irwin
4fb31e2a7d
Revert "Fix multi-touch support in item inventories"
This reverts commit 1551389c75.
2024-03-17 00:38:04 -07:00
Jordan Irwin
0b619f9d8c
Fix corpse & chest cursor when quick pickup enabled
Closes: https://github.com/arianne/stendhal/issues/601
2024-03-16 18:37:54 -07:00
Hendrik Brummermann
edf4297854 updated version 2024-03-15 19:51:55 +01:00
55 changed files with 431 additions and 110 deletions

View file

@ -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
View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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() {

View file

@ -0,0 +1 @@
https://sourceforge.net/projects/arianne/support

View file

@ -0,0 +1 @@
https://stendhalgame.org/

View file

@ -0,0 +1 @@
en-US

View file

@ -0,0 +1 @@
Stendhal ist ein Multiplayer-Adventure mit klassischer 2D-Grafik. Es ist vollständig Open Source.

View file

@ -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

View file

@ -0,0 +1 @@
Stendhal is a multiplayer adventure with classic 2D graphics. It is completely open source.

View file

@ -0,0 +1 @@
Stendhal Game

View file

@ -0,0 +1 @@
Stendhal es una aventura multijugador con gráficos 2D clásicos. Es completamente de código abierto.

View file

@ -0,0 +1 @@
Stendhal est une aventure multijoueur avec des graphismes 2D classiques. C'est complètement open source.

View file

@ -0,0 +1 @@
Stendhal è un'avventura multiplayer con la classica grafica 2D. È completamente open source.

View file

@ -0,0 +1 @@
Stendhal é uma aventura multijogador com gráficos 2D clássicos. É totalmente de código aberto.

View file

@ -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

View file

@ -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"

View file

@ -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>

View file

@ -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

View file

@ -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
View 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

View file

@ -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

View file

@ -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>

View file

@ -14,11 +14,11 @@
match="out.println\(&quot;server_version=.*&quot;\);"
replace="out.println(&quot;server_version=${version}&quot;);"
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 ?= ?&quot;.*&quot;"
replace="STENDHAL_VERSION=&quot;${version}&quot;"
byline="true"/>

View file

@ -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/

View file

@ -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*

View file

@ -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

View file

@ -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;
}

View file

@ -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);
}
}
}

View file

@ -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();
}
}

View file

@ -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 {

View file

@ -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.

View file

@ -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());
}
}

View file

@ -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 {

View file

@ -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>

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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 {

View file

@ -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

View file

@ -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) {

View file

@ -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;
}

View file

@ -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.
*

View file

@ -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");
}
}