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 |
263 changed files with 8142 additions and 8433 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,15 +10,23 @@ android {
|
|||
applicationId namespace
|
||||
minSdk 21
|
||||
targetSdk 32
|
||||
versionCode 1047005
|
||||
versionName "1.47.5"
|
||||
versionCode 1049005
|
||||
versionName "1.49.5"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
targetSdkVersion 32
|
||||
minSdkVersion 21
|
||||
}
|
||||
|
||||
// F-Droid doesn't allow encrypted DependencyInfoBlock in APK
|
||||
dependenciesInfo {
|
||||
// disables dependency metadata when building APKs
|
||||
includeInApk = false
|
||||
// disables dependency metadata when building Android App Bundles
|
||||
includeInBundle = false
|
||||
}
|
||||
|
||||
// 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,9 +1,3 @@
|
|||
Pizza is a popular meal of choice. With growing demand, Leander is looking to hire reliable workers to transport his hot and delicious cuisine to patrons. Couriers with reputations of on-time deliveries are being recognized for their work ethic.
|
||||
PUT RELEASE ANNOUNCEMENT LINES HERE
|
||||
|
||||
Some adventurers may be distressed and feel that their quest for the title of "Ultimate Collector" is in vain. Well fret no more, as Balduin is offering a ray of hope. Requests to bring him a different item are now accepted afer some time has passed.
|
||||
|
||||
Speaking of weapons, some creatures have once again taken up arms. For example the angel and dark angel have new swords.
|
||||
|
||||
Last but not least: We released an official Android App, which is available in the download section of our website or on F-Droid.
|
||||
|
||||
Please see the complete change log for further details: http://localhost/game/stendhal.html#changes
|
||||
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.47.5</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.47.5",
|
||||
"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.47.5
|
||||
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.47.5"
|
||||
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.47.5
|
||||
version.old = 1.49
|
||||
version = 1.49.5
|
||||
# FIXME: dynamic method to set this property?
|
||||
version.android = 1047005
|
||||
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.47.5 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.
Binary file not shown.
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 15 KiB |
BIN
data/sprites/entity/overlay/necro_flames.xcf.bz2
Normal file
BIN
data/sprites/entity/overlay/necro_flames.xcf.bz2
Normal file
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.47.5";
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -32,15 +32,14 @@ public class IdleBehaviourFactory {
|
|||
} else {
|
||||
behaviour = new WanderIdleBehaviour();
|
||||
}
|
||||
} else if (aiProfiles.containsKey("patrolling") && aiProfiles.containsKey("wander")) {
|
||||
// randomly select between "patrolling" & "wander" for individual entity instance
|
||||
behaviour = Rand.flipCoin() ? new Patroller() : behaviour;
|
||||
if (aiProfiles.containsKey("patrolling")) {
|
||||
// randomly select between "patrolling" & "wander" for individual entity instance
|
||||
behaviour = Rand.flipCoin() ? new Patroller() : behaviour;
|
||||
}
|
||||
} else if (aiProfiles.containsKey("patrolling")) {
|
||||
behaviour = new Patroller();
|
||||
} else if (aiProfiles.containsKey("camouflage")) {
|
||||
behaviour = new CamouflagedIdleBehaviour();
|
||||
} else if (aiProfiles.containsKey("wander")) {
|
||||
behaviour = new WanderIdleBehaviour();
|
||||
}
|
||||
return behaviour;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
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