Compare commits
199 commits
VERSION_01
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fcd8330db0 | ||
|
|
98864f3802 | ||
|
|
0dff60f98e | ||
|
|
246d9ce288 | ||
|
|
31d417e31f | ||
|
|
60d20f593b | ||
|
|
f44e519104 | ||
|
|
70dc2ded31 | ||
|
|
542f4524db | ||
|
|
0d25beefa8 | ||
|
|
3a478f341d | ||
|
|
c9f865a894 | ||
|
|
afd5329fcc | ||
|
|
b8edcfb252 | ||
|
|
bebce66517 | ||
|
|
6f58eef4f5 | ||
|
|
4d2925aa4b | ||
|
|
fb2ae76fc5 | ||
|
|
aadec09b5d | ||
|
|
9fd4316d0f | ||
|
|
e1d01dea79 | ||
|
|
dd500a36e5 | ||
|
|
8b2727f392 | ||
|
|
d350c2b494 | ||
|
|
2022b28b76 | ||
|
|
1f9242ae6f | ||
|
|
03654e4459 | ||
|
|
fcadfcdbd3 | ||
|
|
581ffc886a | ||
|
|
e2146721d1 | ||
|
|
c6a51ffcf3 | ||
|
|
d846fa5818 | ||
|
|
13fc7f6b1a | ||
|
|
86cf9c0959 | ||
|
|
7c5cef1181 | ||
|
|
72f23a7bc1 | ||
|
|
404263a1ef | ||
|
|
b479ec3d52 | ||
|
|
b796ba36b0 | ||
|
|
07a41fddfe | ||
|
|
97ea5ab442 | ||
|
|
659c155a36 | ||
|
|
0f3ecbd3dd | ||
|
|
535e7f5727 | ||
|
|
1bf34316fb | ||
|
|
c7befd2fe1 | ||
|
|
230b25e5fa | ||
|
|
3b6d652aa8 | ||
|
|
41604ca00e | ||
|
|
7e0fbe0f16 | ||
|
|
2bd16f0307 | ||
|
|
afb06b8f97 | ||
|
|
95f373bd1c | ||
|
|
e58e6a54cb | ||
|
|
f109b551f5 | ||
|
|
5f4d9d9460 | ||
|
|
61f047a955 | ||
|
|
3534bf384f | ||
|
|
6b1296e059 | ||
|
|
c19e4b0627 | ||
|
|
72d569343a | ||
|
|
a6708ee0c2 | ||
|
|
e0dce1a242 | ||
|
|
55e802b988 | ||
|
|
d24e452f59 | ||
|
|
8fc173d923 | ||
|
|
1484f872da | ||
|
|
93a99c9c10 | ||
|
|
79ba39a030 | ||
|
|
1c50a2a454 | ||
|
|
4feb1e628a | ||
|
|
662aab6ded | ||
|
|
f9fc0230f5 | ||
|
|
ba6d507924 | ||
|
|
e121d44356 | ||
|
|
8b61de02e6 | ||
|
|
1ca1f0e47e | ||
|
|
3026afe931 | ||
|
|
f9a37f122e | ||
|
|
fd2cff8618 | ||
|
|
30494af57c | ||
|
|
2ed431fd6a | ||
|
|
cc4918a5ed | ||
|
|
6608eb2b02 | ||
|
|
79622ee9cf | ||
|
|
c6f2718aec | ||
|
|
1fd97009eb | ||
|
|
517b62c5b1 | ||
|
|
de36580350 | ||
|
|
3d971f37b5 | ||
|
|
4666911be6 | ||
|
|
c4723aba93 | ||
|
|
8c93122d1e | ||
|
|
2bec3a151b | ||
|
|
38f5c0124d | ||
|
|
2df3243f2d | ||
|
|
08873546ba | ||
|
|
26c4723749 | ||
|
|
6eeff4766d | ||
|
|
737cac9495 | ||
|
|
5ae5d33438 | ||
|
|
621a43579a | ||
|
|
45cd2ac30e | ||
|
|
b328b1aedf | ||
|
|
d633ebf947 | ||
|
|
f4935f4928 | ||
|
|
b71a29f883 | ||
|
|
3424b898b8 | ||
|
|
1f3abca39c | ||
|
|
d6ca574a20 | ||
|
|
612b4a6b88 | ||
|
|
a13ee36fe8 | ||
|
|
2abc8df666 | ||
|
|
14d7e046be | ||
|
|
6c64621496 | ||
|
|
6a4009c790 | ||
|
|
38934a8c09 | ||
|
|
738d3cd830 | ||
|
|
8cb1a7b050 | ||
|
|
d1fc6947b7 | ||
|
|
402bb84c43 | ||
|
|
819b80913f | ||
|
|
da4378d30c | ||
|
|
37d3e1c84d | ||
|
|
f1d98fff56 | ||
|
|
8f642ac446 | ||
|
|
6224a0638a | ||
|
|
c38740eaab | ||
|
|
cbf971e632 | ||
|
|
7546fbba80 | ||
|
|
face9f3a67 | ||
|
|
703fa61329 | ||
|
|
4dbe1f73fe | ||
|
|
09371bff47 | ||
|
|
6ff59a0040 | ||
|
|
063d03c45f | ||
|
|
d191c14232 | ||
|
|
d9b51f0d15 | ||
|
|
44f6a4a9fe | ||
|
|
d1d4eb5c49 | ||
|
|
0d56d2b63b | ||
|
|
a000e5f788 | ||
|
|
cc5414894f | ||
|
|
2e5dbc12c6 | ||
|
|
f756534846 | ||
|
|
7174c32521 | ||
|
|
049b91e98b | ||
|
|
a5db37305e | ||
|
|
179bc4d5e7 | ||
|
|
31c4f9cfb4 | ||
|
|
c4491004d2 | ||
|
|
e910892a16 | ||
|
|
7beb123117 | ||
|
|
a141cc187d | ||
|
|
c68f0a59d5 | ||
|
|
a3bd4b328a | ||
|
|
9e56945faf | ||
|
|
6f783d3ef6 | ||
|
|
ccee5a42b3 | ||
|
|
f2d519a29f | ||
|
|
d516c738bf | ||
|
|
ad92b7f2a9 | ||
|
|
2ee0aaa5e7 | ||
|
|
6592f5c245 | ||
|
|
8206631665 | ||
|
|
bdb34e8628 | ||
|
|
0fba46d89b | ||
|
|
4a55c4a706 | ||
|
|
4253e1e73b | ||
|
|
4e8fe0592e | ||
|
|
5709a85824 | ||
|
|
700e3ee730 | ||
|
|
0b2cb9df08 | ||
|
|
63d9667264 | ||
|
|
920ed5a3a2 | ||
|
|
f02fc6b04f | ||
|
|
807a8bb40a | ||
|
|
e6180e9ff5 | ||
|
|
3de1141898 | ||
|
|
3e31e6b788 | ||
|
|
ff9fb76ab3 | ||
|
|
ccb229efe9 | ||
|
|
5f3f86c6e7 | ||
|
|
42c30cdbda | ||
|
|
01dddc103f | ||
|
|
70bcbc3066 | ||
|
|
3c7b1a30ae | ||
|
|
e82524ec2f | ||
|
|
f224b79094 | ||
|
|
a7e66a4288 | ||
|
|
79e882fe5f | ||
|
|
8b63897d37 | ||
|
|
a24774cda9 | ||
|
|
2746ee1411 | ||
|
|
962bd11aec | ||
|
|
a9ae0db9a9 | ||
|
|
06f4e5eb78 | ||
|
|
ade5f226a9 | ||
|
|
d2f549394d |
260 changed files with 8129 additions and 8425 deletions
50
.github/workflows/android-build.yml
vendored
50
.github/workflows/android-build.yml
vendored
|
|
@ -7,16 +7,56 @@ on:
|
|||
pull_request:
|
||||
paths:
|
||||
- 'app/android/**'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- id: job_info
|
||||
uses: daleyjem/gh-job-id@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
job_name: 'build'
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Build Android Packages
|
||||
run: cd app/android/client && gradle assemble
|
||||
- name: Set Up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'adopt'
|
||||
|
||||
- name: Validate Gradle Wrapper .jar
|
||||
run: |
|
||||
cd app/android/gradle/wrapper
|
||||
curl --location --output gradle-wrapper.jar.sha256 \
|
||||
https://services.gradle.org/distributions/gradle-7.5.1-wrapper.jar.sha256
|
||||
echo " gradle-wrapper.jar" >> gradle-wrapper.jar.sha256
|
||||
sha256sum --check gradle-wrapper.jar.sha256
|
||||
|
||||
- name: Build APKs with Ant
|
||||
uses: cedx/setup-ant@v6
|
||||
with:
|
||||
version: '1.10'
|
||||
- run: ant -noinput -buildfile build.xml android -Dgradle.params="assembleDebug assembleRelease"
|
||||
|
||||
- name: Failure Report
|
||||
uses: sarisia/actions-status-discord@v1
|
||||
if: failure()
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_DEVELOPMENT }}
|
||||
with:
|
||||
title: 'Android Build Failed'
|
||||
description: '${{ steps.job_info.outputs.html_url }}'
|
||||
nodetail: true
|
||||
- uses: sarisia/actions-status-discord@v1
|
||||
if: failure()
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_DEVLOG }}
|
||||
with:
|
||||
title: 'Android Build Failed'
|
||||
description: '${{ steps.job_info.outputs.html_url }}'
|
||||
nodetail: true
|
||||
|
|
|
|||
12
.github/workflows/codeql-analysis.yml
vendored
12
.github/workflows/codeql-analysis.yml
vendored
|
|
@ -29,15 +29,15 @@ jobs:
|
|||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
# with:
|
||||
# languages: go, javascript, csharp, python, cpp, java
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
#- name: Autobuild
|
||||
# uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
|
@ -46,9 +46,7 @@ jobs:
|
|||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
- run: ant -noinput -f build.xml clean compile
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
|
|
|||
11
.project
11
.project
|
|
@ -20,4 +20,15 @@
|
|||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
|
||||
</natures>
|
||||
<filteredResources>
|
||||
<filter>
|
||||
<id>1771748271774</id>
|
||||
<name></name>
|
||||
<type>30</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.core.resources.regexFilterMatcher</id>
|
||||
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
</filteredResources>
|
||||
</projectDescription>
|
||||
|
|
|
|||
19
README.md
19
README.md
|
|
@ -30,29 +30,28 @@ button to create or log in to your account.
|
|||
### Mobile
|
||||
|
||||
Play using the [progressive web app](https://en.wikipedia.org/wiki/Progressive_web_app). Just visit
|
||||
https://stendhalgame.org/ in your mobile browser and click "install" when prompted.
|
||||
[stendhalgame.org](https://stendhalgame.org/) in your mobile browser and click "install" when prompted.
|
||||
|
||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" height="75">](https://f-droid.org/packages/org.stendhalgame.client/)
|
||||
|
||||
Play on your Android device using the dedicated app. You can get it from the
|
||||
[F-Droid App Store](https://f-droid.org/) or download it from https://stendhalgame.org/download.html.
|
||||
[F-Droid App Store](https://f-droid.org/) or download it from [stendhalgame.org](https://stendhalgame.org/download.html).
|
||||
|
||||
### Classic Desktop
|
||||
|
||||
[](https://arianne-project.org/download/stendhal.zip)
|
||||
|
||||
Play using the classic desktop client. You will need Java which you can download from
|
||||
[https://www.java.com](https://www.java.com/en/download) on Microsoft Windows. Java is included in
|
||||
[java.com](https://www.java.com/en/download) on Microsoft Windows. Java is included in
|
||||
most Linux distributions. Both Oracle Java and OpenJDK are supported.
|
||||
|
||||
Please download Stendhal from [https://stendhalgame.org](https://stendhalgame.org)<br>
|
||||
You can double click on stendhal-starter.jar and the client will run.<br>
|
||||
If you prefer to run from command line, then just execute this command
|
||||
in the stendhal folder:
|
||||
Please download Stendhal from [stendhalgame.org](https://stendhalgame.org/download.html).<br>
|
||||
You can double click on `stendhal-starter.jar` and the client will run.<br>
|
||||
If you prefer to run from command line, then just execute this command in the stendhal folder:
|
||||
|
||||
`java -jar stendhal-starter.jar`
|
||||
|
||||
There is a [manual](https://stendhalgame.org/wiki/Stendhal_Manual), and there is Help from the client menu icons in the upper right hand side of the game screen.
|
||||
There is a [manual](https://stendhalgame.org/wiki/Stendhal_Manual), and there is Help from the client menu icons in the upper right hand side of the game screen.
|
||||
|
||||
|
||||
## Development environment
|
||||
|
|
@ -67,7 +66,7 @@ There is a [manual](https://stendhalgame.org/wiki/Stendhal_Manual), and there i
|
|||
|
||||
Stendhal is free software. You can redistribute it and/or modify under the following terms:
|
||||
|
||||
- The **server**, **java client**, and **Android client**: *GNU General Public License* 2 or later as published by the Free
|
||||
- The **server**, **java client**, and **Android client**: *GNU General Public License* 2 or later as published by the Free Software Foundation
|
||||
- The **web client** and **native client**: *GNU Affero General Public License* 3 or later as published by the Free Software Foundation with the definition of "System libraries" being extended to include authentication providers and software distribution platforms.
|
||||
- The **nativehelper** extensions: *GNU Lesser General Public License* 3 or later as published by the Free Software Foundation
|
||||
|
||||
|
|
@ -76,6 +75,6 @@ even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
|
|||
[LICENSE.txt](LICENSE.txt) and [src/js/LICENSE.html](src/js/LICENSE.html) file for more details.
|
||||
|
||||
Stendhal(c) is copyright of Miguel Angel Blanch Lardin, 2005-2008, arianne_rpg at users dot sourceforge dot net and others<br>
|
||||
Stendhal(c) is copyright of the Arianne Project, 2006-2024, arianne-general at lists dot sourceforge dot net
|
||||
Stendhal(c) is copyright of the Arianne Project, 2006-2026, arianne-general at lists dot sourceforge dot net
|
||||
|
||||
Please have a look at the list of [contributors](doc/contributors.md#contributors).
|
||||
|
|
|
|||
1
app/.gitignore
vendored
Normal file
1
app/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/godot/
|
||||
|
|
@ -10,8 +10,8 @@ android {
|
|||
applicationId namespace
|
||||
minSdk 21
|
||||
targetSdk 32
|
||||
versionCode 1048000
|
||||
versionName "1.48"
|
||||
versionCode 1049005
|
||||
versionName "1.49.5"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
targetSdkVersion 32
|
||||
minSdkVersion 21
|
||||
|
|
@ -26,7 +26,7 @@ android {
|
|||
}
|
||||
|
||||
// build output
|
||||
project.setProperty("archivesBaseName", "${namespace}-${defaultConfig.versionCode}")
|
||||
project.setProperty("archivesBaseName", "${namespace}-${defaultConfig.versionName}")
|
||||
project.setProperty("buildDir", "${projectDir}/../../../build/build_android_client")
|
||||
|
||||
/* A keystore.properties file can be placed in the root Android project directory and must
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ package org.stendhalgame.client;
|
|||
import java.util.Random;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
|
|
@ -189,7 +190,11 @@ public class ClientView extends WebView {
|
|||
if (!UrlHelper.isInternalUri(uri)) {
|
||||
// open external links in default browser/app
|
||||
// FIXME: should we ask for confirmation?
|
||||
MainActivity.get().startActivity(new Intent(Intent.ACTION_VIEW, uri));
|
||||
try {
|
||||
MainActivity.get().startActivity(new Intent(Intent.ACTION_VIEW, uri));
|
||||
} catch (final ActivityNotFoundException e) {
|
||||
Notifier.toast("No app found to open this link");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
view.loadUrl(UrlHelper.checkClientUrl(uri.toString()));
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 335 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 647 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 597 KiB |
|
|
@ -1,7 +1,3 @@
|
|||
The world has just gotten a little fancier. You may notice that the clouds have cleared in Kikareukin, revealing a beautiful view of Semos below.
|
||||
|
||||
If luck has it, you may find a rare four-leaf clover. Keep your eyes peeled, they pop up in random locations that receive sunshine. Clover hunters will reward generously for such valuable trinkets.
|
||||
|
||||
Jef is still eager to hear from his mother, Amber. But don't expect to find her on her usual route as she has taken to wandering off the beaten path. Speaking of wandering, some creatures have become more unpredictable in their behavior. Be careful, as you may encounter them in unexpected places.
|
||||
PUT RELEASE ANNOUNCEMENT LINES HERE
|
||||
|
||||
Please see the complete change log for further details: https://arianne-project.org/game/stendhal.html#changes
|
||||
|
|
|
|||
|
|
@ -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.48</string>
|
||||
<string name="build_version">1.49.5</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import android.content.DialogInterface;
|
|||
|
||||
/**
|
||||
* Semi-functional logger for release builds.
|
||||
*
|
||||
*
|
||||
* Displays notification dialogs but does not write to logs directory.
|
||||
*/
|
||||
public class Logger {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=91a239400bb638f36a1795d8fdf7939d532cdc7d794d1119b7261aac158b1e60
|
||||
distributionSha256Sum=f6b8596b10cce501591e92f229816aa4046424f3b24d771751b06779d58c8ec4
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ panic = 'abort'
|
|||
strip = true
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1.5.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
steamworks = "0.10.0"
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
use lazy_static::lazy_static;
|
||||
use serde_json::Value;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::process;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
|
|
@ -16,6 +19,10 @@ use websocket::client::ClientBuilder;
|
|||
use websocket::{Message, OwnedMessage};
|
||||
|
||||
|
||||
lazy_static! {
|
||||
static ref AUTHENTICATED: Mutex<bool> = Mutex::new(false);
|
||||
}
|
||||
|
||||
fn connect() -> (Sender<OwnedMessage>, JoinHandle<()>) {
|
||||
println!("Read connection parameters");
|
||||
let mut json = String::new();
|
||||
|
|
@ -119,6 +126,14 @@ fn connect() -> (Sender<OwnedMessage>, JoinHandle<()>) {
|
|||
fn handle_message(nl_token: &String, tx: Sender<OwnedMessage>, message: String) {
|
||||
if message.contains("event\":\"request_authentication\"") {
|
||||
authenticate(tx, nl_token.clone());
|
||||
} else if message.contains("event\":\"clientDisconnect\"") {
|
||||
let authenticated = AUTHENTICATED.lock().unwrap();
|
||||
if *authenticated {
|
||||
println!("Authenticated, exiting extension ...");
|
||||
} else {
|
||||
println!("Unauthenticated, exiting extension ...");
|
||||
}
|
||||
process::exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,6 +147,10 @@ fn authenticate(tx: Sender<OwnedMessage>, nl_token: String) {
|
|||
let _callback =
|
||||
client.register_callback(move |session_ticket_response: AuthSessionTicketResponse| {
|
||||
//if session_ticket_response.ticket == ticket_handle {
|
||||
if session_ticket_response.result.is_ok() {
|
||||
let mut authenticated = AUTHENTICATED.lock().unwrap();
|
||||
*authenticated = true;
|
||||
}
|
||||
println!("Ticket Response Result: {:?}", session_ticket_response.result);
|
||||
callback_called.store(true, Ordering::Relaxed);
|
||||
// println!("Ticket : {:?}", session_ticket_response.ticket);
|
||||
|
|
|
|||
1
app/neutralinojs/.gitignore
vendored
1
app/neutralinojs/.gitignore
vendored
|
|
@ -11,6 +11,7 @@ neutralino.js
|
|||
# Neutralinojs related files
|
||||
.storage
|
||||
*.log
|
||||
extensions/binary/steam_appid.txt
|
||||
extensions/binary/*.so
|
||||
extensions/binary/*.dll
|
||||
extensions/binary/nativehelper*
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
2267890
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/neutralinojs/neutralinojs/main/schemas/neutralino.config.schema.json",
|
||||
"applicationId": "org.stendhalgame.client",
|
||||
"version": "1.48",
|
||||
"version": "1.49.5",
|
||||
"defaultMode": "window",
|
||||
"port": 0,
|
||||
"documentRoot": "/resources/",
|
||||
|
|
@ -11,9 +11,9 @@
|
|||
"enableExtensions": true,
|
||||
"extensions": [
|
||||
{
|
||||
"id": "nativehelper",
|
||||
"commandLinux": "${NL_PATH}/extensions/binary/nativehelper",
|
||||
"commandWindows": "${NL_PATH}/extensions/binary/nativehelper.exe"
|
||||
"id": "nativehelper",
|
||||
"commandLinux": "${NL_PATH}/extensions/binary/nativehelper",
|
||||
"commandWindows": "${NL_PATH}/extensions/binary/nativehelper.exe"
|
||||
}
|
||||
],
|
||||
"tokenSecurity": "one-time",
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
"resourcesPath": "/resources/",
|
||||
"extensionsPath": "/extensions/",
|
||||
"clientLibrary": "/resources/js/neutralino.js",
|
||||
"binaryVersion": "5.0.0",
|
||||
"clientVersion": "5.0.1"
|
||||
"binaryVersion": "6.2.0",
|
||||
"clientVersion": "6.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
90
bin/check-file-size.py
Executable file
90
bin/check-file-size.py
Executable file
|
|
@ -0,0 +1,90 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
'''
|
||||
***************************************************************************
|
||||
* Copyright © 2025 - Faiumoni e. V. *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************
|
||||
'''
|
||||
|
||||
import errno
|
||||
import os
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
dir_root = Path(__file__).parent
|
||||
if "bin" == dir_root.name:
|
||||
dir_root = Path(dir_root.parent)
|
||||
dir_music = Path(dir_root, "data/music")
|
||||
dir_sounds = Path(dir_root, "data/sounds")
|
||||
|
||||
|
||||
## Checks if a file is larger than 2MB.
|
||||
#
|
||||
# On systems with low resources, the Java client struggles to load large audio files.
|
||||
#
|
||||
# @param path
|
||||
# File path.
|
||||
# @return
|
||||
# `EFBIG` if file is larger than 2MB, 0 otherwise.
|
||||
def checkAudioFileSize(path):
|
||||
if not path.is_file():
|
||||
# ignore if audio file doesn't exist
|
||||
print("WARNING: Ignoring file not found: {}".format(path))
|
||||
return 0
|
||||
|
||||
if path.stat().st_size > 1048576 * 2:
|
||||
# warn if file size > 2MB
|
||||
return errno.EFBIG
|
||||
return 0
|
||||
|
||||
## Checks directory for large audio files.
|
||||
#
|
||||
# @param path
|
||||
# Directory path to be walked.
|
||||
# @return
|
||||
# `EFBIG` if any file larger than 2MB found, 0 otherwise.
|
||||
def checkAudioDir(path):
|
||||
if not path.is_dir():
|
||||
# ignore if audio directory doesn't exist
|
||||
print("WARNING: Ignoring directory not found: {}".format(path))
|
||||
return 0
|
||||
|
||||
res = 0
|
||||
for ROOT, DIRS, FILES in path.walk():
|
||||
for filename in FILES:
|
||||
filepath = Path(ROOT, filename)
|
||||
if filepath.suffix.lower().lstrip(".") not in ("ogg", "oga", "mid", "midi"):
|
||||
# only check supported file types
|
||||
continue
|
||||
|
||||
code = checkAudioFileSize(filepath)
|
||||
if code == errno.EFBIG:
|
||||
res = code
|
||||
sys.stderr.write("WARNING: Audio file size larger than 2MB: {}\n".format(str(filepath)[len(str(dir_root)):].lstrip("/\\")))
|
||||
|
||||
return res
|
||||
|
||||
def main():
|
||||
res = 0
|
||||
for audio_dir in dir_music, dir_sounds:
|
||||
code = checkAudioDir(audio_dir)
|
||||
if code != 0:
|
||||
res = code
|
||||
if res == 0:
|
||||
print("No large audio data files detected")
|
||||
return res
|
||||
|
||||
if __name__ == "__main__":
|
||||
# work from source tree root
|
||||
os.chdir(dir_root)
|
||||
sys.exit(main())
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
@echo off
|
||||
|
||||
set STENDHAL_VERSION=1.48
|
||||
set STENDHAL_VERSION=1.49.5
|
||||
set SERVER_JAR=stendhal-server-%STENDHAL_VERSION%.jar
|
||||
|
||||
:: change to server directory
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
STENDHAL_VERSION="1.48"
|
||||
STENDHAL_VERSION="1.49.5"
|
||||
SERVER_JAR="stendhal-server-${STENDHAL_VERSION}.jar"
|
||||
|
||||
# change to server directory
|
||||
|
|
|
|||
|
|
@ -91,10 +91,10 @@ updates_server_fallback = http://arianne.sourceforge.net/stendhal/updates
|
|||
version_server = http://arianne.sourceforge.net/stendhal.version
|
||||
|
||||
# current version of stendhal
|
||||
version.old = 1.47
|
||||
version = 1.48
|
||||
version.android = 1048000
|
||||
version.old = 1.49
|
||||
version = 1.49.5
|
||||
# FIXME: dynamic method to set this property?
|
||||
version.android = 1049005
|
||||
|
||||
# javac options
|
||||
javac.deprecation = true
|
||||
|
|
|
|||
85
build.xml
85
build.xml
|
|
@ -1,81 +1,32 @@
|
|||
<?xml version='1.0'?>
|
||||
|
||||
<project name="stendhal" default="compile" basedir=".">
|
||||
<!--
|
||||
Sets a property (by name and value), or set of properties (from file or resource) in the project. Properties are case sensitive.
|
||||
Properties are immutable: whoever sets a property first freezes it for the rest of the build; they are most definitely not variables.
|
||||
-->
|
||||
<project name="stendhal" default="help" basedir=".">
|
||||
<description>
|
||||
Project:
|
||||
Name: .......... ${game_name}
|
||||
Version: ....... ${version}
|
||||
Root: .......... ${basedir}
|
||||
|
||||
Build system:
|
||||
Ant version: ... ${ant.version.number}
|
||||
Ant home: ...... ${ant.location}
|
||||
Java version: .. ${java.version}
|
||||
Java home: ..... ${java.home}
|
||||
|
||||
Execute `ant help` for more information.
|
||||
</description>
|
||||
|
||||
|
||||
<property file="build.ant-private.properties"/>
|
||||
<property file="build.ant.properties"/>
|
||||
|
||||
<property name="build_tests" value="${buildroot}/build_tests"/>
|
||||
<property name="build_tests_report" value="${buildroot}/build_test_report"/>
|
||||
|
||||
<property name="build_client" value="${buildroot}/build_client"/>
|
||||
<property name="build_client_data" value="${buildroot}/build_client_data"/>
|
||||
<property name="build_client_sound_data" value="${buildroot}/build_client_sound_data"/>
|
||||
<property name="build_client_music_data" value="${buildroot}/build_client_music_data"/>
|
||||
|
||||
<property name="build_webclient" value="${buildroot}/build_webclient"/>
|
||||
|
||||
<property name="build_docker" value="${buildroot}/build_docker"/>
|
||||
<property name="buildtools_docker" value="buildtools/docker"/>
|
||||
|
||||
<property name="build_postman" value="${buildroot}/buildbot/"/>
|
||||
|
||||
<property name="build_server" value="${buildroot}/build_server"/>
|
||||
<property name="build_server_maps" value="${buildroot}/build_server_maps"/>
|
||||
<property name="build_server_script" value="${buildroot}/build_server_script"/>
|
||||
<property name="build_server_mods" value="${buildroot}/build_server_mods"/>
|
||||
<property name="build_server_xmlconf" value="${buildroot}/build_server_xmlconf"/>
|
||||
|
||||
<property name="build_stendhaltools" value="${buildroot}/build_stendhaltools"/>
|
||||
<property name="build_stendhaltextclient" value="${buildroot}/build_stendhaltextclient"/>
|
||||
|
||||
<property name="client_data" value="stendhal-data-${version}.jar"/>
|
||||
<property name="client_jarname" value="stendhal-${version}.jar"/>
|
||||
<property name="client_sound_data" value="stendhal-sound-data-${version}.jar"/>
|
||||
<property name="client_music_data" value="stendhal-music-data-${version}.jar"/>
|
||||
<property name="client_starter_jarname" value="stendhal-starter-${version}.jar"/>
|
||||
|
||||
<property name="dist_server_binary" value="${buildroot}/stendhal-server-${version}.zip" />
|
||||
|
||||
<property name="maps_jarname" value="stendhal-maps-${version}.jar"/>
|
||||
|
||||
<property name="server_jarname" value="stendhal-server-${version}.jar"/>
|
||||
<property name="xmlconf_jarname" value="stendhal-xmlconf-${version}.jar"/>
|
||||
|
||||
<property name="config_dir" value="data/conf"/>
|
||||
|
||||
<property name="schema_location" value="${config_dir}"/>
|
||||
|
||||
<property name="cobertura.dir" value="${libdir}/cobertura"/>
|
||||
|
||||
<condition property="exclude.signing" value="true">
|
||||
<not>
|
||||
<available file="keystore.ks"/>
|
||||
</not>
|
||||
</condition>
|
||||
<condition property="exclude.jardiff" value="true">
|
||||
<not>
|
||||
<available file="${build-archive}/stendhal-${version.old}.zip"/>
|
||||
</not>
|
||||
</condition>
|
||||
|
||||
<!-- time & date -->
|
||||
<tstamp>
|
||||
<format property="year" pattern="yyyy"/>
|
||||
<format property="date" pattern="yyyy-MM-dd"/>
|
||||
<format property="time" pattern="HH:mm:ss"/>
|
||||
</tstamp>
|
||||
<property name="datetime" value="${date} ${time}"/>
|
||||
|
||||
|
||||
<!-- Ant sub-modules -->
|
||||
|
||||
<import file="build-private.xml" optional="true"/>
|
||||
|
||||
<import file="${ant_modules}/properties.xml"/>
|
||||
<import file="${ant_modules}/info.xml"/>
|
||||
<import file="${ant_modules}/system.xml"/>
|
||||
<import file="${ant_modules}/apps.xml"/>
|
||||
<import file="${ant_modules}/main.xml"/>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
<arg value="--target" />
|
||||
<arg value="x86_64-pc-windows-gnu" />
|
||||
</exec>
|
||||
<mkdir dir="app/neutralinojs/extensions/binary" />
|
||||
<exec executable="cargo" dir="app/nativehelper" failonerror="true" output="app/neutralinojs/extensions/binary/LICENSE.txt">
|
||||
<arg value="license" />
|
||||
<arg value="-ad" />
|
||||
|
|
@ -77,23 +78,33 @@
|
|||
<include name="*.log" />
|
||||
</fileset>
|
||||
</delete>
|
||||
<move
|
||||
file="app/neutralinojs/dist/stendhal-client/stendhal-client-linux_x64"
|
||||
tofile="app/neutralinojs/dist/stendhal-client/stendhal-client-linux" />
|
||||
<move
|
||||
file="app/neutralinojs/dist/stendhal-client/stendhal-client-win_x64.exe"
|
||||
tofile="app/neutralinojs/dist/stendhal-client/stendhal-client-windows.exe" />
|
||||
<chmod dir="app/neutralinojs/dist/stendhal-client/" type="file" perm="ugo+rx">
|
||||
<include name="stendhal*" />
|
||||
<include name="stendhal-client-linux" />
|
||||
<include name="**/nativehelper*" />
|
||||
</chmod>
|
||||
<!--
|
||||
<copy todir="dist/stendhal-client" flatten="true">
|
||||
<fileset dir="app/neutralinoks">
|
||||
<include name="LICENSE.txt" />
|
||||
</fileset>
|
||||
</copy>
|
||||
-->
|
||||
<copy file="app/neutralinojs/LICENSE.txt" tofile="app/neutralinojs/dist/stendhal-client/LICENSE.txt">
|
||||
<filterchain>
|
||||
<concatfilter append="app/neutralinojs/extensions/binary/LICENSE.txt" />
|
||||
</filterchain>
|
||||
</copy>
|
||||
|
||||
<echo file="app/neutralinojs/dist/stendhal-client/extensions/binary/steam_appid.txt">${steam-appid}</echo>
|
||||
<delete file="${buildroot}/stendhal-client-${version}.zip"/>
|
||||
<zip destfile="${buildroot}/stendhal-client-${version}.zip">
|
||||
<zipfileset dir="app/neutralinojs/dist/stendhal-client" prefix="stendhal-client" filemode="755">
|
||||
<include name="stendhal-client-linux" />
|
||||
<include name="**/nativehelper*" />
|
||||
</zipfileset>
|
||||
<zipfileset dir="app/neutralinojs/dist/stendhal-client" prefix="stendhal-client">
|
||||
<exclude name="stendhal-client-linux" />
|
||||
<exclude name="**/nativehelper*" />
|
||||
</zipfileset>
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
|
||||
|
|
@ -150,7 +161,8 @@
|
|||
</target> <!-- client_android_build -->
|
||||
|
||||
|
||||
<target name="android" description="Create Android client package for release and distribution.">
|
||||
<!-- Create Android client package for release and distribution. -->
|
||||
<target name="android">
|
||||
<echo
|
||||
if:set="exclude.webview"
|
||||
message="ANDROID_SDK_ROOT environment variable not set. Skipping Android WebView client build."/>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
<project xmlns:if="ant:if" xmlns:unless="ant:unless">
|
||||
|
||||
<target name="clean" description="Delete all build files and directories.">
|
||||
<!-- Delete all build files and directories. -->
|
||||
<target name="clean">
|
||||
<delete includeEmptyDirs="true" quiet="true">
|
||||
<fileset dir="${buildroot}" excludes="eclipse/" defaultExcludes="false"/>
|
||||
</delete>
|
||||
|
|
@ -18,14 +19,16 @@
|
|||
</target>
|
||||
|
||||
|
||||
<target name="clean_client_data" description="Delete client data build files and directories.">
|
||||
<!-- Delete client data build files and directories. -->
|
||||
<target name="clean_client_data">
|
||||
<delete dir="${build_client_data}"/>
|
||||
<delete dir="${build_client_music_data}"/>
|
||||
<delete dir="${build_client_sound_data}"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="cleanjs" description="Delete web client build files and directories.">
|
||||
<!-- Delete web client build files and directories. -->
|
||||
<target name="cleanjs">
|
||||
<delete dir="${buildroot}/js"/>
|
||||
<delete dir="${buildroot}/ts"/>
|
||||
</target>
|
||||
|
|
|
|||
|
|
@ -19,13 +19,15 @@
|
|||
</condition>
|
||||
|
||||
|
||||
<target name="jar" depends="client_build,server_build" description="Build server and clients.">
|
||||
<!-- Build server and clients. -->
|
||||
<target name="jar" depends="client_build,server_build">
|
||||
<!-- XXX: client & server builds are not exclusive to NetBeans, remove this output? -->
|
||||
<echo>Built client and server for NetBeans.</echo>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="signjar" unless="exclude.signing" description="Sign client distribution.">
|
||||
<!-- Sign client distribution. -->
|
||||
<target name="signjar" unless="exclude.signing">
|
||||
<signjar
|
||||
alias="${keystore.alias}"
|
||||
keystore="keystore.ks"
|
||||
|
|
@ -34,20 +36,23 @@
|
|||
</target>
|
||||
|
||||
|
||||
<!-- Generate JAR files for both client and server. -->
|
||||
<!-- XXX: why does this depend on "server_build" twice? -->
|
||||
<target name="compile" depends="server_build,client_build,server_build" description="Generate JAR files for both client and server."/>
|
||||
<target name="compile" depends="server_build,client_build,server_build" />
|
||||
|
||||
|
||||
<target name="dist" depends="clean,dist_binary,dist_source,signupdates" description="Create all packages for Stendhal release."/>
|
||||
<!-- Create all packages for Stendhal release. -->
|
||||
<target name="dist" depends="clean,dist_binary,dist_source,signupdates" />
|
||||
|
||||
|
||||
<target name="dist_binary" depends="clean,dist_server_binary,dist_client_binary,dist_client_starter,dist_webclient_binary"
|
||||
description="Create all binary packages for Stendhal release."/>
|
||||
<!-- Create all binary packages for Stendhal release. -->
|
||||
<target name="dist_binary" depends="clean,dist_server_binary,dist_client_binary,dist_client_starter,dist_webclient_binary" />
|
||||
|
||||
|
||||
<!-- START: source -->
|
||||
|
||||
<target name="dist_source" description="Create all source packages for Stendhal release.">
|
||||
<!-- Create all source packages for Stendhal release. -->
|
||||
<target name="dist_source">
|
||||
<mkdir dir="${buildroot}/stendhal-${version}-src"/>
|
||||
|
||||
<copy todir="${buildroot}/stendhal-${version}-src/src">
|
||||
|
|
@ -104,7 +109,8 @@
|
|||
|
||||
<!-- START: client data -->
|
||||
|
||||
<target name="build_client_data" description="Build client data files.">
|
||||
<!-- Build client data files. -->
|
||||
<target name="build_client_data">
|
||||
<!-- base data -->
|
||||
<mkdir dir="${build_client_data}"/>
|
||||
<copy todir="${build_client_data}/data/sprites">
|
||||
|
|
@ -179,7 +185,8 @@
|
|||
|
||||
<!-- START: server -->
|
||||
|
||||
<target name="server_build" depends="init,checkxml" description="Compile JAR file for Stendhal server.">
|
||||
<!-- Compile JAR file for Stendhal server. -->
|
||||
<target name="server_build" depends="init,checkxml">
|
||||
<mkdir dir="${build_server}"/>
|
||||
|
||||
<copy todir="${build_server}/data/conf" file="data/conf/stendhalcreateaccount.properties"/>
|
||||
|
|
@ -340,7 +347,8 @@
|
|||
</target> <!-- server_build -->
|
||||
|
||||
|
||||
<target name="dist_server_binary" depends="server_build" description="Create server package for release and distribution.">
|
||||
<!-- Create server package for release and distribution. -->
|
||||
<target name="dist_server_binary" depends="server_build">
|
||||
<mkdir dir="${buildroot}/stendhal-server-${version}"/>
|
||||
|
||||
<copy todir="${buildroot}/stendhal-server-${version}/data/script">
|
||||
|
|
@ -392,10 +400,12 @@
|
|||
</target> <!-- dist_server_binary -->
|
||||
|
||||
|
||||
<target name="dist_docker" depends="docker_build,docker_push" description="Build and push container image."/>
|
||||
<!-- Build and push container image. -->
|
||||
<target name="dist_docker" depends="docker_build,docker_push" />
|
||||
|
||||
|
||||
<target name="docker_build_prepare" depends="dist_server_binary" description="Prepare container image build.">
|
||||
<!-- Prepare container image build. -->
|
||||
<target name="docker_build_prepare" depends="dist_server_binary">
|
||||
<mkdir dir="${build_docker}" />
|
||||
<copy file="${buildtools_docker}/Dockerfile" todir="${build_docker}" />
|
||||
<copy file="${buildtools_docker}/.dockerignore" todir="${build_docker}" />
|
||||
|
|
@ -404,7 +414,8 @@
|
|||
</target> <!-- docker_build_prepare -->
|
||||
|
||||
|
||||
<target name="docker_build" depends="docker_build_prepare" description="Build container image.">
|
||||
<!-- Build container image. -->
|
||||
<target name="docker_build" depends="docker_build_prepare">
|
||||
<exec dir="${build_docker}" executable="docker">
|
||||
<arg value="build" />
|
||||
<arg value="-t" />
|
||||
|
|
@ -414,28 +425,57 @@
|
|||
</target> <!-- docker_build -->
|
||||
|
||||
|
||||
<target name="docker_push" description="Push container image."/>
|
||||
<!-- Push container image. -->
|
||||
<target name="docker_push" />
|
||||
|
||||
|
||||
<target name="server_run" depends="server_build,compilejs" description="Run server.">
|
||||
<mkdir dir="run_srvr"/>
|
||||
<!-- Run server. -->
|
||||
<target name="server_run" depends="server_build,compilejs">
|
||||
<mkdir dir="run_srvr/libs"/>
|
||||
<mkdir dir="run_srvr/js"/>
|
||||
|
||||
<copy todir="run_srvr">
|
||||
<fileset file="build/lib/${server_jarname}"/>
|
||||
<fileset file="build/lib/${xmlconf_jarname}"/>
|
||||
<fileset file="build/lib/${maps_jarname}"/>
|
||||
<fileset file="libs/marauroa.jar"/>
|
||||
<fileset file="libs/groovy.jar"/>
|
||||
<fileset file="libs/guava.jar"/>
|
||||
<fileset file="libs/log4j.jar"/>
|
||||
<fileset file="libs/${mysqldriver_jarname}"/>
|
||||
</copy>
|
||||
|
||||
<copy todir="run_srvr/libs">
|
||||
<fileset file="${marauroa_jar}" />
|
||||
<fileset file="${groovy_jar}" />
|
||||
<fileset file="${guava_jar}" />
|
||||
<fileset file="${log4j_jar}" />
|
||||
<fileset file="${mysqldriver_jar}" />
|
||||
<fileset file="${h2_jar}" />
|
||||
<fileset file="${hamcrest_jar}" />
|
||||
<fileset file="${tomcatcore_jar}" />
|
||||
<fileset file="${tomcatwebsocket_jar}" />
|
||||
<fileset file="${jakartaannotation_jar}" />
|
||||
<fileset file="${luaj_jar}" />
|
||||
<fileset file="${jsonsimple_jar}" />
|
||||
</copy>
|
||||
|
||||
<copy todir="run_srvr/js">
|
||||
<fileset dir="${srcjs}">
|
||||
<exclude name="stendhal/" />
|
||||
<exclude name="stendhal-compiled.js.map" />
|
||||
<exclude name=".gitignore" />
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<chmod file="run_srvr/${server_jarname}" perm="+x"/>
|
||||
|
||||
<exec dir="." executable="java">
|
||||
<arg line="-Xmx256m -cp run_srvr -jar run_srvr/${server_jarname} -c server.ini -l"/>
|
||||
</exec>
|
||||
<java jar="run_srvr/${server_jarname}"
|
||||
fork="true"
|
||||
failonerror="true"
|
||||
maxmemory="256m">
|
||||
<arg value="-c" />
|
||||
<arg value="server.ini" />
|
||||
<arg value="-l" />
|
||||
<classpath>
|
||||
<pathelement location="${basedir}" />
|
||||
</classpath>
|
||||
</java>
|
||||
|
||||
<!-- we've run the program, so delete the jars -->
|
||||
<delete dir="run_srvr"/>
|
||||
|
|
@ -446,7 +486,8 @@
|
|||
|
||||
<!-- START: java client -->
|
||||
|
||||
<target name="client_build" depends="init,build_client_data" description="Compile client JAR file.">
|
||||
<!-- Compile client JAR file. -->
|
||||
<target name="client_build" depends="init,build_client_data">
|
||||
<mkdir dir="${build_client}"/>
|
||||
|
||||
<copy todir="${build_client}/games/stendhal/client">
|
||||
|
|
@ -494,7 +535,7 @@
|
|||
|
||||
<!-- compile Starter.java for Java 1.7. So we will be able to
|
||||
display a dialogbox if running on an old Java Version -->
|
||||
<javac srcdir="${src}" destdir="${build_client}" debug="${javac.debug}" debuglevel="${javac.debuglevel}" source="1.7" target="1.7" deprecation="${javac.deprecation}" includeantruntime="false">
|
||||
<javac srcdir="${src}" destdir="${build_client}" debug="${javac.debug}" debuglevel="${javac.debuglevel}" source="1.8" target="1.8" deprecation="${javac.deprecation}" includeantruntime="false">
|
||||
<include name="games/stendhal/client/update/Starter.java"/>
|
||||
|
||||
<compilerarg value="-encoding"/>
|
||||
|
|
@ -539,7 +580,8 @@
|
|||
</target> <!-- client_build -->
|
||||
|
||||
|
||||
<target name="compile_stendhaltextclient" description="Compile text client.">
|
||||
<!-- Compile text client. -->
|
||||
<target name="compile_textclient">
|
||||
<mkdir dir="${build_stendhaltextclient}"/>
|
||||
|
||||
<javac srcdir="${src}" destdir="${build_stendhaltextclient}" source="1.8" target="1.8" debug="${javac.debug}" debuglevel="${javac.debuglevel}" deprecation="${javac.deprecation}" includeantruntime="false">
|
||||
|
|
@ -560,8 +602,12 @@
|
|||
</javac>
|
||||
</target> <!-- compile_stendhaltextclient -->
|
||||
|
||||
<!-- Alias of `compile_textclient`. -->
|
||||
<target name="compile_stendhaltextclient" depends="compile_textclient" />
|
||||
|
||||
<target name="dist_client_binary" depends="clean_client_data,client_build" description="Create Java client package for release and distribution.">
|
||||
|
||||
<!-- Create Java client package for release and distribution. -->
|
||||
<target name="dist_client_binary" depends="clean_client_data,client_build">
|
||||
<mkdir dir="${buildroot}/stendhal-${version}"/>
|
||||
<mkdir dir="${buildroot}/stendhal-${version}/lib"/>
|
||||
<mkdir dir="${buildroot}/stendhal-${version}/log"/>
|
||||
|
|
@ -597,8 +643,8 @@
|
|||
</target> <!-- dist_client_binary -->
|
||||
|
||||
|
||||
<!-- XXX: is this still used? -->
|
||||
<target name="dist_client_starter" depends="client_build" description="Create Java client starter package.">
|
||||
<!-- Create Java client starter package (obsolete). -->
|
||||
<target name="dist_client_starter" depends="client_build">
|
||||
<mkdir dir="${buildroot}/stendhal-${version}"/>
|
||||
<copy todir="${buildroot}/stendhal-${version}" file="${lib}/${client_starter_jarname}"/>
|
||||
<copy todir="${buildroot}/stendhal-${version}/lib">
|
||||
|
|
@ -620,7 +666,8 @@
|
|||
</target> <!-- dist_client_starter -->
|
||||
|
||||
|
||||
<target name="client_run" depends="client_build" description="Run Java client.">
|
||||
<!-- Run Java client. -->
|
||||
<target name="client_run" depends="client_build">
|
||||
<mkdir dir="run_clnt"/>
|
||||
<mkdir dir="run_clnt/lib"/>
|
||||
|
||||
|
|
@ -656,8 +703,9 @@
|
|||
</target> <!-- client_run -->
|
||||
|
||||
|
||||
<!-- Run client for NetBeans trick. -->
|
||||
<!-- Netbeans won't let you choose ant options, so this does it for us-->
|
||||
<target name="run" depends="client_run" description="Run client for NetBeans trick."/>
|
||||
<target name="run" depends="client_run" />
|
||||
|
||||
<!-- END: java client -->
|
||||
|
||||
|
|
@ -665,30 +713,42 @@
|
|||
<!-- START: web client -->
|
||||
|
||||
<target name="js-prepare-marauroa">
|
||||
<mkdir dir="build/js"/>
|
||||
<unzip dest="build" src="libs/marauroa.jar">
|
||||
<mkdir dir="node_modules/marauroa"/>
|
||||
<unzip dest="node_modules/marauroa" src="libs/marauroa.jar">
|
||||
<mapper type="flatten"/>
|
||||
<patternset>
|
||||
<include name="js/**"/>
|
||||
</patternset>
|
||||
</unzip>
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
<target name="js-prepare-build">
|
||||
<echo file="build/js/build.js">
|
||||
var stendhal = window.stendhal = window.stendhal || {};
|
||||
stendhal.data = stendhal.data || {};
|
||||
<mkdir dir="node_modules/marauroa"/>
|
||||
<echo file="node_modules/marauroa/build.js">
|
||||
export function version(marauroa, stendhal) {
|
||||
stendhal.data = stendhal.data || {};
|
||||
|
||||
stendhal.data.build = {
|
||||
version: "${version}",
|
||||
build: "${datetime}",
|
||||
dist: "webclient"
|
||||
}
|
||||
stendhal.data.build = {
|
||||
version: "${version}",
|
||||
build: "${datetime}",
|
||||
dist: "webclient"
|
||||
}
|
||||
|
||||
//CI
|
||||
}
|
||||
</echo>
|
||||
<antcall target="js-prepare-build-ci" />
|
||||
</target>
|
||||
|
||||
<target name="js-prepare-build-ci" if="ci.build.info">
|
||||
<loadfile property="cibuildinfo" srcFile="${ci.build.info}" failonerror="false" quiet="true"/>
|
||||
<replace file="node_modules/marauroa/build.js" token="//CI" value="${cibuildinfo}" />
|
||||
</target>
|
||||
|
||||
|
||||
<extension-point name="js-prepare" depends="js-prepare-marauroa,js-prepare-build,js-prepare-node,js-prepare-contribs"/>
|
||||
<extension-point name="js-prepare" depends="js-prepare-node,js-prepare-contribs,js-prepare-marauroa,js-prepare-build"/>
|
||||
|
||||
|
||||
<target name="js-prepare-node">
|
||||
|
|
@ -713,72 +773,19 @@
|
|||
|
||||
<!-- TODO: Do not write stendhal-compiled.js to the source directory tree but directly to the compiled directory tree -->
|
||||
<target name="js-invoke-compiler">
|
||||
|
||||
<exec executable="${executable.npx}" dir="${srcjs}/stendhal" failonerror="true">
|
||||
<arg value="tsc"/>
|
||||
</exec>
|
||||
|
||||
<property name="js-debug" value="--debug --formatting=PRETTY_PRINT --create_source_map ${srcjs}/stendhal-compiled.js.map --source_map_include_content"/>
|
||||
|
||||
<property name="js-files-license" value="${srcjs}/stendhal/license.js"/>
|
||||
<property name="js-files-marauroa" value="build/js/marauroa.js build/js/client-framework.js build/js/message-factory.js build/js/perception.js build/js/rpfactory.js build/js/inflate.js build/js/deserializer.js"/>
|
||||
<property name="js-files-config" value="build/js/build.js"/>
|
||||
<property name="js-files-lib1" value="${srcjs}/jsxgraph-util.js"/>
|
||||
<property name="js-files-lib2" value=""/>
|
||||
<property name="js-files-data1" value="${srcjs}/stendhal/data/sha3.js"/>
|
||||
<property name="js-files-data2" value=""/>
|
||||
<property name="js-files-entity5" value=""/>
|
||||
<property name="js-files-entity6" value=""/>
|
||||
<property name="js-files-ui1" value=""/>
|
||||
<property name="js-files-ui2" value=""/>
|
||||
<property name="js-files-ui3" value=""/>
|
||||
<property name="js-files-main1" value=""/>
|
||||
<property name="js-files-ui4" value=""/>
|
||||
<property name="js-files-main2" value=""/>
|
||||
<property name="js-files-main3" value=""/>
|
||||
<property name="js-files-ts" value="build/ts/*.js build/ts/**/*.js"/>
|
||||
<property name="js-files-ts2" value=""/>
|
||||
|
||||
|
||||
<java jar="buildtools/closure-compiler/compiler.jar"
|
||||
fork="true"
|
||||
failonerror="true"
|
||||
maxmemory="128m">
|
||||
<arg value="--language_in=ECMASCRIPT_2020"/>
|
||||
<arg value="--language_out=STABLE"/>
|
||||
<arg value="--compilation_level"/>
|
||||
<arg value="ADVANCED"/>
|
||||
<arg line="${js-debug}"/>
|
||||
<arg value="--process_common_js_modules"/>
|
||||
<arg value="--module_resolution=node"/>
|
||||
<arg value="--jscomp_off=checkVars"/>
|
||||
<!-- DEBUG: -->
|
||||
<!--<arg value="-\-jscomp_off=globalThis"/>-->
|
||||
|
||||
<arg value="--js_output_file=${srcjs}/stendhal-compiled.js"/>
|
||||
|
||||
<arg line="${js-files-license}"/>
|
||||
<arg line="${js-files-marauroa}"/>
|
||||
<arg line="${js-files-config}"/>
|
||||
<arg line="${js-files-lib1}"/>
|
||||
<arg line="${js-files-lib2}"/>
|
||||
<arg line="${js-files-data1}"/>
|
||||
<arg line="${js-files-data2}"/>
|
||||
<arg line="${js-files-entity5}"/>
|
||||
<arg line="${js-files-entity6}"/>
|
||||
<arg line="${js-files-ui1}"/>
|
||||
<arg line="${js-files-ui2}"/>
|
||||
<arg line="${js-files-ui3}"/>
|
||||
<arg line="${js-files-main1}"/>
|
||||
<arg line="${js-files-ui4}"/>
|
||||
<arg line="${js-files-main2}"/>
|
||||
<arg line="${js-files-main3}"/>
|
||||
<arg line="${js-files-ts}"/>
|
||||
<arg line="${js-files-ts2}"/>
|
||||
</java>
|
||||
|
||||
<echo file="${srcjs}/stendhal-compiled.js" append="true">
|
||||
//# sourceMappingURL=stendhal-compiled.js.map
|
||||
</echo>
|
||||
<exec executable="${executable.npx}" dir="${srcjs}/stendhal" failonerror="true">
|
||||
<arg value="esbuild"/>
|
||||
<arg value="--bundle"/>
|
||||
<arg value="--outfile=../stendhal-compiled.js"/>
|
||||
<arg value="--platform=browser"/>
|
||||
<!-- <arg value="- -minify"/> -->
|
||||
<arg value="main.ts"/>
|
||||
</exec>
|
||||
|
||||
<antcall target="compilejs-hook" />
|
||||
|
||||
|
|
@ -795,7 +802,8 @@
|
|||
</target>
|
||||
|
||||
|
||||
<target name="compilejs" depends="cleanjs" description="Compile web client.">
|
||||
<!-- Compile web client. -->
|
||||
<target name="compilejs" depends="cleanjs">
|
||||
<antcall target="js-prepare" unless:set="exclude.webclient"/>
|
||||
<antcall target="js-invoke-compiler" unless:set="exclude.webclient"/>
|
||||
|
||||
|
|
@ -804,7 +812,8 @@
|
|||
</target> <!-- compilejs -->
|
||||
|
||||
|
||||
<target name="webclient_build" depends="compilejs,clean_client_data,build_client_data" description="Compile and stage web client files.">
|
||||
<!-- Compile and stage web client files. -->
|
||||
<target name="webclient_build" depends="compilejs,clean_client_data,build_client_data">
|
||||
<mkdir dir="${build_webclient}"/>
|
||||
|
||||
<copy todir="${build_webclient}">
|
||||
|
|
@ -826,10 +835,8 @@
|
|||
</target> <!-- webclient_build -->
|
||||
|
||||
|
||||
<target name="build_webclient" depends="webclient_build" description="Alias of webclient_build."/>
|
||||
|
||||
|
||||
<target name="dist_webclient_binary" depends="webclient_build" description="Create web client package for release and distribution.">
|
||||
<!-- Create web client package for release and distribution. -->
|
||||
<target name="dist_webclient_binary" depends="webclient_build">
|
||||
<zip destfile="${buildroot}/stendhal-webclient-${version}.zip">
|
||||
<zipfileset dir="${build_client_data}"/>
|
||||
<zipfileset dir="${build_client_music_data}"/>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@
|
|||
<delete dir="${buildroot}/build_docs"/>
|
||||
</target>
|
||||
|
||||
<target name="docs" description="Generate HTML documentation for Java, TypeScript, and Lua APIs." depends="luadocs,javadocs,tsdocs"/>
|
||||
<!-- Generate HTML documentation for Java, TypeScript, and Lua APIs. -->
|
||||
<target name="docs" depends="luadocs,javadocs,tsdocs"/>
|
||||
|
||||
|
||||
<!-- Java documentation -->
|
||||
|
|
|
|||
86
buildtools/ant_modules/info.xml
Normal file
86
buildtools/ant_modules/info.xml
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
<?xml version='1.0'?>
|
||||
|
||||
<project>
|
||||
|
||||
<target name="info" description="Print project build information.">
|
||||
<echo level="info" message="Project:" />
|
||||
<echo level="info" message=" Name: .......... ${game_name}" />
|
||||
<echo level="info" message=" Version: ....... ${version}" />
|
||||
<echo level="info" message=" Root: .......... ${basedir}" />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="Build system:" />
|
||||
<echo level="info" message=" Ant version: ... ${ant.version.number}" />
|
||||
<echo level="info" message=" Ant home: ...... ${ant.location}" />
|
||||
<echo level="info" message=" Java version: .. ${java.version}" />
|
||||
<echo level="info" message=" Java home: ..... ${java.home}" />
|
||||
</target>
|
||||
|
||||
<target name="help" description="Print project build and help information." depends="info">
|
||||
<echo level="info" message="Usage:" />
|
||||
<echo level="info" message=" ant <target> [<target>...]" />
|
||||
<echo level="info" />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="=== TARGETS ===" />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="General:" />
|
||||
<echo level="info" message=" info: ........................ Print project build information." />
|
||||
<echo level="info" message=" help: ........................ Print project build and help information." />
|
||||
<echo level="info" message=" init: ........................ Update version and resource info." />
|
||||
<echo level="info" message=" checkxml: .................... Verify XML files are well-formed." />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="Build:" />
|
||||
<echo level="info" message=" server_build: ................ Compile JAR file for Stendhal server." />
|
||||
<echo level="info" message=" client_build: ................ Compile client JAR file." />
|
||||
<echo level="info" message=" webclient_build: ............. Compile and stage web client files." />
|
||||
<echo level="info" message=" compile_textclient: .......... Compile text client." />
|
||||
<echo level="info" message=" compile: ..................... Generate JAR files for both client and server." />
|
||||
<echo level="info" message=" compilejs: ................... Compile web client." />
|
||||
<echo level="info" message=" compile_tools: ............... Compile Stendhal build tools." />
|
||||
<echo level="info" message=" server_run: .................. Run server." />
|
||||
<echo level="info" message=" client_run: .................. Run Java client." />
|
||||
<echo level="info" message=" postman: ..................... Build postman bot." />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="Testing:" />
|
||||
<echo level="info" message=" compile_tests: ............... Compile all tests." />
|
||||
<echo level="info" message=" run_tests: ................... Run all tests." />
|
||||
<echo level="info" message=" test: ........................ Compile and run all tests." />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="Build cleaning:" />
|
||||
<echo level="info" message=" clean: ....................... Delete all build files and directories." />
|
||||
<echo level="info" message=" clean_client_data: ........... Delete client data build files and directories." />
|
||||
<echo level="info" message=" cleanjs: ..................... Delete web client build files and directories." />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="Source maintanence:" />
|
||||
<echo level="info" message=" clean_whitespace: ............ Clean whitespace in source and other specified file types." />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="Distribution:" />
|
||||
<echo level="info" message=" dist_source: ................. Create all source packages for Stendhal release." />
|
||||
<echo level="info" message=" dist_binary: ................. Create all binary packages for Stendhal release." />
|
||||
<echo level="info" message=" dist_server_binary: .......... Create server package for release and distribution." />
|
||||
<echo level="info" message=" dist_client_binary: .......... Create Java client package for release and distribution." />
|
||||
<echo level="info" message=" dist_webclient_binary: ....... Create web client package for release and distribution." />
|
||||
<echo level="info" message=" dist_client_starter: ......... Create Java client starter package (obsolete)." />
|
||||
<echo level="info" message=" dist: ........................ Create all packages for Stendhal release." />
|
||||
<echo level="info" message=" android: ..................... Create Android client package for release and distribution." />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="Resources:" />
|
||||
<echo level="info" message=" rendermaps: .................. Convert TMX maps to PNG images scaled 1:16." />
|
||||
<echo level="info" message=" renderatlas: ................. Generate files for the Stendhal Atlas." />
|
||||
<echo level="info" message=" renderworldmap: .............. Export world.tmx map to PNG image." />
|
||||
<echo level="info" message=" updatemaps: .................. Load and save TMX maps to fix tilesets changes." />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="Documentation:" />
|
||||
<echo level="info" message=" docs: ........................ Generate HTML documentation for Java, TypeScript, and Lua APIs." />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="Localization:" />
|
||||
<echo level="info" message=" locale_template: ............. Creates a template for translating." />
|
||||
<echo level="info" message=" locale_update: ............... Update translation files from template." />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="Aliases:" />
|
||||
<echo level="info" message=" compile_stendhaltextclient: .. Alias of `compile_textclient`." />
|
||||
<echo level="info" message=" compile_stendhaltools: ....... Alias of `compile_tools`." />
|
||||
<echo level="info" />
|
||||
<echo level="info" message="Execute `ant -p -v` for a full list of build targets." />
|
||||
</target>
|
||||
|
||||
</project>
|
||||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
<project xmlns:if="ant:if" xmlns:unless="ant:unless">
|
||||
|
||||
<target name="locale_build_template" description="Creates a template for translating.">
|
||||
<!-- Creates a template for translating. -->
|
||||
<target name="locale_template">
|
||||
<echo unless:true="${python.present}" message="Python unavailable, cannot build locale template"/>
|
||||
|
||||
<exec executable="${executable.python}" if:true="${python.present}" failonerror="true">
|
||||
|
|
@ -11,7 +12,8 @@
|
|||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="locale_update" description="Update translation files from template.">
|
||||
<!-- Update translation files from template. -->
|
||||
<target name="locale_update">
|
||||
<echo unless:true="${python.present}" message="Python unavailable, cannot update translations"/>
|
||||
|
||||
<exec executable="${executable.python}" if:true="${python.present}" failonerror="true">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
<project xmlns:if="ant:if" xmlns:unless="ant:unless">
|
||||
|
||||
<target name="init" description="Update version and resource info.">
|
||||
<!-- Update version and resource info. -->
|
||||
<target name="init">
|
||||
<mkdir dir="${lib}"/>
|
||||
|
||||
<!-- update version -->
|
||||
|
|
@ -42,6 +43,10 @@
|
|||
match=""version": ".*""
|
||||
replace=""version": "${version}""
|
||||
byline="true"/>
|
||||
<replaceregexp file="${src}/games/stendhal/client/update/HttpClient.java"
|
||||
match="StendhalClient/.* \("
|
||||
replace="StendhalClient/${version} \("
|
||||
byline="true"/>
|
||||
|
||||
<!-- update location of resources -->
|
||||
<replaceregexp file="${src}/games/stendhal/client/update/game-default.properties"
|
||||
|
|
@ -85,7 +90,8 @@
|
|||
</target> <!-- init -->
|
||||
|
||||
|
||||
<target name="checkxml" description="Verify XML files are well-formed.">
|
||||
<!-- Verify XML files are well-formed. -->
|
||||
<target name="checkxml">
|
||||
<schemavalidate failonerror="yes" lenient="yes" warn="yes">
|
||||
<schema namespace="stendhal" file="${config_dir}/zones.xsd"/>
|
||||
<fileset dir="${config_dir}/zones">
|
||||
|
|
@ -163,7 +169,8 @@
|
|||
</target> <!-- checkxml -->
|
||||
|
||||
|
||||
<target name="internalUpdatePrereleaseVersion" if="PRE_RELEASE" description="Add date to pre-release test client.">
|
||||
<!-- Add date to pre-release test client. -->
|
||||
<target name="internalUpdatePrereleaseVersion" if="PRE_RELEASE">
|
||||
<tstamp prefix="date">
|
||||
<format property="iso" pattern="yyyy-MM-dd"/>
|
||||
</tstamp>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
<import file="tools.xml" />
|
||||
|
||||
<target name="rendermaps" description="Convert TMX maps to PNG images scaled 1:16." depends="compile_stendhaltools">
|
||||
<!-- Convert TMX maps to PNG images scaled 1:16. -->
|
||||
<target name="rendermaps" depends="compile_stendhaltools">
|
||||
<taskdef name="maprenderer" classname="games.stendhal.tools.MapRenderer">
|
||||
<classpath>
|
||||
<pathelement path="${build_stendhaltools}"/>
|
||||
|
|
@ -23,7 +24,8 @@
|
|||
</target> <!-- rendermaps -->
|
||||
|
||||
|
||||
<target name="renderatlas" description="Generate files for the Stendhal Atlas." depends="compile_stendhaltools">
|
||||
<!-- Generate files for the Stendhal Atlas. -->
|
||||
<target name="renderatlas" depends="compile_stendhaltools">
|
||||
<taskdef name="maprenderer" classname="games.stendhal.tools.MapRenderer">
|
||||
<classpath>
|
||||
<pathelement path="${build_stendhaltools}"/>
|
||||
|
|
@ -58,7 +60,8 @@
|
|||
</target> <!-- renderatlas -->
|
||||
|
||||
|
||||
<target name="renderworldmap" description="Export world.tmx map to PNG image." depends="rendermaps">
|
||||
<!-- Export world.tmx map to PNG image. -->
|
||||
<target name="renderworldmap" depends="rendermaps">
|
||||
<!-- embed area images with area name -->
|
||||
<!-- FIXME: need to detect the Python "PIL" module to ensure script can run or
|
||||
write Java class that can do this -->
|
||||
|
|
@ -85,7 +88,8 @@
|
|||
</target> <!-- renderworldmap -->
|
||||
|
||||
|
||||
<target name="updatemaps" description="Load and save TMX maps to fix tilesets changes." depends="compile_stendhaltools">
|
||||
<!-- Load and save TMX maps to fix tilesets changes. -->
|
||||
<target name="updatemaps" depends="compile_stendhaltools">
|
||||
<taskdef name="mapupdater" classname="games.stendhal.tools.MapUpdater">
|
||||
<classpath>
|
||||
<pathelement path="${build_stendhaltools}"/>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@
|
|||
<delete file="${build}/package/client/stendhal-starter.exe"/>
|
||||
</target>
|
||||
|
||||
<target name="msiPackage" description="Creates MSI installer package from current build" depends="stagePackage">
|
||||
<!-- Creates MSI installer package from current build. -->
|
||||
<target name="msiPackage" depends="stagePackage">
|
||||
<delete dir="${build}/package/msi-app-image"/>
|
||||
<exec executable="jpackage" dir="." failonerror="true">
|
||||
<arg line="--type app-image"/>
|
||||
|
|
@ -46,7 +47,8 @@
|
|||
</exec>
|
||||
</target> <!-- msiPackage -->
|
||||
|
||||
<target name="dmgPackage" description="Creates DMG package from current build" depends="stagePackage">
|
||||
<!-- Creates DMG package from current build. -->
|
||||
<target name="dmgPackage" depends="stagePackage">
|
||||
<delete dir="${build}/package/dmg-app-image"/>
|
||||
<exec executable="jpackage" dir="." failonerror="true">
|
||||
<arg line="--type app-image"/>
|
||||
|
|
@ -74,7 +76,8 @@
|
|||
</exec>
|
||||
</target> <!-- dmgPackage -->
|
||||
|
||||
<target name="rpmPackage" description="Creates RPM package from current build" depends="stagePackage">
|
||||
<!-- Creates RPM package from current build. -->
|
||||
<target name="rpmPackage" depends="stagePackage">
|
||||
<delete dir="${build}/package/rpm-app-image"/>
|
||||
<exec executable="jpackage" dir="." failonerror="true">
|
||||
<arg line="--type app-image"/>
|
||||
|
|
@ -107,7 +110,8 @@
|
|||
</exec>
|
||||
</target> <!-- rpmPackage -->
|
||||
|
||||
<target name="debPackage" description="Creates DEB package from current build" depends="stagePackage">
|
||||
<!-- Creates DEB package from current build. -->
|
||||
<target name="debPackage" depends="stagePackage">
|
||||
<delete dir="${build}/package/deb-app-image"/>
|
||||
<exec executable="jpackage" dir="." failonerror="true">
|
||||
<arg line="--type app-image"/>
|
||||
|
|
|
|||
77
buildtools/ant_modules/properties.xml
Normal file
77
buildtools/ant_modules/properties.xml
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<?xml version='1.0'?>
|
||||
|
||||
<project>
|
||||
|
||||
<!--
|
||||
Sets a property (by name and value), or set of properties (from file or resource) in the project. Properties are case sensitive.
|
||||
Properties are immutable: whoever sets a property first freezes it for the rest of the build; they are most definitely not variables.
|
||||
-->
|
||||
|
||||
<!-- store ant version number without extra details -->
|
||||
<antversion property="ant.version.number" />
|
||||
<!-- store ant home directory with system delimiter -->
|
||||
<property name="ant.location" location="${ant.home}" />
|
||||
|
||||
<property name="build_tests" value="${buildroot}/build_tests"/>
|
||||
<property name="build_tests_report" value="${buildroot}/build_test_report"/>
|
||||
|
||||
<property name="build_client" value="${buildroot}/build_client"/>
|
||||
<property name="build_client_data" value="${buildroot}/build_client_data"/>
|
||||
<property name="build_client_sound_data" value="${buildroot}/build_client_sound_data"/>
|
||||
<property name="build_client_music_data" value="${buildroot}/build_client_music_data"/>
|
||||
|
||||
<property name="build_webclient" value="${buildroot}/build_webclient"/>
|
||||
|
||||
<property name="build_docker" value="${buildroot}/build_docker"/>
|
||||
<property name="buildtools_docker" value="buildtools/docker"/>
|
||||
|
||||
<property name="build_postman" value="${buildroot}/buildbot/"/>
|
||||
|
||||
<property name="build_server" value="${buildroot}/build_server"/>
|
||||
<property name="build_server_maps" value="${buildroot}/build_server_maps"/>
|
||||
<property name="build_server_script" value="${buildroot}/build_server_script"/>
|
||||
<property name="build_server_mods" value="${buildroot}/build_server_mods"/>
|
||||
<property name="build_server_xmlconf" value="${buildroot}/build_server_xmlconf"/>
|
||||
|
||||
<property name="build_stendhaltools" value="${buildroot}/build_stendhaltools"/>
|
||||
<property name="build_stendhaltextclient" value="${buildroot}/build_stendhaltextclient"/>
|
||||
|
||||
<property name="client_data" value="stendhal-data-${version}.jar"/>
|
||||
<property name="client_jarname" value="stendhal-${version}.jar"/>
|
||||
<property name="client_sound_data" value="stendhal-sound-data-${version}.jar"/>
|
||||
<property name="client_music_data" value="stendhal-music-data-${version}.jar"/>
|
||||
<property name="client_starter_jarname" value="stendhal-starter-${version}.jar"/>
|
||||
|
||||
<property name="dist_server_binary" value="${buildroot}/stendhal-server-${version}.zip" />
|
||||
|
||||
<property name="maps_jarname" value="stendhal-maps-${version}.jar"/>
|
||||
|
||||
<property name="server_jarname" value="stendhal-server-${version}.jar"/>
|
||||
<property name="xmlconf_jarname" value="stendhal-xmlconf-${version}.jar"/>
|
||||
|
||||
<property name="config_dir" value="data/conf"/>
|
||||
|
||||
<property name="schema_location" value="${config_dir}"/>
|
||||
|
||||
<property name="cobertura.dir" value="${libdir}/cobertura"/>
|
||||
|
||||
<condition property="exclude.signing" value="true">
|
||||
<not>
|
||||
<available file="keystore.ks"/>
|
||||
</not>
|
||||
</condition>
|
||||
<condition property="exclude.jardiff" value="true">
|
||||
<not>
|
||||
<available file="${build-archive}/stendhal-${version.old}.zip"/>
|
||||
</not>
|
||||
</condition>
|
||||
|
||||
<!-- time & date -->
|
||||
<tstamp>
|
||||
<format property="year" pattern="yyyy"/>
|
||||
<format property="date" pattern="yyyy-MM-dd"/>
|
||||
<format property="time" pattern="HH:mm:ss"/>
|
||||
</tstamp>
|
||||
<property name="datetime" value="${date} ${time}"/>
|
||||
|
||||
</project>
|
||||
|
|
@ -7,7 +7,8 @@
|
|||
<import file="dist.xml" />
|
||||
<import file="tools.xml" />
|
||||
|
||||
<target name="test" description="Compile and run all tests." depends="compile_tests,prepare_serverini_for_tests,run_tests,report_test">
|
||||
<!-- Compile and run all tests. -->
|
||||
<target name="test" depends="compile_tests,prepare_serverini_for_tests,run_tests,report_test">
|
||||
<exec executable="curl">
|
||||
<arg value="-q"/>
|
||||
<arg value="-F"/>
|
||||
|
|
@ -21,7 +22,8 @@
|
|||
</target> <!-- test -->
|
||||
|
||||
|
||||
<target name="compile_tests" description="Compile all tests." depends="server_build,client_build,compile_stendhaltools,compile_stendhaltextclient,postman">
|
||||
<!-- Compile all tests. -->
|
||||
<target name="compile_tests" depends="server_build,client_build,compile_stendhaltools,compile_stendhaltextclient,postman">
|
||||
<mkdir dir="${build_tests}"/>
|
||||
|
||||
<copy todir="${build_tests}">
|
||||
|
|
@ -63,7 +65,8 @@
|
|||
</target> <!-- compile_tests -->
|
||||
|
||||
|
||||
<target name="prepare_serverini_for_tests" unless="server.ini" description="Generate server.ini for testing.">
|
||||
<!-- Generate server.ini for testing. -->
|
||||
<target name="prepare_serverini_for_tests" unless="server.ini">
|
||||
<echo file="server.ini">
|
||||
database_implementation=games.stendhal.server.core.engine.StendhalPlayerDatabase
|
||||
factory_implementation=games.stendhal.server.core.engine.StendhalRPObjectFactory
|
||||
|
|
@ -85,7 +88,8 @@ d = 9017093486007323270605414717455737376618092805104733236083857811315606869372
|
|||
</target> <!-- prepare_serverini_for_tests -->
|
||||
|
||||
|
||||
<target name="run_tests" description="Run all tests.">
|
||||
<!-- Run all tests. -->
|
||||
<target name="run_tests">
|
||||
<mkdir dir="${build_tests_report}"/>
|
||||
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
|
||||
<classpath path="buildtools/jacoco/jacocoant.jar"/>
|
||||
|
|
@ -147,7 +151,8 @@ d = 9017093486007323270605414717455737376618092805104733236083857811315606869372
|
|||
</target> <!-- run_tests -->
|
||||
|
||||
|
||||
<target name="report_test" description="Aggregate test results.">
|
||||
<!-- Aggregate test results. -->
|
||||
<target name="report_test">
|
||||
<mkdir dir="${build_tests_report}"/>
|
||||
<junitreport todir="${build_tests_report}" tofile="testresults.xml">
|
||||
<fileset dir="${build_tests_report}">
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
<import file="dist.xml" />
|
||||
|
||||
<target name="compile_stendhaltools" description="Compile Stendhal build tools.">
|
||||
<!-- Compile Stendhal build tools. -->
|
||||
<target name="compile_tools">
|
||||
<mkdir dir="${build_stendhaltools}"/>
|
||||
|
||||
<javac srcdir="${src}" destdir="${build_stendhaltools}" source="1.8" target="1.8" debug="${javac.debug}" debuglevel="${javac.debuglevel}" deprecation="${javac.deprecation}" includeantruntime="true">
|
||||
|
|
@ -28,7 +29,11 @@
|
|||
</javac>
|
||||
</target> <!-- compile_stendhaltools -->
|
||||
|
||||
<target name="clean_whitespace" description="Clean whitespace in source and other specified file types." depends="compile_stendhaltools">
|
||||
<!-- Alias of `compile_tools`. -->
|
||||
<target name="compile_stendhaltools" depends="compile_tools" />
|
||||
|
||||
<!-- Clean whitespace in source and other specified file types. -->
|
||||
<target name="clean_whitespace" depends="compile_stendhaltools">
|
||||
<!-- process main Java source, config, & scripting files -->
|
||||
<java classname="games.stendhal.tools.CleanWhitespace">
|
||||
<classpath>
|
||||
|
|
@ -36,7 +41,7 @@
|
|||
</classpath>
|
||||
<arg value="src/"/>
|
||||
<arg value="tests/"/>
|
||||
<arg value="android/app/src/"/>
|
||||
<arg value="app/android/client/src"/>
|
||||
<arg value="java,xml,lua"/>
|
||||
</java>
|
||||
|
||||
|
|
@ -55,16 +60,22 @@
|
|||
<pathelement path="${build_stendhaltools}"/>
|
||||
</classpath>
|
||||
<arg value="data/"/>
|
||||
<arg value="tiled/"/>
|
||||
<arg value="xml,xsd,lua,py"/>
|
||||
</java>
|
||||
|
||||
<!-- process Ant build configuration files -->
|
||||
<java classname="games.stendhal.tools.CleanWhitespace">
|
||||
<classpath>
|
||||
<pathelement path="${build_stendhaltools}"/>
|
||||
</classpath>
|
||||
<arg value="${ant_modules}" />
|
||||
<arg value="xml" />
|
||||
</java>
|
||||
</target> <!-- clean_whitespace -->
|
||||
|
||||
|
||||
<target name="cleanwhitespace" depends="clean_whitespace" description="Alias of clean_whitespace."/>
|
||||
|
||||
|
||||
<target name="postman" description="Build postman bot.">
|
||||
<!-- Build postman bot. -->
|
||||
<target name="postman">
|
||||
<mkdir dir="${buildroot}/buildbot"/>
|
||||
<javac srcdir="${src}" destdir="${buildroot}/buildbot" debug="${javac.debug}" debuglevel="${javac.debuglevel}" source="1.8" target="1.8" deprecation="${javac.deprecation}" includeantruntime="false">
|
||||
<include name="games/stendhal/bot/postman/*.java"/>
|
||||
|
|
@ -100,7 +111,8 @@
|
|||
</target> <!-- postman -->
|
||||
|
||||
|
||||
<target name="signupdates" description="Sign updates." depends="compile_stendhaltools,jardiff" unless="exclude.signing">
|
||||
<!-- Sign updates. -->
|
||||
<target name="signupdates" depends="compile_stendhaltools,jardiff" unless="exclude.signing">
|
||||
<taskdef name="updatesigner" classname="games.stendhal.tools.updateprop.UpdateSigner">
|
||||
<classpath>
|
||||
<pathelement path="."/>
|
||||
|
|
@ -116,7 +128,8 @@
|
|||
</target> <!-- signupdates -->
|
||||
|
||||
|
||||
<target name="jardiff" depends="client_build" unless="exclude.jardiff" description="Generate release changes info.">
|
||||
<!-- Generate release changes info. -->
|
||||
<target name="jardiff" depends="client_build" unless="exclude.jardiff">
|
||||
<echo>Creating update from ${version.old} to ${version}</echo>
|
||||
<delete>
|
||||
<fileset dir="${build-archive}">
|
||||
|
|
@ -160,8 +173,9 @@
|
|||
</target> <!-- jardiff -->
|
||||
|
||||
|
||||
<!-- Run enemy balancer. -->
|
||||
<!-- USAGE: ant balance -Dcreature="<creature_name>" -->
|
||||
<target name="balance" description="Run enemy balancer." depends="compile_stendhaltools,server_build">
|
||||
<target name="balance" depends="compile_stendhaltools,server_build">
|
||||
<java classname="games.stendhal.tools.BalanceRPGame">
|
||||
<classpath>
|
||||
<pathelement path="${build_stendhaltools}"/>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
site_name: Stendhal 1.48 Reference Documentation
|
||||
site_name: Stendhal 1.49.5 Reference Documentation
|
||||
site_description: A fun, friendly, & free multiplayer online adventure game.
|
||||
copyright: Copyright © 2003-2024 Stendhal
|
||||
copyright: Copyright © 2003-2026 Stendhal
|
||||
site_url: https://stendhalgame.org/
|
||||
nav:
|
||||
- Index: /reference/
|
||||
|
|
|
|||
|
|
@ -16,18 +16,18 @@
|
|||
-->
|
||||
|
||||
<shop name="deniran_accessories" type="outfit">
|
||||
<outfit name="white balloon" layers="detail=2" price="50000"/>
|
||||
<outfit name="black balloon" layers="detail=3" price="50000"/>
|
||||
<outfit name="bone" layers="detail=4" price="100000"/>
|
||||
<outfit name="umbrella" layers="detail=7" price="50000"/>
|
||||
<outfit name="sword" layers="detail=8" price="250000"/>
|
||||
<outfit name="knife" layers="detail=9" price="125000"/>
|
||||
<outfit name="spear" layers="detail=10" price="150000"/>
|
||||
<outfit name="bow" layers="detail=11" price="175000"/>
|
||||
<outfit name="axe1" layers="detail=12" price="250000"/>
|
||||
<outfit name="axe2" layers="detail=13" price="250000"/>
|
||||
<outfit name="kite shield" layers="detail=14" price="225000"/>
|
||||
<outfit name="shield" layers="detail=15" price="225000"/>
|
||||
<outfit name="white balloon" layers="detail=2" price="25000"/>
|
||||
<outfit name="black balloon" layers="detail=3" price="25000"/>
|
||||
<outfit name="bone" layers="detail=4" price="50000"/>
|
||||
<outfit name="umbrella" layers="detail=7" price="25000"/>
|
||||
<outfit name="sword" layers="detail=8" price="125000"/>
|
||||
<outfit name="knife" layers="detail=9" price="62500"/>
|
||||
<outfit name="spear" layers="detail=10" price="75000"/>
|
||||
<outfit name="bow" layers="detail=11" price="87500"/>
|
||||
<outfit name="axe1" layers="detail=12" price="125000"/>
|
||||
<outfit name="axe2" layers="detail=13" price="125000"/>
|
||||
<outfit name="kite shield" layers="detail=14" price="112500"/>
|
||||
<outfit name="shield" layers="detail=15" price="112500"/>
|
||||
<merchant name="Gwen" flags="configure,noOffer,removeDetailColor,confirmTemp,confirmBalloon,resetBeforeChange"
|
||||
note="do not expire"/>
|
||||
</shop>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1097,6 +1097,7 @@ venom gland=
|
|||
You see the venom gland of a giant king cobra. It is filled with deadly toxin.=
|
||||
|
||||
pelt=
|
||||
You see a pelt of animal skin. It's used to make clothes and leather armor.=
|
||||
|
||||
leather thread=
|
||||
You see a strand of sturdy leather thread.=
|
||||
|
|
@ -1265,6 +1266,9 @@ You see an imperial ring. It is imbued with the strength of a king.=
|
|||
enhanced imperial ring=
|
||||
You see an enhanced imperial ring. It eminates the auras of strength and defense.=
|
||||
|
||||
ring of clarity=
|
||||
You see a ring of clarity. You feel more aware while wearing it.=
|
||||
|
||||
|
||||
## scrolls
|
||||
|
||||
|
|
@ -1407,6 +1411,9 @@ You see a silvery gm token. Does it bring you pride?=
|
|||
bronze gm token=
|
||||
You see a bronze gm token. Does it bring you pride?=
|
||||
|
||||
four-leaf clover=
|
||||
You see a lucky four-leaf clover. What are the chances of finding one!?=
|
||||
|
||||
|
||||
## swords
|
||||
|
||||
|
|
@ -1635,6 +1642,7 @@ You see a killer bat which will suck your blood!=
|
|||
giant bat=
|
||||
|
||||
giant killer bat=
|
||||
You see a giant killer bat. As if small wasn't pesky enough, these giant ones are capable of taking down anyone who dares come before them.=
|
||||
|
||||
piglet=
|
||||
You see a piglet, a bit dirty.=
|
||||
|
|
@ -1702,6 +1710,7 @@ black bear=
|
|||
You see a strong black bear which hibernates in winter.=
|
||||
|
||||
polar bear=
|
||||
You see a polar bear which lives in the icy desert. Beware! It can take you down with its powerful claws!=
|
||||
|
||||
|
||||
## animal_aquatic
|
||||
|
|
@ -2268,6 +2277,7 @@ cannibal=
|
|||
You see a cannibal. He hunts you for cooking and eating your fresh meat! It's useless to tell him that your flesh is not good, better fight him or run away!=
|
||||
|
||||
elder cannibal=
|
||||
You see an elder cannibal. For years it has eaten humans. It will not stop until its hunger is satisfied.=
|
||||
|
||||
cannibal warrior=
|
||||
You see a cannibal warrior.=
|
||||
|
|
|
|||
|
|
@ -1,112 +1,112 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.8" tiledversion="1.8.4" orientation="orthogonal" renderorder="right-down" width="128" height="128" tilewidth="32" tileheight="32" infinite="0" nextlayerid="9" nextobjectid="1">
|
||||
<tileset firstgid="1" name="ground/brown" tilewidth="32" tileheight="32" tilecount="5" columns="5">
|
||||
<image source="../../tileset/ground/brown.png" trans="ff00ff" width="160" height="32"/>
|
||||
</tileset>
|
||||
<tileset firstgid="6" name="logic/collision" tilewidth="32" tileheight="32" tilecount="1" columns="1">
|
||||
<image source="../../tileset/logic/collision.png" width="32" height="32"/>
|
||||
</tileset>
|
||||
<tileset firstgid="7" name="logic/creature/chaos" tilewidth="32" tileheight="32" tilecount="7" columns="7">
|
||||
<image source="../../tileset/logic/creature/chaos.png" width="224" height="32"/>
|
||||
</tileset>
|
||||
<tileset firstgid="14" name="ground/ground" tilewidth="32" tileheight="32" tilecount="33" columns="3">
|
||||
<image source="../../tileset/ground/ground.png" width="96" height="352"/>
|
||||
</tileset>
|
||||
<tileset firstgid="47" name="ground/water/pool" tilewidth="32" tileheight="32" tilecount="72" columns="3">
|
||||
<image source="../../tileset/ground/water/pool.png" width="96" height="768"/>
|
||||
</tileset>
|
||||
<tileset firstgid="119" name="ground/brown_edges" tilewidth="32" tileheight="32" tilecount="18" columns="6">
|
||||
<image source="../../tileset/ground/brown_edges.png" width="192" height="96"/>
|
||||
</tileset>
|
||||
<tileset firstgid="137" name="ground/brown_corners" tilewidth="32" tileheight="32" tilecount="8" columns="4">
|
||||
<image source="../../tileset/ground/brown_corners.png" width="128" height="64"/>
|
||||
</tileset>
|
||||
<tileset firstgid="145" name="ground/earth_edges" tilewidth="32" tileheight="32" tilecount="18" columns="6">
|
||||
<image source="../../tileset/ground/earth_edges.png" width="192" height="96"/>
|
||||
</tileset>
|
||||
<tileset firstgid="163" name="ground/grass_corners" tilewidth="32" tileheight="32" tilecount="24" columns="6">
|
||||
<image source="../../tileset/ground/grass_corners.png" width="192" height="128"/>
|
||||
</tileset>
|
||||
<tileset firstgid="187" name="ground/rock/green_crystal2" tilewidth="32" tileheight="32" tilecount="20" columns="5">
|
||||
<image source="../../tileset/ground/rock/green_crystal2.png" width="160" height="128"/>
|
||||
</tileset>
|
||||
<tileset firstgid="207" name="ground/rock/pebbles" tilewidth="32" tileheight="32" tilecount="3" columns="1">
|
||||
<image source="../../tileset/ground/rock/pebbles.png" width="32" height="96"/>
|
||||
</tileset>
|
||||
<tileset firstgid="210" name="ground/rock/blue_crystal" tilewidth="32" tileheight="32" tilecount="20" columns="5">
|
||||
<image source="../../tileset/ground/rock/blue_crystal.png" width="160" height="128"/>
|
||||
</tileset>
|
||||
<tileset firstgid="230" name="ground/rock/rocks_3" tilewidth="32" tileheight="32" tilecount="16" columns="4">
|
||||
<image source="../../tileset/ground/rock/rocks_3.png" width="128" height="128"/>
|
||||
</tileset>
|
||||
<tileset firstgid="246" name="plant/bush/various_small" tilewidth="32" tileheight="32" tilecount="9" columns="3">
|
||||
<image source="../../tileset/plant/bush/various_small.png" width="96" height="96"/>
|
||||
</tileset>
|
||||
<tileset firstgid="255" name="plant/mosses" tilewidth="32" tileheight="32" tilecount="16" columns="4">
|
||||
<image source="../../tileset/plant/mosses.png" width="128" height="128"/>
|
||||
</tileset>
|
||||
<tileset firstgid="271" name="logic/creature/hybrid" tilewidth="32" tileheight="32" tilecount="16" columns="8">
|
||||
<image source="../../tileset/logic/creature/hybrid.png" trans="ff00ff" width="256" height="64"/>
|
||||
</tileset>
|
||||
<tileset firstgid="287" name="ground/grass_2" tilewidth="32" tileheight="32" tilecount="21" columns="3">
|
||||
<image source="../../tileset/ground/grass_2.png" width="96" height="224"/>
|
||||
</tileset>
|
||||
<tileset firstgid="308" name="ground/water/whirlpool" tilewidth="32" tileheight="32" tilecount="8" columns="1">
|
||||
<image source="../../tileset/ground/water/whirlpool.png" width="32" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="316" name="logic/creature/mythical_being" tilewidth="32" tileheight="32" tilecount="24" columns="8">
|
||||
<image source="../../tileset/logic/creature/mythical_being.png" width="256" height="96"/>
|
||||
</tileset>
|
||||
<tileset firstgid="340" name="building/wall/int_sandstone" tilewidth="32" tileheight="32" tilecount="15" columns="3">
|
||||
<image source="../../tileset/building/wall/int_sandstone.png" width="96" height="160"/>
|
||||
</tileset>
|
||||
<tileset firstgid="355" name="building/entrance/shadow" tilewidth="32" tileheight="32" tilecount="3" columns="1">
|
||||
<image source="../../tileset/building/entrance/shadow.png" width="32" height="96"/>
|
||||
</tileset>
|
||||
<tileset firstgid="358" name="plant/flower/hothouse_flowers" tilewidth="32" tileheight="32" tilecount="72" columns="6">
|
||||
<image source="../../tileset/plant/flower/hothouse_flowers.png" width="192" height="384"/>
|
||||
</tileset>
|
||||
<tileset firstgid="430" name="logic/creature/insect" tilewidth="32" tileheight="32" tilecount="5" columns="5">
|
||||
<image source="../../tileset/logic/creature/insect.png" width="160" height="32"/>
|
||||
</tileset>
|
||||
<layer id="1" name="0_floor" width="128" height="128">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu2cy4rbQBBFFfIHWSZg8JcMhsAku0wW8x2B+X9IDDHRKGqpH/W4VX0Xd+lRVZ2jatmD/fphWV4ZhmEYhmEYhmEYhoHPx6Uc79oYH+7knzc13Mk/Z1rYk3/stLIm/zwh93nD+36+SDAn/7gh+zkifZ+TPX60mZM9Zqy4kz1OLJmTPU48uJP/nLzJPjZ7ib/lPYMZo3Gvkjl+NPcz2WPHYjeTO154Hs8bsp83fBafM5rPeAxuRt/T0YO4kWRP/rEizZ4exMgIT3oQN1LcuBfiRYMRPcCPNhc+J+DGkgMdwIn37OkBPnereSPWlDHoM6YHGLNlrXkScZZ8Lph7fnw2nHtmvb0g98Q52fXl0aNVTZFmgsBfqnfPehD6j8hacg5edWbjjTTTSLVm4o4yz2j1RmeONs9o9ZI/+WdxIFoP3lyzuRCtZm+W2TyIUmdGp8gSLz38vF2IuHfQ08rMYy9EPncipGe2Vh54nDPWfiNkpB9JF0b2DQLzzA54zlFj1si1oTrQ2gvajCP5icof7V5DqCELf00HtDhEYJ/VgdGeZuMfyYGWuXl4R/44DpB/Xv418yP/3PzPZkj+svV+Xv7Fm3vtDMlfh//XP/nyN8gOkL88/9uK/V6Q+Es4QP7v+a/v/ZrM5IC2VxH5Wzigzb+WF/nXRYqJtQNn15mB/7MQf2kHpO/Pnmtp1IzGX2IHaPGx4l+6FvnXs9biZOmA5i5BYr/lX3MGeNTYMk9v7pH5n+0ArxrpgD9/lJq1HcvigCR/tJrJX67nTwH504Gc/Fvr15xLRA96ajrjb82+tY9oDmi4MFIHIv/W3qI6MOKC1LUz8O+dpTd3hCCe/6OMou8D8h/nRAf6+O99BuzNvZeR1b6JnDv/KDugt0c6MDd/etDG/wcofwku3jvHm3eJP/r7QE8Heq5ptVtGr1HLP5sDvR5I/23N2rPzl7qPNK7pPZdZ+Hs5cHZd75nMxN/TgVIN3vMY4X/bYY/OH8kDlPTyv9/7P5f/Pw/07oceyPde2v17Z4F3X9b8I3rQ2tuW/X33v5F/OA96e9q79zPw1/QAyYfRHlr40wE8D6T5P5/wj+jAuvarsg+R2D/47+2AX0n5r6O9F7T8kKynxP9tycP/yAFvH7yzx399Btx25uTNUtsFbybe/Gu+C+zNkB7o8rf+LrB3ZvWg9P+f2t+D8OZGD/T49/wmkDc/eiDHv9eBbE5k9uCMPx3IvQ/W/I8ckPIgqwveHC3404P3/C8JPOjhX/veIKsfR/yjObDl37IDXjYZ5X05mCmKI+s615mNf8mJpwpmT4WUZluas4YXNde+LPu1zs7/aDc88r3jddv9IOHH3t5pzfa1Ec+BPf7SPmj59K0QK/4ZzoEa/mg+1PpS8mObK/l3p4cPoldXIQ9m49/qBvpueeyDrQu1bkR7BtDkL+2P5Rm1PhvOEpl/FBckd1Drs8SZBxnYZ/ZD4lw48iDD54D0oN+DyOx/A/Jq0JkAAAEA
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="1_terrain" width="128" height="128">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu2dS48cNRDHPUoUKQp8JT5FVgQWVpsD3wEOUQ6QA5G4ceLUIHGCj8GR55lTeIblERFIwkoBMcVOhdpaP6r86LZ76ic5k52Z7umZf7lctstu5wzDMAzDMAzDMAzDGIHDjXOveMrLm6WvzGgJ6n5zW566s4LA/181/VcJ1R34i7xG7cD0Xx+HO91P2fNPSfndWf0fnVCbfpNoChpTOzjdPXd9+56XtuVF039IDpnOPnj9p1i9Hxeq/Z/ufEznPH9j20/twfQfj1hMF+KUPJr+Y3MU0ezL3SOv+1x3bPut3e+XVFxHNZb4AHqMad8nhx6dJdqiro8E7zXt+4O36SG4LfwqPP+JM5/fG766XhMeA5j2fSCt65xfCj4T/IbF+svA4zicg5GA43NQDnb6feF53wN3/px/b8s/7BxW9+eHjtFINYe66tOM9vuekPdyqM2Y7svA51uRk8gx1xOaxfr9FPPzyxHS3Qedf5HU0yNyTl9sZ/V9WSRzMSW++QY71nz88vA+XKjOW997fWB95zEYz61CrF1eDxJfT7Ecm/XA+3SSMVjTf2ykY7W+/vjD3ePxxnKtR+TQE9v54rzfPM/z/pqNw45HatyFao79u4PAMfBe8wNjkBrL4X152g8Hm3niOQYxO+iX1PycpC9Px2oOEuMCaAe2Hmt5pGN42nG7UHsA+ObzzDfMi2ROHuflcsbwbiT8AJ6fY3bQnlSdrzW3wtsEDcdmA9VJ1fmS+p6Cz+XE7AH9gvmCOlDdQ7m1c+fM3BD6BehTmC/Ip0V8V5NUrIiYL9AjbeeXnqOV2gD2Hc0G4khi+97m5qW5XoD5gouk5mtwnVwvdZ4D+n+vPGbffYE0Fwfprc5TjiKxqQ/8rvtmAzlraHqt8xT0/39kHMvHk+eyh9B61dpj21xzTT3puc5TQu2/b04ptr8HcFzpt0/pKl3Xor0e3/oZKSOshfDVm5L1gHytP8DHkFr5hVhd9OVJ+ea+cu2KMoKPB7BP+tidxXv4Pb/OPF/s9+e+Y+k8lNj8eIyvAs+PtgZCm0Ma4pQ9Ivg7hXKSSvX/sezw6ixtz1okfXzeB4zlmp86v+8PMdrvlWK07wP639s+fkOeA7/vyytqUVr6yFzf/iDzONj/bLS+r6/+994/0fS1ahynZam+bw6o/7fb8p3rX/va/gfmOCA3Psc2Qsfw53seG+c5AD1r3wJpjiQnlWPto7Vf8PXhe7S5XtHYAsZ50nlSH7XGQfjc4g/urC9Pr9PQkdKV/q7SvJkYObZAdcf2O3adhg5fbIzjh744Pze3MidekI7b1NRfOrfSeu5lTmI6xvp6mtzK2Pl9vxlqD/10uscWwOfqSvVvsT/gSH3kVDsg/S6l9nCs1OGeOxvTydG/9Z6QQM99Io7EBrTfRRozPIy/HEQz91Qyt1nKKPGJZJw8x6/lxAy+uSe+L6f0d601/5PLKG2BtJ9XYs8xW9CMTz1RXIcmx7MVI9kA16fVWF9pvDCS/sAo7QAS+91a5MTD5+GYjm9uFfoCdJ7W9G+LpD2o+Z18OsXaBNO/PZoxwlJQJ6zjqfwK038eYjZQsw0IrcWguTa0X7BW/Wk/tRdiv2Etu/Z9RizPaq36c3oYUw75AGifa/kA0Ck0FnSf/F877je6/sjSOTex37GGDUjHH7Q552vRnzO3Pfj0oXsq1fh++Bl0rpffT1n7OWvVnzPHGFNrHwCE5g2wL2j6h6E+4barbw+15gpzPwvGh0x/GaB/izlIen8UH7XHBDDeA04yzl+Sv1aTlvq/vS1vsXKHvF5zPeKcY0K+e7GU7Au4FK1yzlH3O6k3EmrYwlxjQjVZsh1oUfdBe43uPkpsIRUL9jBuQVnSB9TWv4b2HLzG14TXqtlDbd9tQKP/R4nXW2jvQ5rzN9o+eku0Axr9Jxe3gduF1yJFes2aOtWDL5hb/5zY773Ia73pD3AbCM3b97CXYsn+0BpK9kYJ6T+X7we0PlvrB3poD1rYQumeOJc3Yf3nqvuUEj+QYmlfQClZ41Z7T5ye9Nf25bR5nT3ZABC7/+9ce3z0pD8lpx8rua9XL+1BL4T0f2db3pjzQhg5+ktjQ8DswLkrkfYfWNIH5I7rjRwXLMHkwmMAS7cBSM48nCbW3mcbgH22em0DkNJ1YD4b4HuX7mt78FzHbQBSOqeh6W/tkx1c3n3HyfXdBtTSJJVPAuTmflFG3Duq134gpbSd1sQFJTmvvB/6uWvjV0J7yGg+A/f87T0GQFrnftb4XK4/rCXC3OIadkD3qoI8xU+35TN35tugaH1XbBwY6MkHALXXgtX+XDgnakJBG/jEyfbJj+2fHxrbAF+T03aNpD9Q0w/E1hogJ+RzU/VXO+9Ltcy5PwyAcQ2cax/0B2q3Bdr2INTmYpypvcdFDrgvN123ptEf+n+wR/eI+gO14ypNXEDrLd9T7Kc6l5N1nxTtHNFo7b+PJe3AR+7+6Ln34IB2Pzf3+91t+TDy+gj6I7XzX2vsR0uRtguhe+Lwc5XkA1zdpLUHRtK/1Vh+KEb4WXke2Fsu1zfQNeu17ocV8/vISPoDrcdwS31Cjbiwlp+T6N/bGJCU1vN6kj3sWgDjB7X0n1x6HQAwqg3ccvOMw6dyudA+HsdP8x8+G4LnWt0PT+IDgNHaAeDNbblL/l5qfi8n12+u+3utWX8AbADXKqMtLL3HTU+sXX8K2sJd9vw+zfsj2J+Q6j9qDODD5xOAfbSDycliQGANPoDj8wn7ZgcaH/C6W48foOyzHUj1R9AOsKzJHmLx4lrtQKs/h9vDWmyil/5jK67uvsfk5DGAlLXEi/viD0p9gA/qF9ZgC7fY32taO9JCf8oaYkeuPzC6L8A5zMnVbwN8+GKFUeIGn/7IqPddoLT2ARJS9rGUjVxyK9SfXXMP+ksI2UiJXVwSlNXpz5i25X1S5mgPaiLxHSUllis1YhxA8w0fwT/s2ic3tj0swWh+4HLgevkaaWBy+bbwsTtvS2u1q9H0v4Dw+icn1xO0/yBwngduvr4H54UG51zTmMAzyPe5H37XMyZ33h5C2oeOobYQ8xu1fEltOxjBB9DcNFjfdqWja56cznYeeY5d0g5G0B+R5i5quMqP8ZxDu9bxQjwSua5rm/I2JdcWWt2DYSku5Dlv/tdX0hbkcE1gP8H3EiZXHl9q7WCkuq+lRh5rjRLySc/vnue+osa4VsoOaq3JmYt/ATb8NvgAAAEA
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="3" name="2_object" width="128" height="128">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu3bMQrAIAwFUHOrnqU6tPe/RCkOHUUQrPjelDGQ5ROSlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2dcbsDpjpMn8AoEORHQAAaMhRc6O9437eXeMdXw0AAAAAAAAAAACMcbjLAwAW5b8A+sn/AAAAAAAAAAAAAPAvD8b9VLMAAAEA
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="4" name="3_roof" width="128" height="128">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu3c20rDQBAG4Lz/O1lBL6q3HloVD/sceuMUWppeGKOwmbL7ffBDSgM7sJDdzEKGAQAAAAAAAAAAAIBaPiNf2UUAAAAAAAAAAAAAQEdKdgEAAFRVRtebrCJY1F3kPrsI0mwjTxP/l4XqIMdr5C3yuP/tud+f58hLdhGkeY98ZBcB/MvDcFy/6Y/1u2/Wb8b0dNq3e0//6Rtbv/V0aNuhpwMAQJt27wIluwigqpJdAGnKjHv0/fqm79e+qbNefb/2Oevtm7NeDuz3+ma/1zf7PQAAAAAAAAAAMlxEVtlFcGI8J7eVx7qKXFceg79Zck7WkZuFxmKeqTm5rDhu7WcNAHA+rPsA0Laa/QMAAAAAAAAAAAAAAADOxzeEbpmpAAABAA==
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="5" name="4_roof_add" width="128" height="128">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu3OAQ0AAAgDoPfPZyBj3E1IQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwy7QDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPLYaZVTEAAAEA
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="6" name="objects" width="128" height="128">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu3cQQqDMBAF0Liytr1C73/NIrgqoVA1nZh5b+PGxQdlNF9MKQAAAAAAAABAhHt0AAAAAAAAgIE8ogMAAAAAX83b0Roe8nhGBwAAAICij8pqTy/xmk6PcViPma7MPBjf5zWeq2cBtOeZA0BrvscDe9XmR6v3V91Wv3QmwEp/AQAAwC9u0QEAAAAAACAx/xBAbvbzBQAAAKBGXwQAAFyNven+w3oRODIHzBDO4l4a0xIdAOiOeQ8AAAAAAAAAAAAAAJDXG8ZnpKUAAAEA
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="7" name="collision" width="128" height="128" visible="0" opacity="0.58">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu2T22prQQxD91P//5NLHgohNMlcbC95tgSihXP2WNZyf67r+rFt27Zt27Zt27Zt27bl/Z/oTDbD/U90Npvj/vfTPs/fROezazi/E53b5thfAtltjv0lkN9muF8CO9gcfzq/ncN55Bt6JzuW+Yzo3WyG+yWwn73HfPdG6F3tee6j373+2/P/p3e157XzDr2rvcY+6i16XzuPVdQ7NsOdzmabvV3H/Fl0TptjfwlktTn2l0Bem2N/CWS2c5mP3gW9hx3P/k8j39C72DH8d2+G3sleZxj1zspbNsf9SnozaoatyX7lBiLm2ftsqudVZrAZ9iv3QHd0ohW7/ia6sxOs3u830fk6u0unI6IzdnOnHkdF5+zgrt3NiM6q5u59rYjOTPukjlZF51buic5awZ/cuSqP4u6q/J/VNU/Wuyq+nn6+/p4lBf6Rohkq/V2NqEvOUdEcM9hn9m7+Ou6wQ4V25tD9RHRK56H574ruaKVTOgO9f6bo/ez4W9j9xtb3J63ezac3ojI/56E77O53WrmZT8rKS/fX3e+08+03ReRbecuOv4GdeyAyRu9QkanTDax2OfutGvPMfJ1vQLXfKtFMIzupmPFp9k4WSjRTxRuIYNKB/Z9oppF8yNtbzaEgmmU0D2reynwF0Sw73MCMzJ+/gYw5o7zMn7+Bylvbma0gml8WF4L97FwFrWSlmY/0WHVjO/MUNJuVZj3LJ3vGziwFncC/6gY+zTJ/8zf/+96A+fOO2HN1ZkbmCq3kpDtb6ZO+TcUbWM2YsVt2nzTju/GvyjUzm+asdgM7+ap2yeqT5q1wAxn8szLO5u14A9WK5l+hjE5p7gT/3Wxd+He7gewuo/J04t/1BiJ7jc5AsP80P7JHmnfUHWTO7sh/JjPNWs3f+iGV9fdEd67kkW4oRe4V/f4pHumEUvRuWXM6e6QLBWXfAs1Bhf+7Lmhl7Ro9o5tHe6CVvXPWLHWP7k+rkn/GTFWP7q6iqv0jZmXmruZ/8g2M7pbZ7W7215kn83+I4L86Nyt/RMaZN9SkfgOk7sD/oegbmNlVjf/Py+934P9Q1g3M7qzS2e5+Kvc8K5U7oBS1V+cOHrrbHUTu0233/5TJP6KPqC4zdjiB/0NVN0D2Us2/2w08VHkHlf1k5VXaMUrVN5DZXUUe87+PV/rqKLpnVa901V1050pe7egE0d0reLWf00Rz6Mbfd3CGo7s4RTQXBf5RPXQXzYjkH7V/d9GcSP7RHXQXzYziH71/V9HMaP5VHaiKZqbQMZ2bvBF6Z9X+6F2q7oLeTb2n1Zl0F3f0fwzURHd0sk8U3Wknq4jMQjPoyF/pdqJEs6DdXVE70BxUfUfRnav6taPTRfdtf7/DCtH7RvsXoMjHOgAAAQA=
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="8" name="protection" width="128" height="128" visible="0">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu3BAQEAAACAkP6v7ggKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAauuOl9cAAAEA
|
||||
</data>
|
||||
</layer>
|
||||
</map>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.8" tiledversion="1.8.4" orientation="orthogonal" renderorder="right-down" width="128" height="128" tilewidth="32" tileheight="32" infinite="0" nextlayerid="9" nextobjectid="1">
|
||||
<tileset firstgid="1" name="ground/brown" tilewidth="32" tileheight="32" tilecount="5" columns="5">
|
||||
<image source="../../tileset/ground/brown.png" trans="ff00ff" width="160" height="32"/>
|
||||
</tileset>
|
||||
<tileset firstgid="6" name="logic/collision" tilewidth="32" tileheight="32" tilecount="1" columns="1">
|
||||
<image source="../../tileset/logic/collision.png" width="32" height="32"/>
|
||||
</tileset>
|
||||
<tileset firstgid="7" name="logic/creature/chaos" tilewidth="32" tileheight="32" tilecount="7" columns="7">
|
||||
<image source="../../tileset/logic/creature/chaos.png" width="224" height="32"/>
|
||||
</tileset>
|
||||
<tileset firstgid="14" name="ground/ground" tilewidth="32" tileheight="32" tilecount="33" columns="3">
|
||||
<image source="../../tileset/ground/ground.png" width="96" height="352"/>
|
||||
</tileset>
|
||||
<tileset firstgid="47" name="ground/water/pool" tilewidth="32" tileheight="32" tilecount="72" columns="3">
|
||||
<image source="../../tileset/ground/water/pool.png" width="96" height="768"/>
|
||||
</tileset>
|
||||
<tileset firstgid="119" name="ground/brown_edges" tilewidth="32" tileheight="32" tilecount="18" columns="6">
|
||||
<image source="../../tileset/ground/brown_edges.png" width="192" height="96"/>
|
||||
</tileset>
|
||||
<tileset firstgid="137" name="ground/brown_corners" tilewidth="32" tileheight="32" tilecount="8" columns="4">
|
||||
<image source="../../tileset/ground/brown_corners.png" width="128" height="64"/>
|
||||
</tileset>
|
||||
<tileset firstgid="145" name="ground/earth_edges" tilewidth="32" tileheight="32" tilecount="18" columns="6">
|
||||
<image source="../../tileset/ground/earth_edges.png" width="192" height="96"/>
|
||||
</tileset>
|
||||
<tileset firstgid="163" name="ground/grass_corners" tilewidth="32" tileheight="32" tilecount="24" columns="6">
|
||||
<image source="../../tileset/ground/grass_corners.png" width="192" height="128"/>
|
||||
</tileset>
|
||||
<tileset firstgid="187" name="ground/rock/green_crystal2" tilewidth="32" tileheight="32" tilecount="20" columns="5">
|
||||
<image source="../../tileset/ground/rock/green_crystal2.png" width="160" height="128"/>
|
||||
</tileset>
|
||||
<tileset firstgid="207" name="ground/rock/pebbles" tilewidth="32" tileheight="32" tilecount="3" columns="1">
|
||||
<image source="../../tileset/ground/rock/pebbles.png" width="32" height="96"/>
|
||||
</tileset>
|
||||
<tileset firstgid="210" name="ground/rock/blue_crystal" tilewidth="32" tileheight="32" tilecount="20" columns="5">
|
||||
<image source="../../tileset/ground/rock/blue_crystal.png" width="160" height="128"/>
|
||||
</tileset>
|
||||
<tileset firstgid="230" name="ground/rock/rocks_3" tilewidth="32" tileheight="32" tilecount="16" columns="4">
|
||||
<image source="../../tileset/ground/rock/rocks_3.png" width="128" height="128"/>
|
||||
</tileset>
|
||||
<tileset firstgid="246" name="plant/bush/various_small" tilewidth="32" tileheight="32" tilecount="9" columns="3">
|
||||
<image source="../../tileset/plant/bush/various_small.png" width="96" height="96"/>
|
||||
</tileset>
|
||||
<tileset firstgid="255" name="plant/mosses" tilewidth="32" tileheight="32" tilecount="16" columns="4">
|
||||
<image source="../../tileset/plant/mosses.png" width="128" height="128"/>
|
||||
</tileset>
|
||||
<tileset firstgid="271" name="logic/creature/hybrid" tilewidth="32" tileheight="32" tilecount="16" columns="8">
|
||||
<image source="../../tileset/logic/creature/hybrid.png" trans="ff00ff" width="256" height="64"/>
|
||||
</tileset>
|
||||
<tileset firstgid="287" name="ground/grass_2" tilewidth="32" tileheight="32" tilecount="21" columns="3">
|
||||
<image source="../../tileset/ground/grass_2.png" width="96" height="224"/>
|
||||
</tileset>
|
||||
<tileset firstgid="308" name="ground/water/whirlpool" tilewidth="32" tileheight="32" tilecount="8" columns="1">
|
||||
<image source="../../tileset/ground/water/whirlpool.png" width="32" height="256"/>
|
||||
</tileset>
|
||||
<tileset firstgid="316" name="logic/creature/mythical_being" tilewidth="32" tileheight="32" tilecount="24" columns="8">
|
||||
<image source="../../tileset/logic/creature/mythical_being.png" width="256" height="96"/>
|
||||
</tileset>
|
||||
<tileset firstgid="340" name="building/wall/int_sandstone" tilewidth="32" tileheight="32" tilecount="15" columns="3">
|
||||
<image source="../../tileset/building/wall/int_sandstone.png" width="96" height="160"/>
|
||||
</tileset>
|
||||
<tileset firstgid="355" name="building/entrance/shadow" tilewidth="32" tileheight="32" tilecount="3" columns="1">
|
||||
<image source="../../tileset/building/entrance/shadow.png" width="32" height="96"/>
|
||||
</tileset>
|
||||
<tileset firstgid="358" name="plant/flower/hothouse_flowers" tilewidth="32" tileheight="32" tilecount="72" columns="6">
|
||||
<image source="../../tileset/plant/flower/hothouse_flowers.png" width="192" height="384"/>
|
||||
</tileset>
|
||||
<tileset firstgid="430" name="logic/creature/insect" tilewidth="32" tileheight="32" tilecount="5" columns="5">
|
||||
<image source="../../tileset/logic/creature/insect.png" width="160" height="32"/>
|
||||
</tileset>
|
||||
<layer id="1" name="0_floor" width="128" height="128">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu2cy4rbQBBFFfIHWSZg8JcMhsAku0wW8x2B+X9IDDHRKGqpH/W4VX0Xd+lRVZ2jatmD/fphWV4ZhmEYhmEYhmEYhoHPx6Uc79oYH+7knzc13Mk/Z1rYk3/stLIm/zwh93nD+36+SDAn/7gh+zkifZ+TPX60mZM9Zqy4kz1OLJmTPU48uJP/nLzJPjZ7ib/lPYMZo3Gvkjl+NPcz2WPHYjeTO154Hs8bsp83fBafM5rPeAxuRt/T0YO4kWRP/rEizZ4exMgIT3oQN1LcuBfiRYMRPcCPNhc+J+DGkgMdwIn37OkBPnereSPWlDHoM6YHGLNlrXkScZZ8Lph7fnw2nHtmvb0g98Q52fXl0aNVTZFmgsBfqnfPehD6j8hacg5edWbjjTTTSLVm4o4yz2j1RmeONs9o9ZI/+WdxIFoP3lyzuRCtZm+W2TyIUmdGp8gSLz38vF2IuHfQ08rMYy9EPncipGe2Vh54nDPWfiNkpB9JF0b2DQLzzA54zlFj1si1oTrQ2gvajCP5icof7V5DqCELf00HtDhEYJ/VgdGeZuMfyYGWuXl4R/44DpB/Xv418yP/3PzPZkj+svV+Xv7Fm3vtDMlfh//XP/nyN8gOkL88/9uK/V6Q+Es4QP7v+a/v/ZrM5IC2VxH5Wzigzb+WF/nXRYqJtQNn15mB/7MQf2kHpO/Pnmtp1IzGX2IHaPGx4l+6FvnXs9biZOmA5i5BYr/lX3MGeNTYMk9v7pH5n+0ArxrpgD9/lJq1HcvigCR/tJrJX67nTwH504Gc/Fvr15xLRA96ajrjb82+tY9oDmi4MFIHIv/W3qI6MOKC1LUz8O+dpTd3hCCe/6OMou8D8h/nRAf6+O99BuzNvZeR1b6JnDv/KDugt0c6MDd/etDG/wcofwku3jvHm3eJP/r7QE8Heq5ptVtGr1HLP5sDvR5I/23N2rPzl7qPNK7pPZdZ+Hs5cHZd75nMxN/TgVIN3vMY4X/bYY/OH8kDlPTyv9/7P5f/Pw/07oceyPde2v17Z4F3X9b8I3rQ2tuW/X33v5F/OA96e9q79zPw1/QAyYfRHlr40wE8D6T5P5/wj+jAuvarsg+R2D/47+2AX0n5r6O9F7T8kKynxP9tycP/yAFvH7yzx399Btx25uTNUtsFbybe/Gu+C+zNkB7o8rf+LrB3ZvWg9P+f2t+D8OZGD/T49/wmkDc/eiDHv9eBbE5k9uCMPx3IvQ/W/I8ckPIgqwveHC3404P3/C8JPOjhX/veIKsfR/yjObDl37IDXjYZ5X05mCmKI+s615mNf8mJpwpmT4WUZluas4YXNde+LPu1zs7/aDc88r3jddv9IOHH3t5pzfa1Ec+BPf7SPmj59K0QK/4ZzoEa/mg+1PpS8mObK/l3p4cPoldXIQ9m49/qBvpueeyDrQu1bkR7BtDkL+2P5Rm1PhvOEpl/FBckd1Drs8SZBxnYZ/ZD4lw48iDD54D0oN+DyOx/A/Jq0JkAAAEA
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="2" name="1_terrain" width="128" height="128">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu2dS48cNRDHPUoUKQp8JT5FVgQWVpsD3wEOUQ6QA5G4ceLUIHGCj8GR55lTeIblERFIwkoBMcVOhdpaP6r86LZ76ic5k52Z7umZf7lctstu5wzDMAzDMAzDMAzDGIHDjXOveMrLm6WvzGgJ6n5zW566s4LA/181/VcJ1R34i7xG7cD0Xx+HO91P2fNPSfndWf0fnVCbfpNoChpTOzjdPXd9+56XtuVF039IDpnOPnj9p1i9Hxeq/Z/ufEznPH9j20/twfQfj1hMF+KUPJr+Y3MU0ezL3SOv+1x3bPut3e+XVFxHNZb4AHqMad8nhx6dJdqiro8E7zXt+4O36SG4LfwqPP+JM5/fG766XhMeA5j2fSCt65xfCj4T/IbF+svA4zicg5GA43NQDnb6feF53wN3/px/b8s/7BxW9+eHjtFINYe66tOM9vuekPdyqM2Y7svA51uRk8gx1xOaxfr9FPPzyxHS3Qedf5HU0yNyTl9sZ/V9WSRzMSW++QY71nz88vA+XKjOW997fWB95zEYz61CrF1eDxJfT7Ecm/XA+3SSMVjTf2ykY7W+/vjD3ePxxnKtR+TQE9v54rzfPM/z/pqNw45HatyFao79u4PAMfBe8wNjkBrL4X152g8Hm3niOQYxO+iX1PycpC9Px2oOEuMCaAe2Hmt5pGN42nG7UHsA+ObzzDfMi2ROHuflcsbwbiT8AJ6fY3bQnlSdrzW3wtsEDcdmA9VJ1fmS+p6Cz+XE7AH9gvmCOlDdQ7m1c+fM3BD6BehTmC/Ip0V8V5NUrIiYL9AjbeeXnqOV2gD2Hc0G4khi+97m5qW5XoD5gouk5mtwnVwvdZ4D+n+vPGbffYE0Fwfprc5TjiKxqQ/8rvtmAzlraHqt8xT0/39kHMvHk+eyh9B61dpj21xzTT3puc5TQu2/b04ptr8HcFzpt0/pKl3Xor0e3/oZKSOshfDVm5L1gHytP8DHkFr5hVhd9OVJ+ea+cu2KMoKPB7BP+tidxXv4Pb/OPF/s9+e+Y+k8lNj8eIyvAs+PtgZCm0Ma4pQ9Ivg7hXKSSvX/sezw6ixtz1okfXzeB4zlmp86v+8PMdrvlWK07wP639s+fkOeA7/vyytqUVr6yFzf/iDzONj/bLS+r6/+994/0fS1ahynZam+bw6o/7fb8p3rX/va/gfmOCA3Psc2Qsfw53seG+c5AD1r3wJpjiQnlWPto7Vf8PXhe7S5XtHYAsZ50nlSH7XGQfjc4g/urC9Pr9PQkdKV/q7SvJkYObZAdcf2O3adhg5fbIzjh744Pze3MidekI7b1NRfOrfSeu5lTmI6xvp6mtzK2Pl9vxlqD/10uscWwOfqSvVvsT/gSH3kVDsg/S6l9nCs1OGeOxvTydG/9Z6QQM99Io7EBrTfRRozPIy/HEQz91Qyt1nKKPGJZJw8x6/lxAy+uSe+L6f0d601/5PLKG2BtJ9XYs8xW9CMTz1RXIcmx7MVI9kA16fVWF9pvDCS/sAo7QAS+91a5MTD5+GYjm9uFfoCdJ7W9G+LpD2o+Z18OsXaBNO/PZoxwlJQJ6zjqfwK038eYjZQsw0IrcWguTa0X7BW/Wk/tRdiv2Etu/Z9RizPaq36c3oYUw75AGifa/kA0Ck0FnSf/F877je6/sjSOTex37GGDUjHH7Q552vRnzO3Pfj0oXsq1fh++Bl0rpffT1n7OWvVnzPHGFNrHwCE5g2wL2j6h6E+4barbw+15gpzPwvGh0x/GaB/izlIen8UH7XHBDDeA04yzl+Sv1aTlvq/vS1vsXKHvF5zPeKcY0K+e7GU7Au4FK1yzlH3O6k3EmrYwlxjQjVZsh1oUfdBe43uPkpsIRUL9jBuQVnSB9TWv4b2HLzG14TXqtlDbd9tQKP/R4nXW2jvQ5rzN9o+eku0Axr9Jxe3gduF1yJFes2aOtWDL5hb/5zY773Ia73pD3AbCM3b97CXYsn+0BpK9kYJ6T+X7we0PlvrB3poD1rYQumeOJc3Yf3nqvuUEj+QYmlfQClZ41Z7T5ye9Nf25bR5nT3ZABC7/+9ce3z0pD8lpx8rua9XL+1BL4T0f2db3pjzQhg5+ktjQ8DswLkrkfYfWNIH5I7rjRwXLMHkwmMAS7cBSM48nCbW3mcbgH22em0DkNJ1YD4b4HuX7mt78FzHbQBSOqeh6W/tkx1c3n3HyfXdBtTSJJVPAuTmflFG3Duq134gpbSd1sQFJTmvvB/6uWvjV0J7yGg+A/f87T0GQFrnftb4XK4/rCXC3OIadkD3qoI8xU+35TN35tugaH1XbBwY6MkHALXXgtX+XDgnakJBG/jEyfbJj+2fHxrbAF+T03aNpD9Q0w/E1hogJ+RzU/VXO+9Ltcy5PwyAcQ2cax/0B2q3Bdr2INTmYpypvcdFDrgvN123ptEf+n+wR/eI+gO14ypNXEDrLd9T7Kc6l5N1nxTtHNFo7b+PJe3AR+7+6Ln34IB2Pzf3+91t+TDy+gj6I7XzX2vsR0uRtguhe+Lwc5XkA1zdpLUHRtK/1Vh+KEb4WXke2Fsu1zfQNeu17ocV8/vISPoDrcdwS31Cjbiwlp+T6N/bGJCU1vN6kj3sWgDjB7X0n1x6HQAwqg3ccvOMw6dyudA+HsdP8x8+G4LnWt0PT+IDgNHaAeDNbblL/l5qfi8n12+u+3utWX8AbADXKqMtLL3HTU+sXX8K2sJd9vw+zfsj2J+Q6j9qDODD5xOAfbSDycliQGANPoDj8wn7ZgcaH/C6W48foOyzHUj1R9AOsKzJHmLx4lrtQKs/h9vDWmyil/5jK67uvsfk5DGAlLXEi/viD0p9gA/qF9ZgC7fY32taO9JCf8oaYkeuPzC6L8A5zMnVbwN8+GKFUeIGn/7IqPddoLT2ARJS9rGUjVxyK9SfXXMP+ksI2UiJXVwSlNXpz5i25X1S5mgPaiLxHSUllis1YhxA8w0fwT/s2ic3tj0swWh+4HLgevkaaWBy+bbwsTtvS2u1q9H0v4Dw+icn1xO0/yBwngduvr4H54UG51zTmMAzyPe5H37XMyZ33h5C2oeOobYQ8xu1fEltOxjBB9DcNFjfdqWja56cznYeeY5d0g5G0B+R5i5quMqP8ZxDu9bxQjwSua5rm/I2JdcWWt2DYSku5Dlv/tdX0hbkcE1gP8H3EiZXHl9q7WCkuq+lRh5rjRLySc/vnue+osa4VsoOaq3JmYt/ATb8NvgAAAEA
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="3" name="2_object" width="128" height="128">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu3bMQrAIAwFUHOrnqU6tPe/RCkOHUUQrPjelDGQ5ROSlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2dcbsDpjpMn8AoEORHQAAaMhRc6O9437eXeMdXw0AAAAAAAAAAACMcbjLAwAW5b8A+sn/AAAAAAAAAAAAAPAvD8b9VLMAAAEA
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="4" name="3_roof" width="128" height="128">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu3c20rDQBAG4Lz/O1lBL6q3HloVD/sceuMUWppeGKOwmbL7ffBDSgM7sJDdzEKGAQAAAAAAAAAAAIBaPiNf2UUAAAAAAAAAAAAAQEdKdgEAAFRVRtebrCJY1F3kPrsI0mwjTxP/l4XqIMdr5C3yuP/tud+f58hLdhGkeY98ZBcB/MvDcFy/6Y/1u2/Wb8b0dNq3e0//6Rtbv/V0aNuhpwMAQJt27wIluwigqpJdAGnKjHv0/fqm79e+qbNefb/2Oevtm7NeDuz3+ma/1zf7PQAAAAAAAAAAMlxEVtlFcGI8J7eVx7qKXFceg79Zck7WkZuFxmKeqTm5rDhu7WcNAHA+rPsA0Laa/QMAAAAAAAAAAAAAAADOxzeEbpmpAAABAA==
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="5" name="4_roof_add" width="128" height="128">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu3OAQ0AAAgDoPfPZyBj3E1IQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwy7QDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPLYaZVTEAAAEA
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="6" name="objects" width="128" height="128">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu3cQQqDMBAF0Liytr1C73/NIrgqoVA1nZh5b+PGxQdlNF9MKQAAAAAAAABAhHt0AAAAAAAAgIE8ogMAAAAAX83b0Roe8nhGBwAAAICij8pqTy/xmk6PcViPma7MPBjf5zWeq2cBtOeZA0BrvscDe9XmR6v3V91Wv3QmwEp/AQAAwC9u0QEAAAAAACAx/xBAbvbzBQAAAKBGXwQAAFyNven+w3oRODIHzBDO4l4a0xIdAOiOeQ8AAAAAAAAAAAAAAJDXG8ZnpKUAAAEA
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="7" name="collision" width="128" height="128" visible="0" opacity="0.58">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu2T22prQQxD91P//5NLHgohNMlcbC95tgSihXP2WNZyf67r+rFt27Zt27Zt27Zt27bl/Z/oTDbD/U90Npvj/vfTPs/fROezazi/E53b5thfAtltjv0lkN9muF8CO9gcfzq/ncN55Bt6JzuW+Yzo3WyG+yWwn73HfPdG6F3tee6j373+2/P/p3e157XzDr2rvcY+6i16XzuPVdQ7NsOdzmabvV3H/Fl0TptjfwlktTn2l0Bem2N/CWS2c5mP3gW9hx3P/k8j39C72DH8d2+G3sleZxj1zspbNsf9SnozaoatyX7lBiLm2ftsqudVZrAZ9iv3QHd0ohW7/ia6sxOs3u830fk6u0unI6IzdnOnHkdF5+zgrt3NiM6q5u59rYjOTPukjlZF51buic5awZ/cuSqP4u6q/J/VNU/Wuyq+nn6+/p4lBf6Rohkq/V2NqEvOUdEcM9hn9m7+Ou6wQ4V25tD9RHRK56H574ruaKVTOgO9f6bo/ez4W9j9xtb3J63ezac3ojI/56E77O53WrmZT8rKS/fX3e+08+03ReRbecuOv4GdeyAyRu9QkanTDax2OfutGvPMfJ1vQLXfKtFMIzupmPFp9k4WSjRTxRuIYNKB/Z9oppF8yNtbzaEgmmU0D2reynwF0Sw73MCMzJ+/gYw5o7zMn7+Bylvbma0gml8WF4L97FwFrWSlmY/0WHVjO/MUNJuVZj3LJ3vGziwFncC/6gY+zTJ/8zf/+96A+fOO2HN1ZkbmCq3kpDtb6ZO+TcUbWM2YsVt2nzTju/GvyjUzm+asdgM7+ap2yeqT5q1wAxn8szLO5u14A9WK5l+hjE5p7gT/3Wxd+He7gewuo/J04t/1BiJ7jc5AsP80P7JHmnfUHWTO7sh/JjPNWs3f+iGV9fdEd67kkW4oRe4V/f4pHumEUvRuWXM6e6QLBWXfAs1Bhf+7Lmhl7Ro9o5tHe6CVvXPWLHWP7k+rkn/GTFWP7q6iqv0jZmXmruZ/8g2M7pbZ7W7215kn83+I4L86Nyt/RMaZN9SkfgOk7sD/oegbmNlVjf/Py+934P9Q1g3M7qzS2e5+Kvc8K5U7oBS1V+cOHrrbHUTu0233/5TJP6KPqC4zdjiB/0NVN0D2Us2/2w08VHkHlf1k5VXaMUrVN5DZXUUe87+PV/rqKLpnVa901V1050pe7egE0d0reLWf00Rz6Mbfd3CGo7s4RTQXBf5RPXQXzYjkH7V/d9GcSP7RHXQXzYziH71/V9HMaP5VHaiKZqbQMZ2bvBF6Z9X+6F2q7oLeTb2n1Zl0F3f0fwzURHd0sk8U3Wknq4jMQjPoyF/pdqJEs6DdXVE70BxUfUfRnav6taPTRfdtf7/DCtH7RvsXoMjHOgAAAQA=
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="8" name="protection" width="128" height="128" visible="0">
|
||||
<data encoding="base64" compression="gzip">
|
||||
H4sIAAAAAAAACu3BAQEAAACAkP6v7ggKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAauuOl9cAAAEA
|
||||
</data>
|
||||
</layer>
|
||||
</map>
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -2,6 +2,24 @@ Changelog
|
|||
---------
|
||||
---------
|
||||
|
||||
1.49
|
||||
|
||||
*world*
|
||||
- outfit prices in Gwen's shop reduced
|
||||
|
||||
*web client*
|
||||
- improved lighting effects
|
||||
|
||||
*bug fixes*
|
||||
- fixed invalid head outfit index of Mr Ross
|
||||
- fixed silent NPC paths
|
||||
- fixed desktop webview client window freezing on Windows when closed
|
||||
- fixed nativehelper extension process not exiting cleanly on Windows
|
||||
- set User-Agent string for Wikipedia API requests
|
||||
- trimmed large music files to decrease size to 2MB or less
|
||||
- fixed Gourmet achievement
|
||||
|
||||
|
||||
1.48
|
||||
|
||||
*world*
|
||||
|
|
@ -688,7 +706,7 @@ Changelog
|
|||
|
||||
*other*
|
||||
- started to work on a list of all contributors, please help to add to it:
|
||||
https://github.com/arianne/stendhal/blob/master/doc/contributors.md
|
||||
https://codeberg.org/arianne/stendhal/src/commit/master/doc/contributors.md
|
||||
|
||||
|
||||
1.34
|
||||
|
|
@ -1396,7 +1414,7 @@ the huge task of creating & replacing sprite & tileset images.
|
|||
- Support Postgres databases in addition to H2 (recommended) and MySQL
|
||||
- Setup Travis for continuous integration tests and fixed some order dependent tests
|
||||
- Migrated test coverage analysis from Cobertura to Jacoco
|
||||
- Git repository is mirrored instantaneously between Github and Sourceforge in both directions
|
||||
- Git repository is mirrored instantaneously between Codeberg, Github and Sourceforge in both directions
|
||||
- Yearly special event quests now pick up the current year as part of their quest slot automatically
|
||||
- Backend for puzzles
|
||||
|
||||
|
|
@ -2559,7 +2577,7 @@ read https://stendhalgame.org/wiki/Automatic_Software_Updater
|
|||
- Tab completion for online nick names works now without /who called before
|
||||
- orc spearman creature
|
||||
- /atlas /faq and /manual commands to open useful pages in browser
|
||||
- Harold tweets trades, the official stendhal server uses https://twitter.com/stendhaltrade
|
||||
- Harold tweets trades, the official stendhal server uses https://mastodon.social/@stendhaltrade
|
||||
- magical damage types of weapons (fire, ice ...)
|
||||
- resistance/vulnerability of creatures to magical weapons (fire, ice, ...)
|
||||
- attack sweeps look different depending on the attack type
|
||||
|
|
|
|||
Binary file not shown.
755
package-lock.json
generated
755
package-lock.json
generated
|
|
@ -1,21 +1,736 @@
|
|||
{
|
||||
"name": "stendhal",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "stendhal",
|
||||
"version": "1.0.0",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"devDependencies": {
|
||||
"esbuild": "0.28.1",
|
||||
"showdown": "^2.1.0",
|
||||
"typedoc": "^0.28.15",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
|
||||
"integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
|
||||
"integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
|
||||
"integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
|
||||
"integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
|
||||
"integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
|
||||
"integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
|
||||
"integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
|
||||
"integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
|
||||
"integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openharmony-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
|
||||
"integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@gerrit0/mini-shiki": {
|
||||
"version": "3.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.20.0.tgz",
|
||||
"integrity": "sha512-Wa57i+bMpK6PGJZ1f2myxo3iO+K/kZikcyvH8NIqNNZhQUbDav7V9LQmWOXhf946mz5c1NZ19WMsGYiDKTryzQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"typescript": "^5.1.0"
|
||||
"@shikijs/engine-oniguruma": "^3.20.0",
|
||||
"@shikijs/langs": "^3.20.0",
|
||||
"@shikijs/themes": "^3.20.0",
|
||||
"@shikijs/types": "^3.20.0",
|
||||
"@shikijs/vscode-textmate": "^10.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@shikijs/engine-oniguruma": {
|
||||
"version": "3.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.20.0.tgz",
|
||||
"integrity": "sha512-Yx3gy7xLzM0ZOjqoxciHjA7dAt5tyzJE3L4uQoM83agahy+PlW244XJSrmJRSBvGYELDhYXPacD4R/cauV5bzQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@shikijs/types": "3.20.0",
|
||||
"@shikijs/vscode-textmate": "^10.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@shikijs/langs": {
|
||||
"version": "3.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.20.0.tgz",
|
||||
"integrity": "sha512-le+bssCxcSHrygCWuOrYJHvjus6zhQ2K7q/0mgjiffRbkhM4o1EWu2m+29l0yEsHDbWaWPNnDUTRVVBvBBeKaA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@shikijs/types": "3.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@shikijs/themes": {
|
||||
"version": "3.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.20.0.tgz",
|
||||
"integrity": "sha512-U1NSU7Sl26Q7ErRvJUouArxfM2euWqq1xaSrbqMu2iqa+tSp0D1Yah8216sDYbdDHw4C8b75UpE65eWorm2erQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@shikijs/types": "3.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@shikijs/types": {
|
||||
"version": "3.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.20.0.tgz",
|
||||
"integrity": "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@shikijs/vscode-textmate": "^10.0.2",
|
||||
"@types/hast": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@shikijs/vscode-textmate": {
|
||||
"version": "10.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
|
||||
"integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/hast": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
|
||||
"integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/unist": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/unist": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
||||
"integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "2.0.2",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "9.5.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
|
||||
"integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.28.1",
|
||||
"@esbuild/android-arm": "0.28.1",
|
||||
"@esbuild/android-arm64": "0.28.1",
|
||||
"@esbuild/android-x64": "0.28.1",
|
||||
"@esbuild/darwin-arm64": "0.28.1",
|
||||
"@esbuild/darwin-x64": "0.28.1",
|
||||
"@esbuild/freebsd-arm64": "0.28.1",
|
||||
"@esbuild/freebsd-x64": "0.28.1",
|
||||
"@esbuild/linux-arm": "0.28.1",
|
||||
"@esbuild/linux-arm64": "0.28.1",
|
||||
"@esbuild/linux-ia32": "0.28.1",
|
||||
"@esbuild/linux-loong64": "0.28.1",
|
||||
"@esbuild/linux-mips64el": "0.28.1",
|
||||
"@esbuild/linux-ppc64": "0.28.1",
|
||||
"@esbuild/linux-riscv64": "0.28.1",
|
||||
"@esbuild/linux-s390x": "0.28.1",
|
||||
"@esbuild/linux-x64": "0.28.1",
|
||||
"@esbuild/netbsd-arm64": "0.28.1",
|
||||
"@esbuild/netbsd-x64": "0.28.1",
|
||||
"@esbuild/openbsd-arm64": "0.28.1",
|
||||
"@esbuild/openbsd-x64": "0.28.1",
|
||||
"@esbuild/openharmony-arm64": "0.28.1",
|
||||
"@esbuild/sunos-x64": "0.28.1",
|
||||
"@esbuild/win32-arm64": "0.28.1",
|
||||
"@esbuild/win32-ia32": "0.28.1",
|
||||
"@esbuild/win32-x64": "0.28.1"
|
||||
}
|
||||
},
|
||||
"node_modules/linkify-it": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
|
||||
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"uc.micro": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lunr": {
|
||||
"version": "2.3.9",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/markdown-it": {
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
|
||||
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1",
|
||||
"entities": "^4.4.0",
|
||||
"linkify-it": "^5.0.0",
|
||||
"mdurl": "^2.0.0",
|
||||
"punycode.js": "^2.3.1",
|
||||
"uc.micro": "^2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"markdown-it": "bin/markdown-it.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/mdurl": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
|
||||
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "9.0.9",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
|
||||
"integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode.js": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
|
||||
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/showdown": {
|
||||
"version": "2.1.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "^9.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"showdown": "bin/showdown.js"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://www.paypal.me/tiviesantos"
|
||||
}
|
||||
},
|
||||
"node_modules/typedoc": {
|
||||
"version": "0.28.15",
|
||||
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.15.tgz",
|
||||
"integrity": "sha512-mw2/2vTL7MlT+BVo43lOsufkkd2CJO4zeOSuWQQsiXoV2VuEn7f6IZp2jsUDPmBMABpgR0R5jlcJ2OGEFYmkyg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@gerrit0/mini-shiki": "^3.17.0",
|
||||
"lunr": "^2.3.9",
|
||||
"markdown-it": "^14.1.0",
|
||||
"minimatch": "^9.0.5",
|
||||
"yaml": "^2.8.1"
|
||||
},
|
||||
"bin": {
|
||||
"typedoc": "bin/typedoc"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18",
|
||||
"pnpm": ">= 10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
|
|
@ -23,13 +738,29 @@
|
|||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w=="
|
||||
},
|
||||
"node_modules/uc.micro": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
|
||||
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.8.2",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
|
||||
"integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/eemeli"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,11 +28,10 @@
|
|||
},
|
||||
"homepage": "https://arianne-project.org",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"typescript": "^5.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "0.28.1",
|
||||
"showdown": "^2.1.0",
|
||||
"typedoc": "^0.25.12"
|
||||
"typedoc": "^0.28.15",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -569,7 +569,7 @@ class KTextEdit extends JComponent {
|
|||
*/
|
||||
class LinkListener {
|
||||
/** Allowed patterns for links to be opened in a browser. */
|
||||
String p = "^(http|https)://(|www\\.)(faiumoni.de|stendhalgame.org|arianne.sf.net|arianne-project.org|arianne.sourceforge.net|sourceforge.net|sf.net|download.oracle.com|libregamewiki.org|freesound.org|opengameart.org|openclipart.org|github.io|github.com|arianne.github.io|postsai.github.io)(/.*)?";
|
||||
String p = "^(http|https)://(|www\\.)(faiumoni.de|stendhalgame.org|arianne.sf.net|arianne-project.org|codeberg.org|arianne.sourceforge.net|sourceforge.net|sf.net|download.oracle.com|libregamewiki.org|freesound.org|opengameart.org|openclipart.org|github.io|github.com|arianne.github.io|postsai.github.io)(/.*)?";
|
||||
|
||||
final Pattern whitelist = Pattern.compile(p);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id$ */
|
||||
/***************************************************************************
|
||||
* (C) Copyright 2003-2010 - Stendhal *
|
||||
* (C) Copyright 2003-2025 - Stendhal *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
***************************************************************************/
|
||||
package games.stendhal.client.gui.imageviewer;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
|
@ -53,7 +54,7 @@ public final class RPEventImageViewer {
|
|||
try {
|
||||
URL url = null;
|
||||
if (path.startsWith("http://") || path.startsWith("https://")) {
|
||||
url = new URL(path);
|
||||
url = new URI(path).toURL();
|
||||
} else {
|
||||
url = DataLoader.getResource(path);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2012-2022 Faiumoni e. V. *
|
||||
* (C) Copyright 2012-2025 Faiumoni e. V. *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -15,6 +15,8 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Enumeration;
|
||||
|
|
@ -60,8 +62,8 @@ public class DataLoader {
|
|||
File file = contentFilenameMapping.get(slashlessName);
|
||||
if (file != null) {
|
||||
try {
|
||||
return new URL("jar:" + file.toURI().toASCIIString() + "!/" + slashlessName);
|
||||
} catch (MalformedURLException e) {
|
||||
return new URI("jar:" + file.toURI().toASCIIString() + "!/" + slashlessName).toURL();
|
||||
} catch (MalformedURLException | URISyntaxException e) {
|
||||
logger.error(e, e);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id$ */
|
||||
/***************************************************************************
|
||||
* (C) Copyright 2003-2010 - Stendhal *
|
||||
* (C) Copyright 2003-2025 - Stendhal *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -22,6 +22,8 @@ import java.awt.HeadlessException;
|
|||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
|
@ -353,7 +355,7 @@ public class SpriteStore {
|
|||
URL url;
|
||||
if (ref.startsWith("http://") || ref.startsWith("https://")) {
|
||||
logger.info("Loading sprite from a URL...");
|
||||
url = new URL(ref);
|
||||
url = new URI(ref).toURL();
|
||||
} else {
|
||||
url = DataLoader.getResource(ref);
|
||||
}
|
||||
|
|
@ -372,7 +374,7 @@ public class SpriteStore {
|
|||
|
||||
// use ImageIO to read the image in
|
||||
sourceImage = ImageIO.read(url);
|
||||
} catch (final IOException e) {
|
||||
} catch (final IOException | URISyntaxException e) {
|
||||
logger.error("Failed to read: " + ref, e);
|
||||
|
||||
if (ref.equals(FAILSAFE_ICON_REF)) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2003-2016 - Stendhal *
|
||||
* (C) Copyright 2003-2025 - Stendhal *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -20,6 +20,7 @@ import java.io.InputStreamReader;
|
|||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
|
|
@ -109,13 +110,15 @@ public class HttpClient {
|
|||
// sometimes problems with the webservers being slow or not responding
|
||||
// at all.
|
||||
try {
|
||||
final URL url = new URL(urlString);
|
||||
final URL url = new URI(urlString).toURL();
|
||||
int retryCount = 0;
|
||||
int myTimeout = timeout;
|
||||
while (is == null) {
|
||||
retryCount++;
|
||||
try {
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
// Wikipedia API now requires User-Agent string
|
||||
connection.setRequestProperty("User-Agent", "StendhalClient/1.49.5 (https://arianne-project.org/contact.html)");
|
||||
connection.setConnectTimeout(myTimeout);
|
||||
connection.setInstanceFollowRedirects(true);
|
||||
connection.setUseCaches(false);
|
||||
|
|
@ -134,7 +137,7 @@ public class HttpClient {
|
|||
if(!passedRedirects.contains(newUrl)) {
|
||||
// open the new connnection again
|
||||
passedRedirects.add(newUrl);
|
||||
connection = (HttpURLConnection) new URL(newUrl).openConnection();
|
||||
connection = (HttpURLConnection) new URI(newUrl).toURL().openConnection();
|
||||
redirect = isRedirect(connection.getResponseCode());
|
||||
} else {
|
||||
System.err.println(String.format("The URL '%s' leads into a circular redirect.", url));
|
||||
|
|
|
|||
|
|
@ -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.48";
|
||||
public static final String VERSION = "1.49.5";
|
||||
|
||||
/** 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.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id$ */
|
||||
/***************************************************************************
|
||||
* (C) Copyright 2003-2024 - Stendhal *
|
||||
* (C) Copyright 2003-2025 - Stendhal *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -16,7 +16,7 @@ import java.io.ByteArrayInputStream;
|
|||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
|
@ -302,8 +302,8 @@ public class TMXLoader {
|
|||
final String xmlFile = makeUrl(filename);
|
||||
// xmlPath = makeUrl(xmlPath);
|
||||
|
||||
final URL url = new URL(xmlFile);
|
||||
is = url.openStream();
|
||||
final URI uri = new URI(xmlFile);
|
||||
is = uri.toURL().openStream();
|
||||
}
|
||||
|
||||
// Wrap with GZIP decoder for .tmx.gz files
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2003-2024 - Marauroa *
|
||||
* (C) Copyright 2003-2025 - Marauroa *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -16,7 +16,8 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
|
|
@ -376,8 +377,7 @@ public class StendhalRPRuleProcessor implements IRPRuleProcessor {
|
|||
|
||||
protected void executeZonePreLogic() {
|
||||
for (final IRPZone zoneI : SingletonRepository.getRPWorld()) {
|
||||
final StendhalRPZone zone = (StendhalRPZone) zoneI;
|
||||
zone.preLogic();
|
||||
((StendhalRPZone) zoneI).preLogic();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -544,9 +544,9 @@ public class StendhalRPRuleProcessor implements IRPRuleProcessor {
|
|||
if (config.has("server_welcome")) {
|
||||
msg = config.get("server_welcome");
|
||||
if (msg.startsWith("http://") || msg.startsWith("https://")) {
|
||||
final URL url = new URL(msg);
|
||||
final URI uri = new URI(msg);
|
||||
HttpURLConnection.setFollowRedirects(false);
|
||||
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
final HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();
|
||||
try {
|
||||
final BufferedReader br = new BufferedReader(
|
||||
new InputStreamReader(connection.getInputStream(), "UTF-8"));
|
||||
|
|
@ -560,7 +560,7 @@ public class StendhalRPRuleProcessor implements IRPRuleProcessor {
|
|||
}
|
||||
}
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
} catch (final IOException | URISyntaxException e) {
|
||||
if (firstWelcomeException) {
|
||||
logger.warn("Can't read server_welcome from marauroa.ini", e);
|
||||
firstWelcomeException = false;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2003-2023 - Stendhal *
|
||||
* (C) Copyright 2003-2025 - Stendhal *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -26,7 +26,6 @@ import games.stendhal.server.entity.npc.behaviour.journal.ProducerRegister;
|
|||
import games.stendhal.server.entity.npc.condition.AndCondition;
|
||||
import games.stendhal.server.entity.npc.condition.PlayerProducedNumberOfItemsCondition;
|
||||
import games.stendhal.server.entity.npc.condition.QuestCompletedCondition;
|
||||
import games.stendhal.server.entity.npc.condition.QuestStateStartsWithCondition;
|
||||
import games.stendhal.server.entity.player.Player;
|
||||
|
||||
|
||||
|
|
@ -64,7 +63,7 @@ public class ProductionAchievementFactory extends AbstractAchievementFactory {
|
|||
Achievement.MEDIUM_BASE_SCORE, true,
|
||||
new AndCondition(
|
||||
new PlayerProducedNumberOfItemsCondition(1, foods),
|
||||
new QuestStateStartsWithCondition("coal_for_haunchy","waiting;"))));
|
||||
new QuestCompletedCondition("coal_for_haunchy"))));
|
||||
|
||||
|
||||
final List<String> drinklist = producerRegister.getProducedItemNames("drink");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright © 2003-2024 - Arianne *
|
||||
* Copyright © 2003-2025 - Arianne *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -530,7 +530,7 @@ public abstract class GuidedEntity extends ActiveEntity {
|
|||
*/
|
||||
@Deprecated
|
||||
public final boolean atMovementRadius() {
|
||||
return Math.sqrt(getDistanceFromOrigin()) >= movementRadius;
|
||||
return movementRadius > 0 && Math.sqrt(getDistanceFromOrigin()) >= movementRadius;
|
||||
}
|
||||
|
||||
protected final Direction getDirectionFromOrigin() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id$ */
|
||||
/***************************************************************************
|
||||
* (C) Copyright 2003-2024 - Marauroa *
|
||||
* (C) Copyright 2003-2025 - Marauroa *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -326,10 +326,10 @@ public abstract class NPC extends DressedEntity {
|
|||
// handled in pre-logic
|
||||
return;
|
||||
} else {
|
||||
if (atMovementRadius()) {
|
||||
onOutsideMovementRadius();
|
||||
}
|
||||
if (!hasPath()) {
|
||||
if (atMovementRadius()) {
|
||||
onOutsideMovementRadius();
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
String title = getTitle();
|
||||
String zone = getZone().getName();
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
package games.stendhal.server.entity.npc.behaviour.impl.idle;
|
||||
package games.stendhal.server.entity.npc.behaviour.impl.idle;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id$ */
|
||||
/***************************************************************************
|
||||
* (C) Copyright 2003-2010 - Stendhal *
|
||||
* (C) Copyright 2003-2024 - Stendhal *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -75,7 +75,7 @@ public class FatherNPC implements ZoneConfigurator {
|
|||
|
||||
};
|
||||
|
||||
npc.setOutfit(1, 34, 7, null, 0, null, 27, null, 0);
|
||||
npc.setOutfit(1, 34, 0, null, 0, null, 27, null, 0);
|
||||
npc.setPosition(12, 7);
|
||||
npc.setDirection(Direction.DOWN);
|
||||
npc.initHP(100);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright © 2020-2024 - Faiumoni e. V. *
|
||||
* Copyright © 2020-2025 - Faiumoni e. V. *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -376,7 +376,7 @@ public class CollectEnemyData extends AbstractQuest {
|
|||
new ChatAction() {
|
||||
@Override
|
||||
public void fire(final Player player, final Sentence sentence, final EventRaiser raiser) {
|
||||
npc.say("Thanks so much for you help. Now I have all the information I need to complete my #bestiary."
|
||||
npc.say("Thanks so much for your help. Now I have all the information I need to complete my #bestiary."
|
||||
+ " If you would like one of your own, I can sell you one.");
|
||||
player.addKarma(200.0);
|
||||
}}));
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ public class AsynchronousProgramExecutor extends Thread {
|
|||
}
|
||||
|
||||
/**
|
||||
* sends the message to the twitter account
|
||||
* sends the message to the social media account
|
||||
*
|
||||
* @param cmd command
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2003-2023 - Stendhal *
|
||||
* (C) Copyright 2003-2025 - Stendhal *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -18,7 +18,8 @@ import java.io.IOException;
|
|||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.io.Reader;
|
||||
import java.net.URL;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
|
@ -135,7 +136,7 @@ public class SourceForgeContributorsGenerator {
|
|||
@SuppressWarnings("unchecked")
|
||||
private void fetchProfiles(Map<String, Map<String, Object>> contributors) throws IOException {
|
||||
for (Map.Entry<String, Map<String, Object>> entry : contributors.entrySet()) {
|
||||
try (Reader reader = new InputStreamReader(new URL("https://sourceforge.net/rest/u/" + entry.getKey() +"/profile").openStream(), "UTF-8")) {
|
||||
try (Reader reader = new InputStreamReader(new URI("https://sourceforge.net/rest/u/" + entry.getKey() +"/profile").toURL().openStream(), "UTF-8")) {
|
||||
Map<String, Object> contributor = entry.getValue();
|
||||
Map<String, Object> profile = (Map<String, Object>) JSONValue.parse(reader);
|
||||
String fullname = (String) profile.get("name");
|
||||
|
|
@ -149,7 +150,7 @@ public class SourceForgeContributorsGenerator {
|
|||
if (country != null && !country.trim().equals("")) {
|
||||
contributor.put("country", country);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
} catch (FileNotFoundException | URISyntaxException e) {
|
||||
System.err.println("Profile " + entry.getKey() + " does not exist.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* $Id$ */
|
||||
/***************************************************************************
|
||||
* (C) Copyright 2003-2011 - Stendhal *
|
||||
* (C) Copyright 2003-2025 - Stendhal *
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
* *
|
||||
|
|
@ -18,7 +18,8 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.URL;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
|
@ -80,13 +81,14 @@ public class UpdatePropUpdater {
|
|||
* loads the current version of the update.properties
|
||||
*
|
||||
* @throws IOException in case of an input/output error
|
||||
* @throws URISyntaxException
|
||||
*/
|
||||
private void loadOldUpdateProperties() throws IOException {
|
||||
private void loadOldUpdateProperties() throws IOException, URISyntaxException {
|
||||
prop = new Properties();
|
||||
InputStream is;
|
||||
if (oldFile.indexOf(":") > 2) {
|
||||
URL url = new URL(oldFile);
|
||||
is = url.openStream();
|
||||
URI uri = new URI(oldFile);
|
||||
is = uri.toURL().openStream();
|
||||
} else {
|
||||
is = new FileInputStream(oldFile);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ div.logcolR {
|
|||
background: url(/data/gui/danger.png) repeat;
|
||||
}
|
||||
|
||||
.qm-button, img#held-object {
|
||||
.qm-button, canvas#held-object {
|
||||
position: absolute;
|
||||
display: none;
|
||||
opacity: 0.5;
|
||||
|
|
@ -708,3 +708,16 @@ img#click-indicator {
|
|||
.pad-contents {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
table.shoptable {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table.shoptable th, table.shoptable td {
|
||||
border: 1px solid var(--text-color);
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
td.number {
|
||||
text-align: right;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -486,14 +486,11 @@
|
|||
<div class="shortcuts-dialog"></div>
|
||||
</template>
|
||||
|
||||
<img id="held-object" class="hidden unselectable notarget" draggable="false">
|
||||
<canvas id="held-object" class="unselectable notarget" draggable="false"></canvas>
|
||||
|
||||
<!-- place at end of document so drawn above all other elements -->
|
||||
<img id="click-indicator" class="unclickable notarget">
|
||||
|
||||
<!-- hidden canvas for manipulating images before being displayed -->
|
||||
<canvas id="drawing-stage" class="hidden"></canvas>
|
||||
|
||||
<script type="text/javascript" src="stendhal-compiled.js"></script>
|
||||
</body>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright © 2023-2024 - Faiumoni e. V. *
|
||||
* Copyright © 2023-2026 - Faiumoni e. V. *
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
|
@ -9,25 +9,21 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var marauroa: any;
|
||||
declare var stendhal: any;
|
||||
import { marauroa, Deserializer, RPObject } from "marauroa"
|
||||
import { stendhal } from "./stendhal";
|
||||
|
||||
import { PerceptionListener } from "./PerceptionListener";
|
||||
import { StendhalPerceptionListener } from "./PerceptionListener";
|
||||
import { singletons } from "./SingletonRepo";
|
||||
|
||||
import { Paths } from "./data/Paths";
|
||||
|
||||
import { Color } from "./data/color/Color";
|
||||
|
||||
import { Ground } from "./entity/Ground";
|
||||
import { RPObject } from "./entity/RPObject";
|
||||
import { EntityRegistry } from "./entity/EntityRegistry";
|
||||
|
||||
import { ui } from "./ui/UI";
|
||||
import { UIComponentEnum } from "./ui/UIComponentEnum";
|
||||
|
||||
import { BuddyListComponent } from "./ui/component/BuddyListComponent";
|
||||
import { MiniMapComponent } from "./ui/component/MiniMapComponent";
|
||||
import { PlayerEquipmentComponent } from "./ui/component/PlayerEquipmentComponent";
|
||||
import { ZoneInfoComponent } from "./ui/component/ZoneInfoComponent";
|
||||
|
||||
import { ChooseCharacterDialog } from "./ui/dialog/ChooseCharacterDialog";
|
||||
|
|
@ -40,6 +36,12 @@ import { SingletonFloatingWindow } from "./ui/toolkit/SingletonFloatingWindow";
|
|||
import { Chat } from "./util/Chat";
|
||||
import { DialogHandler } from "./util/DialogHandler";
|
||||
import { Globals } from "./util/Globals";
|
||||
import { TileMap } from "data/TileMap";
|
||||
import { OutfitStore } from "data/OutfitStore";
|
||||
import { TileStore } from "data/TileStore";
|
||||
import { WeatherRenderer } from "util/WeatherRenderer";
|
||||
import { ViewPort } from "ui/ViewPort";
|
||||
import { htmlImageStore } from "data/HTMLImageStore";
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -62,6 +64,7 @@ export class Client {
|
|||
|
||||
/** Singleton instance. */
|
||||
private static instance: Client;
|
||||
public loaded = false;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -78,7 +81,7 @@ export class Client {
|
|||
* Hidden singleton constructor.
|
||||
*/
|
||||
private constructor() {
|
||||
// do nothing
|
||||
// empty
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -91,19 +94,18 @@ export class Client {
|
|||
}
|
||||
this.initialized = true;
|
||||
|
||||
// add version & build info to DOM for retrieval by browser
|
||||
document.documentElement.setAttribute("data-build-version", stendhal.data.build.version);
|
||||
document.documentElement.setAttribute("data-build-build", stendhal.data.build.build);
|
||||
|
||||
stendhal.paths = singletons.getPaths();
|
||||
stendhal.config = singletons.getConfigManager();
|
||||
stendhal.session = singletons.getSessionManager();
|
||||
stendhal.actions = singletons.getSlashActionRepo();
|
||||
new EntityRegistry().init();
|
||||
|
||||
this.initData();
|
||||
this.initSound();
|
||||
this.initUI();
|
||||
this.initZone();
|
||||
|
||||
// add version & build info to DOM for retrieval by browser
|
||||
document.documentElement.setAttribute("data-build-version", stendhal.data.build?.version);
|
||||
document.documentElement.setAttribute("data-build-build", stendhal.data.build?.build);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -117,9 +119,6 @@ export class Client {
|
|||
stendhal.data.cstatus = singletons.getCStatus();
|
||||
stendhal.data.cstatus.init();
|
||||
stendhal.data.group = singletons.getGroupManager();
|
||||
stendhal.data.outfit = singletons.getOutfitStore();
|
||||
stendhal.data.sprites = singletons.getSpriteStore();
|
||||
stendhal.data.map = singletons.getMap();
|
||||
// online players
|
||||
stendhal.players = [];
|
||||
}
|
||||
|
|
@ -141,22 +140,9 @@ export class Client {
|
|||
private initUI() {
|
||||
stendhal.ui = stendhal.ui || {};
|
||||
stendhal.ui.equip = singletons.getInventory();
|
||||
stendhal.ui.html = singletons.getHTMLManager();
|
||||
stendhal.ui.touch = singletons.getTouchHandler();
|
||||
stendhal.ui.viewport = singletons.getViewPort();
|
||||
// alias for backward-compat until changed in all source
|
||||
stendhal.ui.gamewindow = stendhal.ui.viewport;
|
||||
|
||||
stendhal.ui.getMenuStyle = Globals.getMenuStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds initial zone for user to enter world.
|
||||
*/
|
||||
private initZone() {
|
||||
stendhal.zone = singletons.getZone();
|
||||
stendhal.zone.ground = new Ground();
|
||||
}
|
||||
|
||||
/**
|
||||
* Main startup routines.
|
||||
|
|
@ -177,11 +163,11 @@ export class Client {
|
|||
singletons.getEventRegistry().init();
|
||||
|
||||
// initialize tileset animation data
|
||||
singletons.getTileStore().init();
|
||||
TileStore.get().init();
|
||||
// initialize emoji data
|
||||
singletons.getEmojiStore().init();
|
||||
// initialize outfit data
|
||||
stendhal.data.outfit.init();
|
||||
OutfitStore.get().init();
|
||||
|
||||
new DesktopUserInterfaceFactory().create();
|
||||
|
||||
|
|
@ -204,11 +190,11 @@ export class Client {
|
|||
stendhal.ui.globalInternalWindow = new DialogHandler();
|
||||
|
||||
// pre-cache images & sounds
|
||||
stendhal.data.sprites.startupCache();
|
||||
htmlImageStore.startupCache();
|
||||
stendhal.sound.startupCache();
|
||||
|
||||
if (document.getElementById("viewport")) {
|
||||
stendhal.ui.gamewindow.draw.apply(stendhal.ui.gamewindow, arguments);
|
||||
ViewPort.get().draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -259,11 +245,14 @@ export class Client {
|
|||
* Registers Marauroa event handlers.
|
||||
*/
|
||||
registerMarauroaEventHandlers() {
|
||||
marauroa.clientFramework.onDisconnect = function(_reason: string, _error: string) {
|
||||
marauroa.clientFramework.onDisconnect = function(_reason: string, _code: number, _wasClean: boolean) {
|
||||
if (!Client.instance.unloading) {
|
||||
Chat.logH("error", "Disconnected from server.");
|
||||
if (window.location.hostname !== "localhost" && window.location.hostname !== "127.0.0.1" && window.location.hostname !== "::1") {
|
||||
window.location.href = "/account/mycharacters.html";
|
||||
}
|
||||
}
|
||||
};
|
||||
}.bind(this);
|
||||
|
||||
marauroa.clientFramework.onLoginRequired = function(config: Record<string, string>) {
|
||||
if (config["client_login_url"]) {
|
||||
|
|
@ -281,25 +270,25 @@ export class Client {
|
|||
"Login",
|
||||
new LoginDialog(),
|
||||
100, 50).enableCloseButton(false);
|
||||
};
|
||||
}.bind(this);
|
||||
|
||||
marauroa.clientFramework.onCreateAccountAck = function(username: string) {
|
||||
// TODO: We should login automatically
|
||||
alert("Account succesfully created, please login.");
|
||||
window.location.reload();
|
||||
};
|
||||
}.bind(this);
|
||||
|
||||
marauroa.clientFramework.onCreateCharacterAck = function(charname: string, _template: any) {
|
||||
// Client.get().chooseCharacter(charname);
|
||||
};
|
||||
}.bind(this);
|
||||
|
||||
marauroa.clientFramework.onLoginFailed = function(_reason: string, _text: string) {
|
||||
alert("Login failed. " + _text);
|
||||
// TODO: Server closes the connection, so we need to open a new one
|
||||
window.location.reload();
|
||||
};
|
||||
}.bind(this);
|
||||
|
||||
marauroa.clientFramework.onAvailableCharacterDetails = function(characters: {[key: string]: RPObject}) {
|
||||
marauroa.clientFramework.onAvailableCharacterDetails = (characters: {[key: string]: RPObject}) => {
|
||||
SingletonFloatingWindow.closeAll();
|
||||
if (!Object.keys(characters).length && this.username) {
|
||||
marauroa.clientFramework.createCharacter(this.username, {});
|
||||
|
|
@ -331,9 +320,9 @@ export class Client {
|
|||
}
|
||||
items[i]["ack"] = true;
|
||||
}
|
||||
};
|
||||
}.bind(this);
|
||||
|
||||
marauroa.clientFramework.onTransfer = function(items: any) {
|
||||
marauroa.clientFramework.onTransfer = (items: any) => {
|
||||
var data = {} as any;
|
||||
var zoneName = ""
|
||||
for (var i in items) {
|
||||
|
|
@ -345,34 +334,13 @@ export class Client {
|
|||
this.onDataMap(items[i]["data"]);
|
||||
}
|
||||
}
|
||||
stendhal.data.map.onTransfer(zoneName, data);
|
||||
TileMap.get().onTransfer(zoneName, data);
|
||||
};
|
||||
|
||||
// update user interface on perceptions
|
||||
if (document.getElementById("viewport")) {
|
||||
// override perception listener
|
||||
marauroa.perceptionListener = new PerceptionListener(marauroa.perceptionListener);
|
||||
marauroa.perceptionListener.onPerceptionEnd = function(_type: Int8Array, _timestamp: number) {
|
||||
stendhal.zone.sortEntities();
|
||||
(ui.get(UIComponentEnum.MiniMap) as MiniMapComponent).draw();
|
||||
(ui.get(UIComponentEnum.BuddyList) as BuddyListComponent).update();
|
||||
stendhal.ui.equip.update();
|
||||
(ui.get(UIComponentEnum.PlayerEquipment) as PlayerEquipmentComponent).update();
|
||||
if (!this.loaded) {
|
||||
this.loaded = true;
|
||||
// delay visibile change of client a little to allow for initialisation in the background for a smoother experience
|
||||
window.setTimeout(function() {
|
||||
let body = document.getElementById("body")!;
|
||||
body.style.cursor = "auto";
|
||||
document.getElementById("client")!.style.display = "block";
|
||||
document.getElementById("loginpopup")!.style.display = "none";
|
||||
|
||||
// initialize observer after UI is ready
|
||||
singletons.getUIUpdateObserver().init();
|
||||
ui.onDisplayReady();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
marauroa.perceptionListener = new StendhalPerceptionListener();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -420,18 +388,19 @@ export class Client {
|
|||
|
||||
document.getElementById("body")!.addEventListener("mouseenter", stendhal.main.onMouseEnter);
|
||||
|
||||
var gamewindow = document.getElementById("viewport")!;
|
||||
let gamewindow = document.getElementById("viewport")!;
|
||||
let viewPort = ViewPort.get();
|
||||
gamewindow.setAttribute("draggable", "true");
|
||||
gamewindow.addEventListener("mousedown", stendhal.ui.gamewindow.onMouseDown);
|
||||
gamewindow.addEventListener("dblclick", stendhal.ui.gamewindow.onMouseDown);
|
||||
gamewindow.addEventListener("dragstart", stendhal.ui.gamewindow.onDragStart);
|
||||
gamewindow.addEventListener("mousemove", stendhal.ui.gamewindow.onMouseMove);
|
||||
gamewindow.addEventListener("touchstart", stendhal.ui.gamewindow.onMouseDown);
|
||||
gamewindow.addEventListener("touchend", stendhal.ui.gamewindow.onTouchEnd);
|
||||
gamewindow.addEventListener("dragover", stendhal.ui.gamewindow.onDragOver);
|
||||
gamewindow.addEventListener("drop", stendhal.ui.gamewindow.onDrop);
|
||||
gamewindow.addEventListener("contextmenu", stendhal.ui.gamewindow.onContentMenu);
|
||||
gamewindow.addEventListener("wheel", stendhal.ui.gamewindow.onMouseWheel);
|
||||
gamewindow.addEventListener("mousedown", viewPort.onMouseDown);
|
||||
gamewindow.addEventListener("dblclick", viewPort.onMouseDown);
|
||||
gamewindow.addEventListener("dragstart", viewPort.onDragStart);
|
||||
gamewindow.addEventListener("mousemove", viewPort.onMouseMove);
|
||||
gamewindow.addEventListener("touchstart", viewPort.onMouseDown, {passive: true});
|
||||
gamewindow.addEventListener("touchend", viewPort.onTouchEnd);
|
||||
gamewindow.addEventListener("dragover", viewPort.onDragOver);
|
||||
gamewindow.addEventListener("drop", viewPort.onDrop);
|
||||
gamewindow.addEventListener("contextmenu", viewPort.onContentMenu);
|
||||
gamewindow.addEventListener("wheel", viewPort.onMouseWheel, {passive: true});
|
||||
|
||||
singletons.getJoystickController().registerGlobalEventHandlers();
|
||||
|
||||
|
|
@ -459,7 +428,7 @@ export class Client {
|
|||
document.addEventListener("click", Client.handleClickIndicator);
|
||||
document.addEventListener("touchend", Client.handleClickIndicator);
|
||||
};
|
||||
click_indicator.src = stendhal.paths.gui + "/click_indicator.png";
|
||||
click_indicator.src = Paths.gui + "/click_indicator.png";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -469,8 +438,10 @@ export class Client {
|
|||
* Information about map.
|
||||
*/
|
||||
onDataMap(data: any) {
|
||||
let map = TileMap.get();
|
||||
let viewPort = ViewPort.get();
|
||||
var zoneinfo = {} as {[key: string]: string};
|
||||
var deserializer = marauroa.Deserializer.fromBase64(data);
|
||||
var deserializer = Deserializer.fromBase64(data);
|
||||
deserializer.readAttributes(zoneinfo);
|
||||
(ui.get(UIComponentEnum.ZoneInfo) as ZoneInfoComponent).zoneChange(zoneinfo);
|
||||
|
||||
|
|
@ -481,29 +452,29 @@ export class Client {
|
|||
|
||||
// parallax background
|
||||
if (stendhal.config.getBoolean("effect.parallax")) {
|
||||
stendhal.data.map.setParallax(zoneinfo["parallax"]);
|
||||
stendhal.data.map.setIgnoredTiles(zoneinfo["parallax_ignore_tiles"]);
|
||||
map.setParallax(zoneinfo["parallax"]);
|
||||
map.setIgnoredTiles(zoneinfo["parallax_ignore_tiles"]);
|
||||
}
|
||||
|
||||
// coloring information
|
||||
if (zoneinfo["color"] && stendhal.config.getBoolean("effect.lighting")) {
|
||||
if (zoneinfo["color_method"]) {
|
||||
stendhal.ui.gamewindow.setColorMethod(zoneinfo["color_method"]);
|
||||
viewPort.setColorMethod(zoneinfo["color_method"]);
|
||||
}
|
||||
if (zoneinfo["blend_method"]) {
|
||||
stendhal.ui.gamewindow.setBlendMethod(zoneinfo["blend_method"]);
|
||||
viewPort.setBlendMethod(zoneinfo["blend_method"]);
|
||||
}
|
||||
const hsl = Color.numToHSL(Number(zoneinfo["color"]));
|
||||
stendhal.ui.gamewindow.HSLFilter = hsl.toString();
|
||||
viewPort.HSLFilter = hsl.toString();
|
||||
// deprecated
|
||||
stendhal.ui.gamewindow.filter = "hue-rotate(" + hsl.H + "deg) saturate(" + hsl.S
|
||||
viewPort.filter = "hue-rotate(" + hsl.H + "deg) saturate(" + hsl.S
|
||||
+ ") brightness(" + hsl.L + ")";
|
||||
} else {
|
||||
stendhal.ui.gamewindow.HSLFilter = undefined;
|
||||
stendhal.ui.gamewindow.filter = undefined;
|
||||
viewPort.HSLFilter = undefined;
|
||||
viewPort.filter = undefined;
|
||||
}
|
||||
|
||||
singletons.getWeatherRenderer().update(zoneinfo["weather"]);
|
||||
WeatherRenderer.get().update(zoneinfo["weather"]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -518,7 +489,7 @@ export class Client {
|
|||
*/
|
||||
onMouseEnter(e: MouseEvent) {
|
||||
// use Stendhal's built-in cursor for entire page
|
||||
(e.target as HTMLElement).style.cursor = "url(" + stendhal.paths.sprites + "/cursor/normal.png) 1 3, auto";
|
||||
(e.target as HTMLElement).style.cursor = "url(" + Paths.sprites + "/cursor/normal.png) 1 3, auto";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,310 +0,0 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2003-2024 - Stendhal *
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Affero General Public License as *
|
||||
* published by the Free Software Foundation; either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var marauroa: any;
|
||||
declare var stendhal: any;
|
||||
|
||||
import { RPEntity } from "./entity/RPEntity";
|
||||
import { RPObject } from "./entity/RPObject";
|
||||
|
||||
import { BestiaryEvent } from "./event/BestiaryEvent";
|
||||
import { ChatOptionsEvent } from "./event/ChatOptionsEvent";
|
||||
import { ExamineEvent } from "./event/ExamineEvent";
|
||||
import { GroupChangeEvent } from "./event/GroupChangeEvent";
|
||||
import { GroupInviteEvent } from "./event/GroupInviteEvent";
|
||||
import { PlayerLoggedOnEvent } from "./event/PlayerLoggedOnEvent";
|
||||
import { PlayerLoggedOutEvent } from "./event/PlayerLoggedOutEvent";
|
||||
import { ProgressStatusEvent } from "./event/ProgressStatusEvent";
|
||||
import { RPEvent } from "./event/RPEvent";
|
||||
import { SoundEvent } from "./event/SoundEvent";
|
||||
import { TradeEvent } from "./event/TradeEvent";
|
||||
import { ViewChangeEvent } from "./event/ViewChangeEvent";
|
||||
|
||||
import { ui } from "./ui/UI";
|
||||
|
||||
import { DialogContentComponent } from "./ui/toolkit/DialogContentComponent";
|
||||
|
||||
import { Chat } from "./util/Chat";
|
||||
|
||||
|
||||
export class EventRegistry {
|
||||
|
||||
private initialized = false;
|
||||
|
||||
/** Singleton instance. */
|
||||
private static instance: EventRegistry;
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves singleton instance.
|
||||
*/
|
||||
static get(): EventRegistry {
|
||||
if (!EventRegistry.instance) {
|
||||
EventRegistry.instance = new EventRegistry();
|
||||
}
|
||||
return EventRegistry.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hidden singleton constructor.
|
||||
*/
|
||||
private constructor() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers standard events.
|
||||
*/
|
||||
init() {
|
||||
if (this.initialized) {
|
||||
console.warn("tried to re-initialize EventRegistry");
|
||||
return;
|
||||
}
|
||||
this.initialized = true;
|
||||
|
||||
this.register("chat_options", new ChatOptionsEvent());
|
||||
this.register("examine", new ExamineEvent());
|
||||
this.register("group_change_event", new GroupChangeEvent());
|
||||
this.register("group_invite_event", new GroupInviteEvent());
|
||||
this.register("progress_status_event", new ProgressStatusEvent());
|
||||
this.register("trade_state_change_event", new TradeEvent());
|
||||
|
||||
this.register("attack", {
|
||||
execute: function(entity: RPEntity) {
|
||||
var target = entity.getAttackTarget();
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
if (this.hasOwnProperty("hit")) {
|
||||
var damage = parseInt(this["damage"], 10);
|
||||
if (damage !== 0) {
|
||||
target.onDamaged(entity, damage);
|
||||
} else {
|
||||
target.onBlocked(entity);
|
||||
}
|
||||
} else {
|
||||
target.onMissed(entity);
|
||||
}
|
||||
entity.onAttackPerformed(parseInt(this["type"], 10), this.hasOwnProperty("ranged"), this["weapon"]);
|
||||
}
|
||||
}); // attack
|
||||
|
||||
this.register("bestiary", new BestiaryEvent());
|
||||
|
||||
this.register("global_visual_effect", {
|
||||
execute: function(rpobject: RPObject) {
|
||||
// TODO: new GlobalVisualEffectEvent();
|
||||
}
|
||||
}); // global_visual_effect
|
||||
|
||||
this.register("image_event", {
|
||||
execute: function(rpobject: RPObject) {
|
||||
// TODO: new ImageEffectEvent();
|
||||
console.log("image_event", this, rpobject);
|
||||
}
|
||||
}); // image_event
|
||||
|
||||
this.register("player_logged_on", new PlayerLoggedOnEvent());
|
||||
this.register("player_logged_out", new PlayerLoggedOutEvent());
|
||||
|
||||
this.register("private_text", {
|
||||
soundTextEvents: {
|
||||
"privmsg": true,
|
||||
"support": true,
|
||||
"tutorial": true
|
||||
},
|
||||
|
||||
execute: function(rpobject: RPObject) {
|
||||
const ttype = this["texttype"].toLowerCase();
|
||||
const msg = this["text"].replace(/\\r\\n/g, "\n").replace(/\\r/g, "\n");
|
||||
|
||||
let profile;
|
||||
if (this.hasOwnProperty("profile")) {
|
||||
profile = this["profile"];
|
||||
} else if (ttype === "tutorial") {
|
||||
profile = "floattingladynpc";
|
||||
}
|
||||
|
||||
if (ttype === "server" && msg.includes("\n")) {
|
||||
Chat.log(ttype, msg.split("\n"), undefined, profile);
|
||||
} else {
|
||||
// scene settings messages should not disturb playing, just create some atmosphere
|
||||
const headed = ttype !== "scene_setting";
|
||||
Chat.log(ttype, msg, undefined, profile, headed);
|
||||
}
|
||||
|
||||
// play notification sound
|
||||
const notif = stendhal.config.get("chat.private.sound");
|
||||
if (notif && this.soundTextEvents[ttype]) {
|
||||
stendhal.sound.playGlobalizedEffect(notif);
|
||||
}
|
||||
}
|
||||
}); // private_text
|
||||
|
||||
this.register("reached_achievement", {
|
||||
execute: function(rpobject: RPObject) {
|
||||
stendhal.ui.gamewindow.addAchievementNotif(this["category"], this["title"], this["description"]);
|
||||
}
|
||||
}); // reached_achievement
|
||||
|
||||
this.register("show_item_list", {
|
||||
execute: function(rpobject: RPObject) {
|
||||
let title = "Items";
|
||||
let caption = "";
|
||||
let items = [];
|
||||
|
||||
if (this.hasOwnProperty("title")) {
|
||||
title = this["title"];
|
||||
}
|
||||
if (this.hasOwnProperty("caption")) {
|
||||
caption = this["caption"];
|
||||
}
|
||||
if (this.hasOwnProperty("content")) {
|
||||
for (var obj in this["content"]) {
|
||||
if (this["content"].hasOwnProperty(obj)) {
|
||||
var slotObj = this["content"][obj];
|
||||
var data = this["content"][obj]["a"];
|
||||
const i = {
|
||||
clazz: data["class"],
|
||||
subclass: data["subclass"],
|
||||
img: data["class"] + "/" + data["subclass"] + ".png",
|
||||
price: data["price"],
|
||||
desc: data["description_info"]
|
||||
}
|
||||
|
||||
// seller shops prefix prices with "-"
|
||||
if (i.price.startsWith("-")) {
|
||||
i.price = i.price.substr(1);
|
||||
}
|
||||
items.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const content = new class extends DialogContentComponent {} ("empty-div-template");
|
||||
content.componentElement.classList.add("shopsign");
|
||||
const captionElement = document.createElement("div");
|
||||
captionElement.className = "horizontalgroup shopcaption";
|
||||
captionElement.textContent = caption + "\nItem\t-\tPrice\t-\tDescription";
|
||||
content.componentElement.appendChild(captionElement);
|
||||
const itemList = document.createElement("div");
|
||||
itemList.className = "shoplist";
|
||||
content.componentElement.appendChild(itemList);
|
||||
|
||||
// TODO: organize in columns & show item sprites
|
||||
for (const i of items) {
|
||||
const row = document.createElement("div");
|
||||
row.className = "horizontalgroup shoprow";
|
||||
const img = document.createElement("div");
|
||||
img.className = "shopcol";
|
||||
img.appendChild(stendhal.data.sprites.get(stendhal.paths.sprites + "/items/" + i.img));
|
||||
row.appendChild(img);
|
||||
const price = document.createElement("div");
|
||||
price.className = "shopcol";
|
||||
price.textContent = i.price;
|
||||
row.appendChild(price);
|
||||
const desc = document.createElement("div");
|
||||
desc.className = "shopcol shopcolr";
|
||||
desc.textContent = i.desc;
|
||||
row.appendChild(desc);
|
||||
itemList.appendChild(row);
|
||||
}
|
||||
|
||||
stendhal.ui.globalInternalWindow.set(
|
||||
ui.createSingletonFloatingWindow(title, content, 20, 20));
|
||||
}
|
||||
}); // show_item_list
|
||||
|
||||
this.register("show_outfit_list", {
|
||||
execute: function(rpobject: RPObject) {
|
||||
let title = "Outfits";
|
||||
let caption = "";
|
||||
let outfits = [];
|
||||
|
||||
if (this.hasOwnProperty("title")) {
|
||||
title = this["title"];
|
||||
}
|
||||
if (this.hasOwnProperty("caption")) {
|
||||
caption = this["caption"];
|
||||
}
|
||||
if (this.hasOwnProperty("outfits")) {
|
||||
for (let o of this["outfits"].split(":")) {
|
||||
o = o.split(";");
|
||||
if (o.length > 2) {
|
||||
outfits.push([o[0], o[1], o[2]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.hasOwnProperty("show_base")) {
|
||||
//Chat.log("normal", this["show_base"]);
|
||||
}
|
||||
|
||||
const content = new class extends DialogContentComponent {} ("empty-div-template");
|
||||
content.componentElement.classList.add("shopsign");
|
||||
const captionElement = document.createElement("div");
|
||||
captionElement.className = "horizontalgroup shopcaption";
|
||||
captionElement.textContent = caption;
|
||||
content.componentElement.appendChild(captionElement);
|
||||
const itemList = document.createElement("div");
|
||||
itemList.className = "shoplist";
|
||||
content.componentElement.appendChild(itemList);
|
||||
|
||||
// TODO: organize in columns & show outfit sprites
|
||||
for (const o of outfits) {
|
||||
const row = document.createElement("div");
|
||||
row.className = "horizontalgroup shoprow";
|
||||
row.textContent = o[0] + ": " + o[2];
|
||||
itemList.appendChild(row);
|
||||
}
|
||||
|
||||
stendhal.ui.globalInternalWindow.set(
|
||||
ui.createSingletonFloatingWindow(title, content, 20, 20));
|
||||
}
|
||||
}); // show_outfit_list
|
||||
|
||||
this.register("sound_event", new SoundEvent());
|
||||
|
||||
this.register("text", {
|
||||
execute: function(entity: RPEntity) {
|
||||
if (this.hasOwnProperty("range")) {
|
||||
entity.say(this["text"], this["range"]);
|
||||
} else {
|
||||
entity.say(this["text"]);
|
||||
}
|
||||
}
|
||||
}); // text
|
||||
|
||||
this.register("transition_graph", {
|
||||
execute: function(rpobject: RPObject) {
|
||||
// TODO: new TransitionGraphEvent();
|
||||
}
|
||||
}); // transition_graph
|
||||
|
||||
this.register("view_change", new ViewChangeEvent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new event.
|
||||
*
|
||||
* @param _type
|
||||
* String identifier.
|
||||
* @param _event
|
||||
* Event to be registered.
|
||||
*/
|
||||
register(_type: string, _event: any) {
|
||||
if (_event instanceof RPEvent) {
|
||||
marauroa.rpeventFactory[_type] = _event;
|
||||
} else {
|
||||
marauroa.rpeventFactory[_type] =
|
||||
marauroa.util.fromProto(marauroa.rpeventFactory["_default"], _event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,29 +9,24 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var stendhal: any;
|
||||
import { ui } from "ui/UI";
|
||||
import { stendhal } from "./stendhal";
|
||||
|
||||
import { RPObject } from "./entity/RPObject";
|
||||
import { RPObject, PerceptionListener } from "marauroa";
|
||||
import { UIComponentEnum } from "ui/UIComponentEnum";
|
||||
import { MiniMapComponent } from "ui/component/MiniMapComponent";
|
||||
import { BuddyListComponent } from "ui/component/BuddyListComponent";
|
||||
import { PlayerEquipmentComponent } from "ui/component/PlayerEquipmentComponent";
|
||||
import { singletons } from "SingletonRepo";
|
||||
import { Client } from "Client";
|
||||
import { Zone } from "entity/Zone";
|
||||
|
||||
|
||||
/**
|
||||
* Class to override `marauroa.perceptionListener` & handle creating
|
||||
* User object.
|
||||
*/
|
||||
export class PerceptionListener {
|
||||
[key: string]: any;
|
||||
private readonly _super: any;
|
||||
|
||||
|
||||
constructor(perceptionListener: any) {
|
||||
this._super = perceptionListener;
|
||||
for (const prop of Object.getOwnPropertyNames(perceptionListener)) {
|
||||
if (typeof(this[prop]) === "undefined") {
|
||||
// members & methods that are not overridden by this class
|
||||
this[prop] = perceptionListener[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
export class StendhalPerceptionListener extends PerceptionListener {
|
||||
|
||||
/**
|
||||
* Action when an object is added to the world.
|
||||
|
|
@ -42,7 +37,7 @@ export class PerceptionListener {
|
|||
* `true` if object was added.
|
||||
* @see marauroa.perceptionListener.onAdded
|
||||
*/
|
||||
onAdded(obj: RPObject): boolean {
|
||||
override onAdded(obj: RPObject): boolean {
|
||||
if (obj["c"] === "player") {
|
||||
if (obj.hasOwnProperty("a")) {
|
||||
if (obj["a"]["name"] === stendhal.session.getCharName()) {
|
||||
|
|
@ -51,6 +46,28 @@ export class PerceptionListener {
|
|||
}
|
||||
}
|
||||
}
|
||||
return this._super.onAdded(obj);
|
||||
return super.onAdded(obj);
|
||||
}
|
||||
|
||||
override onPerceptionEnd(_type: Int8Array, _timestamp: number) {
|
||||
Zone.get().sortEntities();
|
||||
(ui.get(UIComponentEnum.MiniMap) as MiniMapComponent).draw();
|
||||
(ui.get(UIComponentEnum.BuddyList) as BuddyListComponent).update();
|
||||
stendhal.ui.equip.update();
|
||||
(ui.get(UIComponentEnum.PlayerEquipment) as PlayerEquipmentComponent).update();
|
||||
if (!Client.get().loaded) {
|
||||
Client.get().loaded = true;
|
||||
// delay visibile change of client a little to allow for initialisation in the background for a smoother experience
|
||||
window.setTimeout(function() {
|
||||
let body = document.getElementById("body")!;
|
||||
body.style.cursor = "auto";
|
||||
document.getElementById("client")!.style.display = "block";
|
||||
document.getElementById("loginpopup")!.style.display = "none";
|
||||
|
||||
// initialize observer after UI is ready
|
||||
singletons.getUIUpdateObserver().init();
|
||||
ui.onDisplayReady();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright © 2003-2024 - Faiumoni e. V. *
|
||||
* Copyright © 2003-2026 - Faiumoni e. V. *
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
|
@ -10,45 +10,35 @@
|
|||
***************************************************************************/
|
||||
|
||||
import { Client } from "./Client";
|
||||
import { EventRegistry } from "./EventRegistry";
|
||||
import { EventRegistry } from "./event/EventRegistry";
|
||||
import { SlashActionRepo } from "./SlashActionRepo";
|
||||
|
||||
import { Zone } from "./entity/Zone";
|
||||
|
||||
import { ConfigManager } from "./util/ConfigManager";
|
||||
import { DownloadUtil } from "./util/DownloadUtil";
|
||||
import { DrawingStage } from "./util/DrawingStage";
|
||||
import { FacingHandler } from "./util/FacingHandler";
|
||||
import { KeyHandler } from "./util/KeyHandler";
|
||||
import { SessionManager } from "./util/SessionManager";
|
||||
import { WeatherRenderer } from "./util/WeatherRenderer";
|
||||
|
||||
import { CStatus } from "./data/CStatus";
|
||||
import { CacheManager } from "./data/CacheManager";
|
||||
import { CStatus } from "./data/CStatus";
|
||||
import { EmojiStore } from "./data/EmojiStore";
|
||||
import { GroupManager } from "./data/GroupManager";
|
||||
import { Map } from "./data/Map";
|
||||
import { OutfitStore } from "./data/OutfitStore";
|
||||
import { Paths } from "./data/Paths";
|
||||
import { SpriteStore, store } from "./data/SpriteStore";
|
||||
import { TileStore } from "./data/TileStore";
|
||||
|
||||
import { LoopedSoundSourceManager } from "./data/sound/LoopedSoundSourceManager";
|
||||
import { SoundManager } from "./data/sound/SoundManager";
|
||||
|
||||
import { ui } from "./ui/UI";
|
||||
import { UIComponentEnum } from "./ui/UIComponentEnum";
|
||||
import { HeldObjectManager } from "./ui/HeldObject";
|
||||
import { HTMLManager } from "./ui/HTMLManager";
|
||||
import { Inventory } from "./ui/Inventory";
|
||||
import { SoftwareJoystickController } from "./ui/SoftwareJoystickController";
|
||||
import { TouchHandler } from "./ui/TouchHandler";
|
||||
import { ui } from "./ui/UI";
|
||||
import { UIComponentEnum } from "./ui/UIComponentEnum";
|
||||
import { UIUpdateObserver } from "./ui/UIUpdateObserver";
|
||||
import { ViewPort } from "./ui/ViewPort";
|
||||
|
||||
import { ChatInputComponent } from "./ui/component/ChatInputComponent";
|
||||
|
||||
|
||||
/**
|
||||
* @Deprecated use Class.get() directly to prevent dependency chain
|
||||
*/
|
||||
export class SingletonRepo {
|
||||
|
||||
static getCStatus(): CStatus {
|
||||
|
|
@ -75,10 +65,6 @@ export class SingletonRepo {
|
|||
return DownloadUtil;
|
||||
}
|
||||
|
||||
static getDrawingStage(): DrawingStage {
|
||||
return DrawingStage.get();
|
||||
}
|
||||
|
||||
static getEmojiStore(): EmojiStore {
|
||||
return EmojiStore.get();
|
||||
}
|
||||
|
|
@ -95,14 +81,6 @@ export class SingletonRepo {
|
|||
return GroupManager.get();
|
||||
}
|
||||
|
||||
static getHeldObjectManager(): HeldObjectManager {
|
||||
return HeldObjectManager.get();
|
||||
}
|
||||
|
||||
static getHTMLManager(): HTMLManager {
|
||||
return HTMLManager.get();
|
||||
}
|
||||
|
||||
static getInventory(): Inventory {
|
||||
return Inventory.get();
|
||||
}
|
||||
|
|
@ -119,14 +97,6 @@ export class SingletonRepo {
|
|||
return LoopedSoundSourceManager.get();
|
||||
}
|
||||
|
||||
static getMap(): Map {
|
||||
return Map.get();
|
||||
}
|
||||
|
||||
static getOutfitStore(): OutfitStore {
|
||||
return OutfitStore.get();
|
||||
}
|
||||
|
||||
static getPaths(): typeof Paths {
|
||||
return Paths;
|
||||
}
|
||||
|
|
@ -143,33 +113,10 @@ export class SingletonRepo {
|
|||
return SoundManager.get();
|
||||
}
|
||||
|
||||
static getSpriteStore(): SpriteStore {
|
||||
return store;
|
||||
}
|
||||
|
||||
static getTileStore(): TileStore {
|
||||
return TileStore.get();
|
||||
}
|
||||
|
||||
static getTouchHandler(): TouchHandler {
|
||||
return TouchHandler.get();
|
||||
}
|
||||
|
||||
static getUIUpdateObserver(): UIUpdateObserver {
|
||||
return UIUpdateObserver.get();
|
||||
}
|
||||
|
||||
static getViewPort(): ViewPort {
|
||||
return ViewPort.get();
|
||||
}
|
||||
|
||||
static getWeatherRenderer(): WeatherRenderer {
|
||||
return WeatherRenderer.get();
|
||||
}
|
||||
|
||||
static getZone(): Zone {
|
||||
return Zone.get();
|
||||
}
|
||||
}
|
||||
|
||||
export const singletons = SingletonRepo;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var marauroa: any;
|
||||
declare var stendhal: any;
|
||||
import { marauroa } from "marauroa"
|
||||
import { stendhal } from "./stendhal";
|
||||
|
||||
import { singletons } from "./SingletonRepo";
|
||||
|
||||
|
|
@ -766,7 +766,7 @@ export class SlashActionRepo {
|
|||
execute: (type: string, params: string[], remainder: string): boolean => {
|
||||
const newMode = !stendhal.config.getBoolean("input.doubleclick");
|
||||
stendhal.config.set("input.doubleclick", newMode);
|
||||
stendhal.ui.gamewindow.updateClickMode();
|
||||
ViewPort.get().updateClickMode();
|
||||
|
||||
if (newMode) {
|
||||
Chat.log("info", "Click mode is now set to double click.");
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var stendhal: any;
|
||||
|
||||
import { ParamList } from "./ParamList";
|
||||
import { SlashAction } from "./SlashAction";
|
||||
|
|
@ -20,6 +19,7 @@ import { ui } from "../ui/UI";
|
|||
import { AboutDialog } from "../ui/dialog/AboutDialog";
|
||||
|
||||
import { Pair } from "../util/Pair";
|
||||
import { stendhal } from "../stendhal";
|
||||
|
||||
|
||||
export class AboutAction extends SlashAction {
|
||||
|
|
@ -28,7 +28,7 @@ export class AboutAction extends SlashAction {
|
|||
|
||||
execute(_type: string, _params: string[], _remainder: string): boolean {
|
||||
const wstate = stendhal.config.getWindowState("about");
|
||||
const offset = stendhal.ui.getPageOffset();
|
||||
const offset = ui.getPageOffset();
|
||||
|
||||
const content = new AboutDialog();
|
||||
const dialog = ui.createSingletonFloatingWindow(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2022-2024 - Stendhal *
|
||||
* (C) Copyright 2022-2026 - Stendhal *
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
|
@ -9,21 +9,20 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import { singletons } from "../SingletonRepo";
|
||||
|
||||
import { ui } from "../ui/UI";
|
||||
import { UIComponentEnum } from "../ui/UIComponentEnum";
|
||||
import { FloatingWindow } from "../ui/toolkit/FloatingWindow";
|
||||
|
||||
import { SlashAction } from "./SlashAction";
|
||||
import { ShowFloatingWindowComponent } from "../ui/component/ShowFloatingWindowComponent";
|
||||
import { Panel } from "ui/toolkit/Panel";
|
||||
import { ShowFloatingWindowComponent } from "../ui/component/ShowFloatingWindowComponent";
|
||||
import { SlashAction } from "./SlashAction";
|
||||
|
||||
import { Chat } from "../util/Chat";
|
||||
import { Debug } from "../util/Debug";
|
||||
|
||||
declare var marauroa: any;
|
||||
declare var stendhal: any;
|
||||
import { marauroa } from "marauroa";
|
||||
import { WeatherRenderer } from "util/WeatherRenderer";
|
||||
import { stendhal } from "../stendhal";
|
||||
|
||||
/**
|
||||
* performances debugging actions
|
||||
|
|
@ -55,6 +54,8 @@ export class DebugAction extends SlashAction {
|
|||
Debug.setActive("screencap", !Debug.isActive("screencap"));
|
||||
Chat.log("client", "Screen capture debugging " + (Debug.isActive("screencap") ? "enabled"
|
||||
: "disabled"));
|
||||
} else if(params[0] === "light") {
|
||||
Debug.toggle("light");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -66,7 +67,8 @@ export class DebugAction extends SlashAction {
|
|||
" /debug ui [pop]",
|
||||
" /debug weather [<name>]",
|
||||
" /debug settings",
|
||||
" /debug touch"
|
||||
" /debug touch",
|
||||
" /debug light"
|
||||
];
|
||||
Chat.log("client", usage);
|
||||
}
|
||||
|
|
@ -135,14 +137,9 @@ export class DebugAction extends SlashAction {
|
|||
|
||||
if (weather) {
|
||||
weather = weather.replace(/ /g, "_");
|
||||
const wfilename = stendhal.paths.weather + "/" + weather + ".png";
|
||||
if (!stendhal.data.sprites.getCached(wfilename)) {
|
||||
Chat.logH("error", "unknown weather: " + wfilename);
|
||||
return;
|
||||
}
|
||||
WeatherRenderer.get().update(weather);
|
||||
}
|
||||
|
||||
singletons.getWeatherRenderer().update(weather);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ import { SlashAction } from "./SlashAction";
|
|||
|
||||
import { ScreenCapture } from "../util/ScreenCapture";
|
||||
|
||||
declare var stendhal: any;
|
||||
import { stendhal } from "../stendhal";
|
||||
import { ViewPort } from "ui/ViewPort";
|
||||
|
||||
|
||||
export class ScreenCaptureAction extends SlashAction {
|
||||
|
|
@ -35,7 +36,7 @@ export class ScreenCaptureAction extends SlashAction {
|
|||
return true;
|
||||
}
|
||||
this.recorder = new ScreenCapture();
|
||||
this.recorder.start(stendhal.ui.viewport.getElement() as HTMLCanvasElement);
|
||||
this.recorder.start(ViewPort.get().getElement());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var stendhal: any;
|
||||
import { stendhal } from "../stendhal";
|
||||
|
||||
import { SlashAction } from "./SlashAction";
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ export class SettingsAction extends SlashAction {
|
|||
|
||||
execute(_type: string, _params: string[], _remainder: string): boolean {
|
||||
const wstate = stendhal.config.getWindowState("menu");
|
||||
const offset = stendhal.ui.getPageOffset();
|
||||
const offset = ui.getPageOffset();
|
||||
|
||||
const content = new SettingsDialog();
|
||||
const dialog = ui.createSingletonFloatingWindow(
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var marauroa: any;
|
||||
import { marauroa } from "marauroa"
|
||||
|
||||
import { ParamList } from "./ParamList";
|
||||
import { Pair } from "../util/Pair";
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var marauroa: any;
|
||||
declare var stendhal: any;
|
||||
import { marauroa } from "marauroa"
|
||||
import { stendhal } from "../stendhal";
|
||||
|
||||
|
||||
export class CStatus {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var stendhal: any;
|
||||
import { stendhal } from "../stendhal";
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright © 2003-2023 - Stendhal *
|
||||
* Copyright © 2003-2026 - Stendhal *
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
|
@ -9,10 +9,9 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import { Paths } from "./Paths";
|
||||
import { JSONLoader } from "../util/JSONLoader";
|
||||
|
||||
declare var stendhal: any;
|
||||
import { htmlImageStore } from "./HTMLImageStore";
|
||||
import { Paths } from "./Paths";
|
||||
|
||||
|
||||
export class EmojiStore {
|
||||
|
|
@ -71,7 +70,7 @@ export class EmojiStore {
|
|||
if (!filename) {
|
||||
return;
|
||||
}
|
||||
return stendhal.data.sprites.get(filename);
|
||||
return htmlImageStore.get(filename);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var stendhal: any;
|
||||
import { stendhal } from "../stendhal";
|
||||
|
||||
import { Entity } from "../entity/Entity";
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var stendhal: any;
|
||||
import { stendhal } from "../stendhal";
|
||||
|
||||
import { SlashActionRepo } from "../SlashActionRepo";
|
||||
|
||||
|
|
|
|||
290
src/js/stendhal/data/HTMLImageStore.ts
Normal file
290
src/js/stendhal/data/HTMLImageStore.ts
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2003-2026 - Stendhal *
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Affero General Public License as *
|
||||
* published by the Free Software Foundation; either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import { Paths } from "./Paths";
|
||||
import { ImageFilter } from "../sprite/image/ImageFilter";
|
||||
|
||||
export class HTMLImageStore {
|
||||
|
||||
private knownBrokenUrls: {[url: string]: boolean} = {};
|
||||
private images: {[filename: string]: CanvasImageSource} = {};
|
||||
|
||||
private knownShadows: {[key: string]: boolean} = {
|
||||
"24x32": true,
|
||||
"32x32": true,
|
||||
"32x48": true,
|
||||
"32x48_long": true,
|
||||
"48x64": true,
|
||||
"48x64_float": true,
|
||||
"64x48": true,
|
||||
"64x64": true,
|
||||
"64x85": true,
|
||||
"64x96": true,
|
||||
"76x64": true,
|
||||
"81x96": true,
|
||||
"96x96": true,
|
||||
"96x128": true,
|
||||
"128x96": true,
|
||||
"128x170": true,
|
||||
"144x128": true,
|
||||
"168x224": true,
|
||||
"192x192": true,
|
||||
"192x192_float": true,
|
||||
"192x256": true,
|
||||
"320x440": true,
|
||||
"ent": true
|
||||
};
|
||||
|
||||
// alternatives for known images that may be considered violent or mature
|
||||
private knownSafeSprites: {[filename: string]: boolean} = {
|
||||
[Paths.sprites + "/monsters/huge_animal/thing"]: true,
|
||||
[Paths.sprites + "/monsters/mutant/imperial_mutant"]: true,
|
||||
[Paths.sprites + "/monsters/undead/bloody_zombie"]: true,
|
||||
[Paths.sprites + "/npc/deadmannpc"]: true
|
||||
};
|
||||
|
||||
// TODO: move to animation.json
|
||||
animations: {[key: string]: any} = {
|
||||
idea: {
|
||||
"love": {delay: 100, offsetX: 24, offsetY: -8}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
get(filename: string): any {
|
||||
if (!filename) {
|
||||
return {};
|
||||
}
|
||||
if (filename.indexOf("undefined") > -1) {
|
||||
if (!this.knownBrokenUrls[filename]) {
|
||||
console.log("Broken image path: ", filename, new Error());
|
||||
}
|
||||
this.knownBrokenUrls[filename] = true;
|
||||
return {};
|
||||
}
|
||||
if (this.images[filename]) {
|
||||
return this.images[filename];
|
||||
}
|
||||
var temp = new Image();
|
||||
temp.onerror = (function(t: HTMLImageElement, store: HTMLImageStore) {
|
||||
return function() {
|
||||
if (t.src && !store.knownBrokenUrls[t.src]) {
|
||||
console.log("Broken image path:", t.src, new Error());
|
||||
store.knownBrokenUrls[t.src] = true;
|
||||
}
|
||||
const failsafe = store.getFailsafe();
|
||||
if (failsafe.src && t.src !== failsafe.src) {
|
||||
t.src = failsafe.src;
|
||||
}
|
||||
};
|
||||
})(temp, this);
|
||||
temp.src = filename;
|
||||
this.images[filename] = temp;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates an image.
|
||||
*
|
||||
* @param img
|
||||
* Image to be rotated.
|
||||
* @param angle
|
||||
* Angle of rotation.
|
||||
*/
|
||||
private rotate(img: HTMLImageElement, angle: number) {
|
||||
const canvas = document.getElementById("drawing-stage")! as HTMLCanvasElement;
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
// make sure working with blank canvas
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
|
||||
ctx.translate(canvas.width / 2, canvas.height / 2);
|
||||
ctx.rotate(angle * Math.PI / 180);
|
||||
ctx.translate(-canvas.width / 2, -canvas.height / 2);
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
img.src = canvas.toDataURL("image/png");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a rotated image.
|
||||
*
|
||||
* @param filename
|
||||
* Path to target image file.
|
||||
* @param angle
|
||||
* Angle of rotation.
|
||||
* @return
|
||||
* HTMLImageElement.
|
||||
*/
|
||||
getRotated(filename: string, angle: number): any {
|
||||
if (angle == 0) {
|
||||
return this.get(filename);
|
||||
}
|
||||
const id = filename + "-rot" + angle;
|
||||
if (this.images[id]) {
|
||||
return this.get(id);
|
||||
}
|
||||
// NOTE: cannot use HTMLImageElement.cloneNode here, must get base image then transfer
|
||||
// `src` property when ready
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
img.onload = null;
|
||||
this.rotate(img, angle);
|
||||
}
|
||||
const baseImg = this.get(filename);
|
||||
if (baseImg.complete) {
|
||||
img.src = baseImg.src;
|
||||
} else {
|
||||
baseImg.onload = () => {
|
||||
baseImg.onload = null;
|
||||
img.src = baseImg.src;
|
||||
}
|
||||
}
|
||||
this.images[id] = img;
|
||||
return img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an image to cache.
|
||||
*
|
||||
* @param {string} id
|
||||
* Cache identifier.
|
||||
* @param {SpriteImage}
|
||||
* Image to be cached.
|
||||
*/
|
||||
cache(id: string, image: CanvasImageSource) {
|
||||
this.images[id] = image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when we only want an image if it was previously cached.
|
||||
*
|
||||
* @param filename
|
||||
* Full file path.
|
||||
* @return
|
||||
* HTMLImageElement or undefined.
|
||||
*/
|
||||
getCached(filename: string): any {
|
||||
return this.images[filename];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the failsafe sprite.
|
||||
*
|
||||
* @return
|
||||
* HTMLImageElement with failsafe image data.
|
||||
*/
|
||||
getFailsafe(): HTMLImageElement {
|
||||
const filename = Paths.sprites + "/failsafe.png";
|
||||
let failsafe = this.images[filename];
|
||||
if (failsafe) {
|
||||
} else {
|
||||
failsafe = new Image();
|
||||
failsafe.src = filename;
|
||||
this.images[filename] = failsafe;
|
||||
}
|
||||
return failsafe as HTMLImageElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks cached images for a valid filename.
|
||||
*
|
||||
* @param filename
|
||||
* Image filename to be checked.
|
||||
* @return
|
||||
* Path to image or failsafe image file.
|
||||
*/
|
||||
checkPath(filename: string): string {
|
||||
return this.get(filename).src;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} fileName
|
||||
* @param {string} filter
|
||||
* @param {number=} param
|
||||
*/
|
||||
getFiltered(fileName: string, filter: string, param?: number) {
|
||||
const img = this.get(fileName);
|
||||
if (!img.complete || img.width === 0 || img.height === 0) {
|
||||
return img;
|
||||
}
|
||||
const filteredName = fileName + " " + filter + " " + param;
|
||||
let filtered = this.images[filteredName];
|
||||
if (typeof(filtered) === "undefined") {
|
||||
const canvas = document.createElement("canvas") as any;
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
ctx.drawImage(img, 0, 0);
|
||||
const imgData = ctx.getImageData(0, 0, img.width, img.height);
|
||||
new ImageFilter().filter(imgData, filter, param);
|
||||
ctx.putImageData(imgData, 0, 0);
|
||||
canvas.complete = true;
|
||||
this.images[filteredName] = filtered = canvas;
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a shadow sprite if the style is available.
|
||||
*
|
||||
* @param shadowStyle
|
||||
* Style of shadow to get from cache.
|
||||
* @return
|
||||
* Image sprite or <code>undefined</code>.
|
||||
*/
|
||||
getShadow(shadowStyle: string): any {
|
||||
if (this.knownShadows[shadowStyle]) {
|
||||
const img = new Image();
|
||||
img.src = Paths.sprites + "/shadow/" + shadowStyle + ".png";
|
||||
return img;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is a "safe" image available for sprite.
|
||||
*
|
||||
* @param filename
|
||||
* The sprite image base file path.
|
||||
* @return
|
||||
* <code>true</code> if a known safe image is available.
|
||||
*/
|
||||
hasSafeImage(filename: string): boolean {
|
||||
return this.knownSafeSprites[filename] == true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called at startup to pre-cache certain images.
|
||||
*/
|
||||
startupCache() {
|
||||
// failsafe image
|
||||
this.getFailsafe();
|
||||
// tutorial profile
|
||||
this.get(Paths.sprites + "/npc/floattingladynpc.png");
|
||||
// achievement assets
|
||||
this.get(Paths.gui + "/banner_background.png");
|
||||
for (const cat of ["commerce", "deathmatch", "experience", "fighting", "friend",
|
||||
"interior_zone", "item", "obtain", "outside_zone", "production", "quest",
|
||||
"quest_ados_items", "quest_kill_blordroughs", "quest_kirdneh_item",
|
||||
"quest_mithrilbourgh_enemy_army", "quest_semos_monster", "special",
|
||||
"underground_zone"]) {
|
||||
this.get(Paths.achievements + "/" + cat + ".png");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SpriteStore singleton instance
|
||||
export const htmlImageStore = /* @__PURE__ */ new HTMLImageStore();
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2003-2023 - Stendhal *
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Affero General Public License as *
|
||||
* published by the Free Software Foundation; either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var stendhal: any;
|
||||
|
||||
|
||||
/*
|
||||
* Start: http://www.webreference.com/programming/javascript/gr/column3/
|
||||
* ( https://web.archive.org/web/20110910064905/http://www.webreference.com:80/programming/javascript/gr/column3/index.html )
|
||||
*
|
||||
function ImagePreloader(images, callback) {
|
||||
// store the call-back
|
||||
this.callback = callback;
|
||||
|
||||
// initialize internal state.
|
||||
this.nLoaded = 0;
|
||||
this.nProcessed = 0;
|
||||
stendhal.data.map.aImages = new Array;
|
||||
|
||||
// record the number of images.
|
||||
this.nImages = images.length;
|
||||
|
||||
// for each image, call preload()
|
||||
for ( var i = 0; i < images.length; i++) {
|
||||
this.preload(images[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ImagePreloader.prototype.preload = function(image) {
|
||||
// create new Image object and add to array
|
||||
var oImage = new Image;
|
||||
stendhal.data.map.aImages.push(oImage);
|
||||
|
||||
// set up event handlers for the Image object
|
||||
oImage.onload = ImagePreloader.prototype.onload;
|
||||
oImage.onerror = ImagePreloader.prototype.onerror;
|
||||
oImage.onabort = ImagePreloader.prototype.onabort;
|
||||
|
||||
// assign pointer back to this.
|
||||
oImage.oImagePreloader = this;
|
||||
oImage.bLoaded = false;
|
||||
|
||||
// assign the .src property of the Image object
|
||||
oImage.src = image;
|
||||
};
|
||||
|
||||
ImagePreloader.prototype.onComplete = function() {
|
||||
this.nProcessed++;
|
||||
if (this.nProcessed == this.nImages) {
|
||||
this.callback();
|
||||
}
|
||||
};
|
||||
|
||||
ImagePreloader.prototype.onload = function() {
|
||||
this.bLoaded = true;
|
||||
this.oImagePreloader.nLoaded++;
|
||||
this.oImagePreloader.onComplete();
|
||||
};
|
||||
|
||||
ImagePreloader.prototype.onerror = function() {
|
||||
this.bError = true;
|
||||
this.oImagePreloader.onComplete();
|
||||
console.error("Error loading " + this.src);
|
||||
};
|
||||
|
||||
ImagePreloader.prototype.onabort = function() {
|
||||
this.bAbort = true;
|
||||
this.oImagePreloader.onComplete();
|
||||
console.error("Loading " + this.src + " was aborted");
|
||||
};
|
||||
*
|
||||
* End: http://www.webreference.com/programming/javascript/gr/column3/
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* preloads images
|
||||
*
|
||||
* @param images image url to load
|
||||
* @param callback callback to invoke
|
||||
* @constructor
|
||||
*/
|
||||
export class ImagePreloader extends Function {
|
||||
|
||||
oImagePreloader: ImagePreloader;
|
||||
src?: string;
|
||||
callback: Function;
|
||||
|
||||
// internal state
|
||||
bLoaded: boolean;
|
||||
bError: boolean;
|
||||
bAbort: boolean;
|
||||
nLoaded: number;
|
||||
nProcessed: number;
|
||||
|
||||
// number of images
|
||||
nImages: number;
|
||||
|
||||
|
||||
constructor(images: string[], callback: Function) {
|
||||
super();
|
||||
|
||||
this.oImagePreloader = {} as ImagePreloader;
|
||||
// store the call-back
|
||||
this.callback = callback;
|
||||
|
||||
// initialize internal state.
|
||||
this.bLoaded = false;
|
||||
this.bError = false;
|
||||
this.bAbort = false;
|
||||
this.nLoaded = 0;
|
||||
this.nProcessed = 0;
|
||||
stendhal.data.map.aImages = new Array();
|
||||
|
||||
// record the number of images.
|
||||
this.nImages = images.length;
|
||||
|
||||
// for each image, call preload()
|
||||
for (let i = 0; i < images.length; i++) {
|
||||
this.preload(images[i]);
|
||||
}
|
||||
}
|
||||
|
||||
preload(image: string) {
|
||||
// create new Image object and add to array
|
||||
const oImage = new Image() as any;
|
||||
stendhal.data.map.aImages.push(oImage);
|
||||
|
||||
// set up event handlers for the Image object
|
||||
oImage.onload = ImagePreloader.prototype.onload;
|
||||
oImage.onerror = ImagePreloader.prototype.onerror;
|
||||
oImage.onabort = ImagePreloader.prototype.onabort;
|
||||
|
||||
// assign pointer back to this
|
||||
oImage.oImagePreloader = this;
|
||||
oImage.bLoaded = false;
|
||||
|
||||
// assign the .src property of the Image object
|
||||
oImage.src = image;
|
||||
}
|
||||
|
||||
onComplete() {
|
||||
this.nProcessed++;
|
||||
if (this.nProcessed == this.nImages) {
|
||||
this.callback();
|
||||
}
|
||||
}
|
||||
|
||||
onload() {
|
||||
this.bLoaded = true;
|
||||
this.oImagePreloader.nLoaded++;
|
||||
this.oImagePreloader.onComplete();
|
||||
}
|
||||
|
||||
onerror() {
|
||||
this.bError = true;
|
||||
this.oImagePreloader.onComplete();
|
||||
console.error("Error loading " + this.src);
|
||||
}
|
||||
|
||||
onabort() {
|
||||
this.bAbort = true;
|
||||
this.oImagePreloader.onComplete();
|
||||
console.error("Loading " + this.src + " was aborted");
|
||||
}
|
||||
}
|
||||
|
|
@ -10,11 +10,14 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import { DrawingStage } from "../util/DrawingStage";
|
||||
import { Pair } from "../util/Pair";
|
||||
import { StringUtil } from "../util/StringUtil";
|
||||
import { Paths } from "./Paths";
|
||||
|
||||
declare var stendhal: any;
|
||||
import { stendhal } from "../stendhal";
|
||||
import { ImageMetadata } from "sprite/image/ImageMetadata";
|
||||
import { MultilayerImageLoader } from "sprite/image/MultilayerImageLoader";
|
||||
import { OutfitStore } from "./OutfitStore";
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -113,7 +116,7 @@ export class Outfit {
|
|||
public getLayers(): Pair<string, number>[] {
|
||||
const layers: Pair<string, number>[] = [];
|
||||
// only include valid layers
|
||||
for (const name of stendhal.data.outfit.getLayerNames()) {
|
||||
for (const name of OutfitStore.get().getLayerNames()) {
|
||||
let index = this.layers[name];
|
||||
if (index != undefined) {
|
||||
layers.push(new Pair(name, index));
|
||||
|
|
@ -151,7 +154,7 @@ export class Outfit {
|
|||
* Color value or `undefined`.
|
||||
*/
|
||||
public getLayerColor(name: string): number|undefined {
|
||||
if (stendhal.data.outfit.isSkinLayer(name)) {
|
||||
if (OutfitStore.get().isSkinLayer(name)) {
|
||||
name = "skin";
|
||||
}
|
||||
return this.coloring && name in this.coloring ? this.coloring[name] : undefined;
|
||||
|
|
@ -193,40 +196,14 @@ export class Outfit {
|
|||
*
|
||||
* TODO:
|
||||
* - use dress layer based on body type
|
||||
*
|
||||
* @param {Function} callback
|
||||
* Function to pass image to when ready.
|
||||
*/
|
||||
toImage(callback: Function) {
|
||||
const sig = this.getSignature();
|
||||
// get directly from cache since we don't want to return failsafe image
|
||||
let image: HTMLImageElement = stendhal.data.sprites.getCached(sig);
|
||||
|
||||
const onReady = function(e?: Event) {
|
||||
image.removeEventListener("load", onReady);
|
||||
callback(image);
|
||||
};
|
||||
|
||||
if (image instanceof HTMLImageElement) {
|
||||
if (image.height > 0) {
|
||||
onReady();
|
||||
} else {
|
||||
image.addEventListener("load", onReady);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const stage = DrawingStage.get();
|
||||
stage.reset();
|
||||
stage.setSize(48 * 3, 64 * 4);
|
||||
|
||||
async toImage(): Promise<ImageBitmap> {
|
||||
let parts: ImageMetadata[] = [];
|
||||
let outfitLayers = this.getLayers();
|
||||
const detailIndex = this.getLayerIndex("detail") || 0;
|
||||
if (stendhal.data.outfit.detailHasRearLayer(detailIndex)) {
|
||||
if (OutfitStore.get().detailHasRearLayer(detailIndex)) {
|
||||
outfitLayers = [new Pair("detail-rear", detailIndex), ...outfitLayers];
|
||||
}
|
||||
|
||||
const layers: HTMLImageElement[] = [];
|
||||
for (const l of outfitLayers) {
|
||||
let layerName = l.first;
|
||||
let suffix = "";
|
||||
|
|
@ -235,58 +212,21 @@ export class Outfit {
|
|||
layerName = layerName.replace(/-rear$/, "");
|
||||
}
|
||||
const layerIndex = l.second;
|
||||
let layerPath = stendhal.paths.sprites + "/outfit/" + layerName + "/"
|
||||
let layerPath = Paths.sprites + "/outfit/" + layerName + "/"
|
||||
+ StringUtil.padLeft(""+layerIndex, "0", 3) + suffix;
|
||||
if (layerName === "body" && stendhal.config.getBoolean("effect.no-nude")) {
|
||||
// FIXME: some non-player pickable bodies don't have "no-nude" variant
|
||||
layerPath += "-nonude";
|
||||
}
|
||||
layerPath += ".png";
|
||||
const coloring = this.getLayerColor(layerName);
|
||||
if (typeof(coloring) === "undefined") {
|
||||
layers.push(stendhal.data.sprites.get(layerPath));
|
||||
} else {
|
||||
layers.push(stendhal.data.sprites.getFiltered(layerPath, "trueColor", coloring));
|
||||
let filter = undefined;
|
||||
let coloring = this.getLayerColor(layerName);
|
||||
if (coloring) {
|
||||
filter = "trueColor";
|
||||
}
|
||||
parts.push(new ImageMetadata(layerPath, filter, coloring));
|
||||
}
|
||||
|
||||
if (layers.length == 0) {
|
||||
image = stendhal.data.sprites.getFailsafe();
|
||||
callback(image);
|
||||
return;
|
||||
}
|
||||
|
||||
let onAllLayersReady: Function;
|
||||
const onLayerReady = function(e?: Event) {
|
||||
for (const layer of layers) {
|
||||
if (!layer.complete || layer.height === 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
onAllLayersReady();
|
||||
};
|
||||
|
||||
onAllLayersReady = function() {
|
||||
for (const layer of layers) {
|
||||
layer.removeEventListener("load", onLayerReady);
|
||||
stage.drawImage(layer);
|
||||
}
|
||||
image = stage.toImage();
|
||||
stage.reset();
|
||||
stendhal.data.sprites.cache(sig, image);
|
||||
if (image.height > 0) {
|
||||
onReady();
|
||||
} else {
|
||||
image.addEventListener("load", onReady);
|
||||
}
|
||||
};
|
||||
|
||||
for (const layer of layers) {
|
||||
if (layer.height > 0) {
|
||||
onLayerReady();
|
||||
} else {
|
||||
layer.addEventListener("load", onLayerReady);
|
||||
}
|
||||
}
|
||||
return await new MultilayerImageLoader(parts).load();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export class OutfitStore {
|
|||
|
||||
|
||||
// player pickable layers
|
||||
private count: {[key: string]: number} = {
|
||||
public readonly count: {[key: string]: number} = {
|
||||
"hat": 19,
|
||||
"hair": 57,
|
||||
"mask": 9,
|
||||
|
|
|
|||
|
|
@ -1,618 +0,0 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2003-2024 - Stendhal *
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Affero General Public License as *
|
||||
* published by the Free Software Foundation; either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var stendhal: any;
|
||||
|
||||
import { Paths } from "./Paths";
|
||||
|
||||
|
||||
class SpriteImage extends Image {
|
||||
// number of times the image has been accessed after initial creation
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
export class SpriteStore {
|
||||
|
||||
private knownBrokenUrls: {[url: string]: boolean} = {};
|
||||
private images: {[filename: string]: SpriteImage} = {};
|
||||
|
||||
private knownShadows: {[key: string]: boolean} = {
|
||||
"24x32": true,
|
||||
"32x32": true,
|
||||
"32x48": true,
|
||||
"32x48_long": true,
|
||||
"48x64": true,
|
||||
"48x64_float": true,
|
||||
"64x48": true,
|
||||
"64x64": true,
|
||||
"64x85": true,
|
||||
"64x96": true,
|
||||
"76x64": true,
|
||||
"81x96": true,
|
||||
"96x96": true,
|
||||
"96x128": true,
|
||||
"128x96": true,
|
||||
"128x170": true,
|
||||
"144x128": true,
|
||||
"168x224": true,
|
||||
"192x192": true,
|
||||
"192x192_float": true,
|
||||
"192x256": true,
|
||||
"320x440": true,
|
||||
"ent": true
|
||||
};
|
||||
|
||||
// alternatives for known images that may be considered violent or mature
|
||||
private knownSafeSprites: {[filename: string]: boolean} = {
|
||||
[Paths.sprites + "/monsters/huge_animal/thing"]: true,
|
||||
[Paths.sprites + "/monsters/mutant/imperial_mutant"]: true,
|
||||
[Paths.sprites + "/monsters/undead/bloody_zombie"]: true,
|
||||
[Paths.sprites + "/npc/deadmannpc"]: true
|
||||
};
|
||||
|
||||
// TODO: move to animation.json
|
||||
private animations: {[key: string]: any} = {
|
||||
idea: {
|
||||
"love": {delay: 100, offsetX: 24, offsetY: -8}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hidden singleton constructor.
|
||||
*/
|
||||
protected constructor() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
get(filename: string): any {
|
||||
if (!filename) {
|
||||
return {};
|
||||
}
|
||||
if (filename.indexOf("undefined") > -1) {
|
||||
if (!this.knownBrokenUrls[filename]) {
|
||||
console.log("Broken image path: ", filename, new Error());
|
||||
}
|
||||
this.knownBrokenUrls[filename] = true;
|
||||
return {};
|
||||
}
|
||||
if (this.images[filename]) {
|
||||
this.images[filename].counter++;
|
||||
return this.images[filename];
|
||||
}
|
||||
var temp = new Image() as SpriteImage;
|
||||
// TypeError: Image constructor: 'new' is required
|
||||
//~ var temp = new SpriteImage();
|
||||
temp.counter = 0;
|
||||
temp.onerror = (function(t: SpriteImage, store: SpriteStore) {
|
||||
return function() {
|
||||
if (t.src && !store.knownBrokenUrls[t.src]) {
|
||||
console.log("Broken image path:", t.src, new Error());
|
||||
store.knownBrokenUrls[t.src] = true;
|
||||
}
|
||||
const failsafe = store.getFailsafe();
|
||||
if (failsafe.src && t.src !== failsafe.src) {
|
||||
t.src = failsafe.src;
|
||||
}
|
||||
};
|
||||
})(temp, this);
|
||||
temp.src = filename;
|
||||
this.images[filename] = temp;
|
||||
return temp;
|
||||
}
|
||||
|
||||
getWithPromise(filename: string): any {
|
||||
return new Promise((resolve) => {
|
||||
if (typeof(this.images[filename]) != "undefined") {
|
||||
this.images[filename].counter++;
|
||||
resolve(this.images[filename]);
|
||||
}
|
||||
|
||||
const image = new Image() as SpriteImage;
|
||||
// TypeError: Image constructor: 'new' is required
|
||||
//~ const image = new SpriteImage();
|
||||
image.counter = 0;
|
||||
this.images[filename] = image;
|
||||
image.onload = () => resolve(image);
|
||||
image.src = filename;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates an image.
|
||||
*
|
||||
* @param img
|
||||
* Image to be rotated.
|
||||
* @param angle
|
||||
* Angle of rotation.
|
||||
*/
|
||||
private rotate(img: HTMLImageElement, angle: number) {
|
||||
const canvas = <HTMLCanvasElement> document.getElementById("drawing-stage")!;
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
// make sure working with blank canvas
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
|
||||
ctx.translate(canvas.width / 2, canvas.height / 2);
|
||||
ctx.rotate(angle * Math.PI / 180);
|
||||
ctx.translate(-canvas.width / 2, -canvas.height / 2);
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
img.src = canvas.toDataURL("image/png");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a rotated image.
|
||||
*
|
||||
* @param filename
|
||||
* Path to target image file.
|
||||
* @param angle
|
||||
* Angle of rotation.
|
||||
* @return
|
||||
* HTMLImageElement.
|
||||
*/
|
||||
getRotated(filename: string, angle: number): any {
|
||||
if (angle == 0) {
|
||||
return this.get(filename);
|
||||
}
|
||||
const id = filename + "-rot" + angle;
|
||||
if (this.images[id]) {
|
||||
return this.get(id);
|
||||
}
|
||||
// NOTE: cannot use HTMLImageElement.cloneNode here, must get base image then transfer
|
||||
// `src` property when ready
|
||||
const img = new Image() as SpriteImage;
|
||||
img.counter = 0;
|
||||
img.onload = () => {
|
||||
img.onload = null;
|
||||
this.rotate(img, angle);
|
||||
}
|
||||
const baseImg = this.get(filename);
|
||||
if (baseImg.complete) {
|
||||
img.src = baseImg.src;
|
||||
} else {
|
||||
baseImg.onload = () => {
|
||||
baseImg.onload = null;
|
||||
img.src = baseImg.src;
|
||||
}
|
||||
}
|
||||
this.images[id] = img;
|
||||
return img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an image to cache.
|
||||
*
|
||||
* @param {string} id
|
||||
* Cache identifier.
|
||||
* @param {SpriteImage}
|
||||
* Image to be cached.
|
||||
*/
|
||||
cache(id: string, image: SpriteImage) {
|
||||
image.counter = 0;
|
||||
this.images[id] = image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when we only want an image if it was previously cached.
|
||||
*
|
||||
* @param filename
|
||||
* Full file path.
|
||||
* @return
|
||||
* HTMLImageElement or undefined.
|
||||
*/
|
||||
getCached(filename: string): any {
|
||||
return this.images[filename];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the failsafe sprite.
|
||||
*
|
||||
* @return
|
||||
* HTMLImageElement with failsafe image data.
|
||||
*/
|
||||
getFailsafe(): HTMLImageElement {
|
||||
const filename = Paths.sprites + "/failsafe.png";
|
||||
let failsafe = this.images[filename];
|
||||
if (failsafe) {
|
||||
failsafe.counter++;
|
||||
} else {
|
||||
failsafe = new Image() as SpriteImage;
|
||||
// TypeError: Image constructor: 'new' is required
|
||||
//~ failsafe = new SpriteImage();
|
||||
failsafe.counter = 0;
|
||||
failsafe.src = filename;
|
||||
this.images[filename] = failsafe;
|
||||
}
|
||||
return failsafe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks cached images for a valid filename.
|
||||
*
|
||||
* @param filename
|
||||
* Image filename to be checked.
|
||||
* @return
|
||||
* Path to image or failsafe image file.
|
||||
*/
|
||||
checkPath(filename: string): string {
|
||||
return this.get(filename).src;
|
||||
}
|
||||
|
||||
/** deletes all objects that have not been accessed since this method was called last time */
|
||||
// TODO: call clean on map change
|
||||
clean() {
|
||||
for (var i in this.images) {
|
||||
console.log(typeof(this.images[i]));
|
||||
if (this.images[i] instanceof SpriteImage) {
|
||||
if (this.images[i].counter > 0) {
|
||||
this.images[i].counter--;
|
||||
} else {
|
||||
delete(this.images[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an image element whose image data is an area of a specified image.
|
||||
* If the area matches the original image, the image itself is returned.
|
||||
* Otherwise <em>a copy</em> of the image data is returned. This is meant
|
||||
* to be used for obtaining the drag image for drag and drop.
|
||||
*
|
||||
* @param image original image
|
||||
* @param width width of the area
|
||||
* @param height height of the area
|
||||
* @param {number=} offsetX optional. left x coordinate of the area
|
||||
* @param {number=} offsetY optional. top y coordinate of the area
|
||||
*/
|
||||
getAreaOf(image: HTMLImageElement, width: number, height: number,
|
||||
offsetX?: number, offsetY?: number): any {
|
||||
try {
|
||||
offsetX = offsetX || 0;
|
||||
offsetY = offsetY || 0;
|
||||
if ((image.width === width) && (image.height === height)
|
||||
&& (offsetX === 0) && (offsetY === 0)) {
|
||||
return image;
|
||||
}
|
||||
var canvas = document.createElement("canvas") as HTMLCanvasElement;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
var ctx = canvas.getContext("2d")!;
|
||||
ctx.drawImage(image, offsetX, offsetY, width, height, 0, 0, width, height);
|
||||
// Firefox would be able to use the canvas directly as a drag image, but
|
||||
// Chrome does not. This should work in any standards compliant browser.
|
||||
var newImage = new Image();
|
||||
newImage.src = canvas.toDataURL("image/png");
|
||||
return newImage;
|
||||
} catch (err) {
|
||||
if (err instanceof DOMException) {
|
||||
return this.getFailsafe();
|
||||
} else {
|
||||
// don't ignore other errors
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} fileName
|
||||
* @param {string} filter
|
||||
* @param {number=} param
|
||||
*/
|
||||
getFiltered(fileName: string, filter: string, param?: number) {
|
||||
const img = this.get(fileName);
|
||||
let filterFn;
|
||||
if (typeof(filter) === "undefined"
|
||||
|| !(filterFn = this.filter[filter])
|
||||
|| !img.complete || img.width === 0 || img.height === 0) {
|
||||
return img;
|
||||
}
|
||||
const filteredName = fileName + " " + filter + " " + param;
|
||||
let filtered: SpriteImage = this.images[filteredName];
|
||||
if (typeof(filtered) === "undefined") {
|
||||
const canvas = document.createElement("canvas") as any;
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
ctx.drawImage(img, 0, 0);
|
||||
const imgData = ctx.getImageData(0, 0, img.width, img.height);
|
||||
const data = imgData.data;
|
||||
filterFn(data, param);
|
||||
ctx.putImageData(imgData, 0, 0);
|
||||
canvas.complete = true;
|
||||
this.images[filteredName] = filtered = canvas as SpriteImage;
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} fileName
|
||||
* @param {string} filter
|
||||
* @param {number=} param
|
||||
*/
|
||||
getFilteredWithPromise(fileName: string, filter: string, param?: number) {
|
||||
const imgPromise = this.getWithPromise(fileName);
|
||||
return imgPromise.then(function (img: HTMLImageElement) {
|
||||
let filterFn: Function;
|
||||
if (typeof(filter) === "undefined"
|
||||
|| !(filterFn = stendhal.data.sprites.filter[filter])
|
||||
|| !img.complete || img.width === 0 || img.height === 0) {
|
||||
return img;
|
||||
}
|
||||
const filteredName = fileName + " " + filter + " " + param;
|
||||
let filtered: SpriteImage = stendhal.data.sprites.images[filteredName];
|
||||
if (typeof(filtered) === "undefined") {
|
||||
const canvas = document.createElement("canvas") as any;
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
ctx.drawImage(img, 0, 0);
|
||||
const imgData = ctx.getImageData(0, 0, img.width, img.height);
|
||||
const data = imgData.data;
|
||||
filterFn(data, param);
|
||||
ctx.putImageData(imgData, 0, 0);
|
||||
canvas.complete = true;
|
||||
stendhal.data.sprites.images[filteredName] = filtered = canvas as SpriteImage;
|
||||
}
|
||||
|
||||
return filtered;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/** Image filters */
|
||||
filter: {[key: string]: Function} = {
|
||||
// Helper functions
|
||||
/**
|
||||
* @param {Number} rgb
|
||||
* @return {Array<Number>}
|
||||
*/
|
||||
splitrgb: function(rgb: number): number[] {
|
||||
rgb &= 0xffffff;
|
||||
var b = rgb & 0xff;
|
||||
rgb >>>= 8;
|
||||
var g = rgb & 0xff;
|
||||
rgb >>>= 8;
|
||||
return [rgb, g, b];
|
||||
},
|
||||
|
||||
mergergb: function(rgbArray: number[]): number {
|
||||
const r = rgbArray[0] << 16;
|
||||
const g = rgbArray[1] << 8;
|
||||
return 0xffffff & (r | g | rgbArray[2]);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array<Number>} rgb
|
||||
* @return {Array<Number>}
|
||||
*/
|
||||
rgb2hsl: function(rgb: number[]): number[] {
|
||||
var r = rgb[0] / 255;
|
||||
var g = rgb[1] / 255;
|
||||
var b = rgb[2] / 255;
|
||||
|
||||
var max, min, maxVar;
|
||||
// Find the max and minimum colors, and remember which one it was
|
||||
if (r > g) {
|
||||
max = r;
|
||||
min = g;
|
||||
maxVar = 0;
|
||||
} else {
|
||||
max = g;
|
||||
min = r;
|
||||
maxVar = 1;
|
||||
}
|
||||
if (b > max) {
|
||||
max = b;
|
||||
maxVar = 2;
|
||||
} else if (b < min) {
|
||||
min = b;
|
||||
}
|
||||
|
||||
// lightness
|
||||
var l = (max + min) / 2;
|
||||
var s, h;
|
||||
|
||||
// saturation
|
||||
var diff = max - min;
|
||||
if (diff < 0.000001) {
|
||||
s = 0;
|
||||
// hue not really defined, but set it to something reasonable
|
||||
h = 0;
|
||||
} else {
|
||||
if (l < 0.5) {
|
||||
s = diff / (max + min);
|
||||
} else {
|
||||
s = diff / (2 - max - min);
|
||||
}
|
||||
|
||||
// hue
|
||||
if (maxVar === 0) {
|
||||
h = (g - b) / diff;
|
||||
} else if (maxVar === 1) {
|
||||
h = 2 + (b - r) / diff;
|
||||
} else {
|
||||
h = 4 + (r - g) / diff;
|
||||
}
|
||||
// Normalize to range [0, 1]. It's more useful than the usual 360
|
||||
h /= 6;
|
||||
}
|
||||
|
||||
return [h, s, l];
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array<Number>} hsl
|
||||
* @return {Array<Number>}
|
||||
*/
|
||||
hsl2rgb: function(hsl: number[]): number[] {
|
||||
var r, g, b;
|
||||
var h = hsl[0];
|
||||
var s = hsl[1];
|
||||
var l = hsl[2];
|
||||
|
||||
if (s < 0.0000001) {
|
||||
r = g = b = Math.floor(255 * l);
|
||||
} else {
|
||||
var tmp1, tmp2;
|
||||
if (l < 0.5) {
|
||||
tmp1 = l * (1 + s);
|
||||
} else {
|
||||
tmp1 = l + s - l * s;
|
||||
}
|
||||
tmp2 = 2 * l - tmp1;
|
||||
|
||||
var rf = stendhal.data.sprites.filter.hue2rgb(this.limitHue(h + 1/3), tmp2, tmp1);
|
||||
var gf = stendhal.data.sprites.filter.hue2rgb(this.limitHue(h), tmp2, tmp1);
|
||||
var bf = stendhal.data.sprites.filter.hue2rgb(this.limitHue(h - 1/3), tmp2, tmp1);
|
||||
|
||||
r = Math.floor(255 * rf) & 0xff;
|
||||
g = Math.floor(255 * gf) & 0xff;
|
||||
b = Math.floor(255 * bf) & 0xff;
|
||||
}
|
||||
|
||||
return [r, g, b];
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Number} hue
|
||||
* @param {Number} val1
|
||||
* @param {Number} val2
|
||||
*/
|
||||
hue2rgb: function(hue: number, val1: number, val2: number): number {
|
||||
var res = hue;
|
||||
if (6 * hue < 1) {
|
||||
res = val1 + (val2 - val1) * 6 * hue;
|
||||
} else if (2 * hue < 1) {
|
||||
res = val2;
|
||||
} else if (3 * hue < 2) {
|
||||
res = val1 + (val2 - val1) * (2/3 - hue) * 6;
|
||||
} else {
|
||||
res = val1;
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Number} hue
|
||||
*/
|
||||
limitHue: function(hue: number): number {
|
||||
var res = hue;
|
||||
if (res < 0) {
|
||||
res += 1;
|
||||
} else if (res > 1) {
|
||||
res -= 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a shadow sprite if the style is available.
|
||||
*
|
||||
* @param shadowStyle
|
||||
* Style of shadow to get from cache.
|
||||
* @return
|
||||
* Image sprite or <code>undefined</code>.
|
||||
*/
|
||||
getShadow(shadowStyle: string): any {
|
||||
if (this.knownShadows[shadowStyle]) {
|
||||
const img = new Image();
|
||||
img.src = Paths.sprites + "/shadow/" + shadowStyle + ".png";
|
||||
return img;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is a "safe" image available for sprite.
|
||||
*
|
||||
* @param filename
|
||||
* The sprite image base file path.
|
||||
* @return
|
||||
* <code>true</code> if a known safe image is available.
|
||||
*/
|
||||
hasSafeImage(filename: string): boolean {
|
||||
return this.knownSafeSprites[filename] == true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called at startup to pre-cache certain images.
|
||||
*/
|
||||
startupCache() {
|
||||
// failsafe image
|
||||
this.getFailsafe();
|
||||
// tutorial profile
|
||||
this.get(Paths.sprites + "/npc/floattingladynpc.png");
|
||||
// achievement assets
|
||||
this.get(Paths.gui + "/banner_background.png");
|
||||
for (const cat of ["commerce", "deathmatch", "experience", "fighting", "friend",
|
||||
"interior_zone", "item", "obtain", "outside_zone", "production", "quest",
|
||||
"quest_ados_items", "quest_kill_blordroughs", "quest_kirdneh_item",
|
||||
"quest_mithrilbourgh_enemy_army", "quest_semos_monster", "special",
|
||||
"underground_zone"]) {
|
||||
this.get(Paths.achievements + "/" + cat + ".png");
|
||||
}
|
||||
// weather
|
||||
for (const weather of ["clouds", "fog", "fog_heavy", "rain", "rain_heavy",
|
||||
"rain_light", "snow", "snow_heavy", "snow_light", "wave"]) {
|
||||
this.get(Paths.weather + "/" + weather + ".png");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hidden class to create the singleton instance internally.
|
||||
*/
|
||||
class SpriteStoreInternal extends SpriteStore {
|
||||
|
||||
/** Singleton instance. */
|
||||
private static instance: SpriteStore;
|
||||
|
||||
/**
|
||||
* Retrieves singleton instance.
|
||||
*/
|
||||
static get(): SpriteStore {
|
||||
if (!SpriteStoreInternal.instance) {
|
||||
SpriteStoreInternal.instance = new SpriteStore();
|
||||
}
|
||||
return SpriteStoreInternal.instance;
|
||||
}
|
||||
}
|
||||
|
||||
// SpriteStore singleton instance
|
||||
export const store = SpriteStoreInternal.get();
|
||||
// *** Image filters. Prevent the closure compiler from mangling the names. ***
|
||||
store.filter['trueColor'] = function(data: any, color: number) {
|
||||
var hslColor = stendhal.data.sprites.filter.rgb2hsl(stendhal.data.sprites.filter.splitrgb(color));
|
||||
var end = data.length;
|
||||
for (var i = 0; i < end; i += 4) {
|
||||
var rgb = [data[i], data[i + 1], data[i + 2]];
|
||||
var hsl = stendhal.data.sprites.filter.rgb2hsl(rgb);
|
||||
// Adjust the brightness
|
||||
var adj = hslColor[2] - 0.5; // [-0.5, 0.5]
|
||||
var tmp = hsl[2] - 0.5; // [-0.5, 0.5]
|
||||
// tweaks the middle lights either upward or downward, depending
|
||||
// on if source lightness is high or low
|
||||
var l = hsl[2] - 2.0 * adj * ((tmp * tmp) - 0.25);
|
||||
var resultHsl = [hslColor[0], hslColor[1], l];
|
||||
var resultRgb = stendhal.data.sprites.filter.hsl2rgb(resultHsl);
|
||||
data[i] = resultRgb[0];
|
||||
data[i+1] = resultRgb[1];
|
||||
data[i+2] = resultRgb[2];
|
||||
}
|
||||
};
|
||||
|
|
@ -9,54 +9,56 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var marauroa: any;
|
||||
declare var stendhal: any;
|
||||
import { Deserializer } from "marauroa"
|
||||
import { stendhal } from "../stendhal";
|
||||
|
||||
import { Paths } from "./Paths";
|
||||
|
||||
import { LandscapeRenderingStrategy, CombinedTilesetRenderingStrategy } from "../landscape/LandscapeRenderingStrategy";
|
||||
import { LandscapeRenderingStrategy } from "../landscape/LandscapeRenderingStrategy";
|
||||
import { CombinedTilesetRenderingStrategy } from "../landscape/CombinedTilesetRenderingStrategy";
|
||||
import { IndividualTilesetRenderingStrategy } from "../landscape/IndividualTilesetRenderingStrategy";
|
||||
import { ParallaxBackground } from "../landscape/ParallaxBackground";
|
||||
|
||||
|
||||
export class Map {
|
||||
export class TileMap {
|
||||
|
||||
private currentZoneName = "";
|
||||
public currentZoneName = "";
|
||||
|
||||
private offsetX = 0;
|
||||
private offsetY = 0;
|
||||
private zoneSizeX = -1;
|
||||
private zoneSizeY = -1;
|
||||
private sizeX = 20;
|
||||
private sizeY = 15;
|
||||
public offsetX = 0;
|
||||
public offsetY = 0;
|
||||
public zoneSizeX = -1;
|
||||
public zoneSizeY = -1;
|
||||
public sizeX = 20;
|
||||
public sizeY = 15;
|
||||
|
||||
private tileWidth = 32;
|
||||
private tileHeight = 32;
|
||||
private zoom = 100;
|
||||
public tileWidth = 32;
|
||||
public tileHeight = 32;
|
||||
public zoom = 100;
|
||||
|
||||
private tilesetFilenames: string[] = [];
|
||||
private aImages = -1;
|
||||
private layerNames: any = -1;
|
||||
private layers: any = -1;
|
||||
private firstgids: any = -1;
|
||||
private gidsindex: any = [];
|
||||
public tilesetFilenames: string[] = [];
|
||||
public aImages = -1;
|
||||
public layerNames: any = -1;
|
||||
public layers: any = -1;
|
||||
public firstgids: any = -1;
|
||||
public gidsindex: any = [];
|
||||
|
||||
private drawingError = false;
|
||||
private targetTileWidth = 0;
|
||||
private targetTileHeight = 0;
|
||||
public drawingError = false;
|
||||
public targetTileWidth = 0;
|
||||
public targetTileHeight = 0;
|
||||
|
||||
private readonly layerGroups: any = [
|
||||
public readonly layerGroups = [
|
||||
["0_floor", "1_terrain", "2_object"],
|
||||
["3_roof", "4_roof_add"]
|
||||
];
|
||||
private layerGroupIndexes: any;
|
||||
public readonly blendLayers = ["blend_ground", "blend_roof"]
|
||||
public layerGroupIndexes: any;
|
||||
|
||||
private strategy: LandscapeRenderingStrategy;
|
||||
private protection: any;
|
||||
private collisionData: any;
|
||||
public strategy: LandscapeRenderingStrategy;
|
||||
public protection: any;
|
||||
public collisionData: any;
|
||||
|
||||
// alternatives for known images that may be considered violent or mature
|
||||
private knownSafeTilesets: string[] = [
|
||||
public knownSafeTilesets: string[] = [
|
||||
Paths.tileset + "/item/armor/bloodied_small_axe",
|
||||
Paths.tileset + "/item/blood/floor_stain",
|
||||
Paths.tileset + "/item/blood/floor_stains_2",
|
||||
|
|
@ -64,22 +66,22 @@ export class Map {
|
|||
Paths.tileset + "/item/blood/small_stains"
|
||||
];
|
||||
|
||||
private parallax: ParallaxBackground;
|
||||
private parallaxImage?: string;
|
||||
private ignoredTiles: string[];
|
||||
public parallax: ParallaxBackground;
|
||||
public parallaxImage?: string;
|
||||
public ignoredTiles: string[];
|
||||
|
||||
/** Singleton instance. */
|
||||
private static instance: Map;
|
||||
private static instance: TileMap;
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves singleton instance.
|
||||
*/
|
||||
static get(): Map {
|
||||
if (!Map.instance) {
|
||||
Map.instance = new Map();
|
||||
static get(): TileMap {
|
||||
if (!TileMap.instance) {
|
||||
TileMap.instance = new TileMap();
|
||||
}
|
||||
return Map.instance;
|
||||
return TileMap.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -124,6 +126,8 @@ export class Map {
|
|||
this.decodeMapLayer(content, "2_object");
|
||||
this.decodeMapLayer(content, "3_roof");
|
||||
this.decodeMapLayer(content, "4_roof_add");
|
||||
this.decodeMapLayer(content, "blend_ground");
|
||||
this.decodeMapLayer(content, "blend_roof");
|
||||
this.protection = this.decodeMapLayer(content, "protection");
|
||||
this.collisionData = this.decodeMapLayer(content, "collision");
|
||||
this.layerGroupIndexes = this.mapLayerGroup();
|
||||
|
|
@ -138,7 +142,7 @@ export class Map {
|
|||
|
||||
decodeTileset(content: any, name: string) {
|
||||
var layerData = content[name];
|
||||
var deserializer = marauroa.Deserializer.fromBase64(layerData);
|
||||
var deserializer = Deserializer.fromBase64(layerData);
|
||||
var amount = deserializer.readInt() as number;
|
||||
|
||||
this.tilesetFilenames = [];
|
||||
|
|
@ -192,7 +196,7 @@ export class Map {
|
|||
if (!layerData) {
|
||||
return;
|
||||
}
|
||||
var deserializer = marauroa.Deserializer.fromDeflatedBase64(layerData);
|
||||
var deserializer = Deserializer.fromDeflatedBase64(layerData);
|
||||
deserializer.readString(); // zone name
|
||||
this.zoneSizeX = deserializer.readInt();
|
||||
this.zoneSizeY = deserializer.readInt();
|
||||
|
|
@ -12,9 +12,6 @@
|
|||
import { Paths } from "./Paths";
|
||||
import { JSONLoader } from "../util/JSONLoader";
|
||||
|
||||
declare var stendhal: any;
|
||||
|
||||
|
||||
type AnimationMap = {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
|
@ -70,7 +67,7 @@ export class TileStore {
|
|||
this.landscapeMap = this.loadAnimations(
|
||||
loader.data["landscape"], Paths.tileset + "/");
|
||||
this.weatherMap = this.loadAnimations(
|
||||
loader.data["weather"], stendhal.paths.weather + "/");
|
||||
loader.data["weather"], Paths.weather + "/");
|
||||
};
|
||||
loader.load(Paths.tileset + "/animation.json");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright © 2003-2024 - Faiumoni e. V. *
|
||||
* Copyright © 2003-2026 - Faiumoni e. V. *
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
|
@ -9,10 +9,11 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var marauroa: any;
|
||||
declare var stendhal: any;
|
||||
import { marauroa } from "marauroa"
|
||||
import { stendhal } from "../../stendhal";
|
||||
|
||||
import { LoopedSoundSource } from "../../entity/LoopedSoundSource";
|
||||
import { Zone } from "entity/Zone";
|
||||
|
||||
|
||||
// server doesn't distinguish between music & looped sound effects so we
|
||||
|
|
@ -179,8 +180,8 @@ export class LoopedSoundSourceManager {
|
|||
*/
|
||||
private getZoneEntities(): LoopedSoundSource[] {
|
||||
const ents: LoopedSoundSource[] = [];
|
||||
if (stendhal.zone.entities) {
|
||||
for (const ent of stendhal.zone.entities) {
|
||||
if (Zone.get().entities) {
|
||||
for (const ent of Zone.get().entities) {
|
||||
if (ent instanceof LoopedSoundSource) {
|
||||
ents.push(ent);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import { AbstractEnum } from "../enum/AbstractEnum";
|
|||
/**
|
||||
* Available layers of sound.
|
||||
*
|
||||
* NOTE: string names should match `games.stendhal.common.constants.SoundLayer`
|
||||
* string names should match `games.stendhal.common.constants.SoundLayer`
|
||||
*/
|
||||
export class SoundLayer extends AbstractEnum<string> {
|
||||
|
||||
|
|
@ -29,9 +29,6 @@ export class SoundLayer extends AbstractEnum<string> {
|
|||
static readonly SFX = new SoundLayer("sfx");
|
||||
static readonly GUI = new SoundLayer("gui");
|
||||
|
||||
/** Value is required. */
|
||||
override readonly value!: string;
|
||||
|
||||
|
||||
private constructor(value: string) {
|
||||
super(value);
|
||||
|
|
@ -47,7 +44,7 @@ export class SoundLayer extends AbstractEnum<string> {
|
|||
static names(): string[] {
|
||||
const names: string[] = [];
|
||||
for (const layer of SoundLayer.layers) {
|
||||
names.push(layer.value);
|
||||
names.push(layer.value!);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,16 +9,15 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
declare var marauroa: any;
|
||||
declare var stendhal: any;
|
||||
import { marauroa } from "marauroa"
|
||||
import { stendhal } from "../../stendhal";
|
||||
|
||||
import { SoundFactory } from "./SoundFactory";
|
||||
import { SoundObject } from "./SoundFactory";
|
||||
import { SoundLayer } from "./SoundLayer";
|
||||
|
||||
import { singletons } from "../../SingletonRepo";
|
||||
|
||||
import { ui } from "../../ui/UI";
|
||||
import { Paths } from "../Paths";
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -244,7 +243,7 @@ export class SoundManager {
|
|||
let snd = this.cache[soundName] || this.cacheGlobal[soundName];
|
||||
if (!snd) {
|
||||
// add new sound to cache
|
||||
snd = this.load(soundName, stendhal.paths.sounds + "/" + soundName + ".ogg");
|
||||
snd = this.load(soundName, Paths.sounds + "/" + soundName + ".ogg");
|
||||
}
|
||||
|
||||
if (!this.cache[soundName]) {
|
||||
|
|
@ -406,7 +405,7 @@ export class SoundManager {
|
|||
volume=1.0): SoundObject|undefined {
|
||||
// load into cache so playEffect doesn't look in "data/sounds"
|
||||
if (!this.cache[musicName]) {
|
||||
this.load(musicName, stendhal.paths.music + "/" + musicName + ".ogg");
|
||||
this.load(musicName, Paths.music + "/" + musicName + ".ogg");
|
||||
}
|
||||
return this.playLocalizedLoop(x, y, radius, layer, musicName, volume);
|
||||
}
|
||||
|
|
@ -424,7 +423,7 @@ export class SoundManager {
|
|||
playGlobalizedMusic(musicName: string, volume=1.0): SoundObject|undefined {
|
||||
// load into cache so playEffect doesn't look in "data/sounds"
|
||||
if (!this.cache[musicName]) {
|
||||
this.load(musicName, stendhal.paths.music + "/" + musicName + ".ogg");
|
||||
this.load(musicName, Paths.music + "/" + musicName + ".ogg");
|
||||
}
|
||||
return this.playGlobalizedLoop(musicName, "music", volume);
|
||||
}
|
||||
|
|
@ -796,6 +795,6 @@ export class SoundManager {
|
|||
startupCache() {
|
||||
// login sound
|
||||
this.load("ui/login",
|
||||
stendhal.paths.sounds + "/ui/login.ogg", true);
|
||||
Paths.sounds + "/ui/login.ogg", true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ import { Entity } from "./Entity";
|
|||
import { Direction } from "../util/Direction";
|
||||
import { MathUtil } from "../util/MathUtil";
|
||||
|
||||
declare var stendhal: any;
|
||||
import { stendhal } from "../stendhal";
|
||||
import { TileMap } from "data/TileMap";
|
||||
import { Zone } from "./Zone";
|
||||
|
||||
export class ActiveEntity extends Entity {
|
||||
|
||||
|
|
@ -230,9 +232,10 @@ export class ActiveEntity extends Entity {
|
|||
var startY = Math.floor(this["_y"]);
|
||||
var endX = Math.ceil(this["_x"] + this["width"]);
|
||||
var endY = Math.ceil(this["_y"] + this["height"]);
|
||||
let map = TileMap.get();
|
||||
for (var y = startY; y < endY; y++) {
|
||||
for (var x = startX; x < endX; x++) {
|
||||
if (stendhal.data.map.collision(x, y)) {
|
||||
if (map.collision(x, y)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -258,8 +261,8 @@ export class ActiveEntity extends Entity {
|
|||
var thisEndY = Math.ceil(this["_y"] + this["height"]);
|
||||
|
||||
var i;
|
||||
for (i in stendhal.zone.entities) {
|
||||
var other = stendhal.zone.entities[i];
|
||||
for (i in Zone.get().entities) {
|
||||
var other = Zone.get().entities[i];
|
||||
if (!this.isObstacle(other)) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* (C) Copyright 2003-2024 - Stendhal *
|
||||
* (C) Copyright 2003-2026 - Stendhal *
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
|
@ -9,9 +9,13 @@
|
|||
* *
|
||||
***************************************************************************/
|
||||
|
||||
import { RenderingContext2D } from "util/Types";
|
||||
import { Entity } from "./Entity";
|
||||
import { Paths } from "../data/Paths";
|
||||
|
||||
declare var stendhal: any;
|
||||
import { stendhal } from "../stendhal";
|
||||
import { ImageSprite } from "sprite/image/ImageSprite";
|
||||
import { images } from "sprite/image/ImageManager";
|
||||
|
||||
export class Blood extends Entity {
|
||||
|
||||
|
|
@ -20,27 +24,30 @@ export class Blood extends Entity {
|
|||
|
||||
constructor() {
|
||||
super();
|
||||
this.sprite = {
|
||||
height: 32,
|
||||
width: 32,
|
||||
filename: stendhal.paths.sprites + "/combat/blood_red.png"
|
||||
};
|
||||
this.imageSprite = new ImageSprite(
|
||||
images.load(Paths.sprites + "/combat/blood_red.png"),
|
||||
0, 0, 32, 32
|
||||
);
|
||||
}
|
||||
|
||||
override set(key: string, value: any) {
|
||||
super.set(key, value);
|
||||
if (key === "amount") {
|
||||
this.sprite.offsetY = parseInt(value, 10) * 32;
|
||||
this.imageSprite!.offsetY = parseInt(value, 10) * 32;
|
||||
} else if (key === "class") {
|
||||
this.sprite.filename = stendhal.paths.sprites + "/combat/blood_" + value + ".png";
|
||||
this.imageSprite?.free();
|
||||
this.imageSprite = new ImageSprite(
|
||||
images.load(Paths.sprites + "/combat/blood_" + value + ".png"),
|
||||
0, parseInt(this["amount"], 10) * 32, 32, 32
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
override getCursor(x: number, y: number) {
|
||||
return "url(" + stendhal.paths.sprites + "/cursor/walk.png) 1 3, auto";
|
||||
override getCursor(_x: number, _y: number) {
|
||||
return "url(" + Paths.sprites + "/cursor/walk.png) 1 3, auto";
|
||||
}
|
||||
|
||||
override drawSpriteAt(ctx: CanvasRenderingContext2D, x: number, y: number) {
|
||||
override drawSpriteAt(ctx: RenderingContext2D, x: number, y: number) {
|
||||
if (!stendhal.config.getBoolean("effect.blood")) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,23 +19,13 @@ import { FloatingWindow } from "../ui/toolkit/FloatingWindow";
|
|||
import { ItemInventoryComponent } from "../ui/component/ItemInventoryComponent";
|
||||
|
||||
import { Chat } from "../util/Chat";
|
||||
import { Paths } from "../data/Paths";
|
||||
|
||||
declare var marauroa: any;
|
||||
declare var stendhal: any;
|
||||
|
||||
|
||||
let OPEN_SPRITE = {
|
||||
filename: stendhal.paths.sprites + "/chest.png",
|
||||
height: 32,
|
||||
width: 32,
|
||||
offsetY: 32
|
||||
};
|
||||
|
||||
let CLOSED_SPRITE = {
|
||||
filename: stendhal.paths.sprites + "/chest.png",
|
||||
height: 32,
|
||||
width: 32
|
||||
};
|
||||
import { marauroa } from "marauroa"
|
||||
import { stendhal } from "../stendhal";
|
||||
import { Entity } from "./Entity";
|
||||
import { ImageSprite } from "sprite/image/ImageSprite";
|
||||
import { images } from "sprite/image/ImageManager";
|
||||
|
||||
export class Chest extends PopupInventory {
|
||||
|
||||
|
|
@ -43,16 +33,22 @@ export class Chest extends PopupInventory {
|
|||
override minimapStyle = Color.CHEST;
|
||||
|
||||
override zIndex = 5000;
|
||||
sprite = CLOSED_SPRITE;
|
||||
open = false;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.imageSprite = new ImageSprite(
|
||||
images.load(Paths.sprites + "/chest.png"),
|
||||
0, 0, 32, 32);
|
||||
}
|
||||
|
||||
override set(key: string, value: any) {
|
||||
super.set(key, value);
|
||||
if (key === "open") {
|
||||
this.sprite = OPEN_SPRITE;
|
||||
this.imageSprite!.offsetY = 32;
|
||||
this.open = true;
|
||||
}
|
||||
if (this.isNextTo(marauroa.me)) {
|
||||
if (this.isNextTo(marauroa.me as Entity)) {
|
||||
this.openInventoryWindow();
|
||||
}
|
||||
}
|
||||
|
|
@ -60,7 +56,7 @@ export class Chest extends PopupInventory {
|
|||
override unset(key: string) {
|
||||
super.unset(key);
|
||||
if (key === "open") {
|
||||
this.sprite = CLOSED_SPRITE;
|
||||
this.imageSprite!.offsetY = 0;
|
||||
this.open = false;
|
||||
if (this.inventory && this.inventory.isOpen()) {
|
||||
this.inventory.close();
|
||||
|
|
@ -151,7 +147,7 @@ export class Chest extends PopupInventory {
|
|||
}
|
||||
|
||||
override getCursor(_x: number, _y: number) {
|
||||
return "url(" + stendhal.paths.sprites + "/cursor/bag.png) 1 3, auto";
|
||||
return "url(" + Paths.sprites + "/cursor/bag.png) 1 3, auto";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue