Initial commit (basic backend stuff)
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# gradle specific directories
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# IDE specific stuff
|
||||||
|
.idea/
|
||||||
39
build.gradle
Normal file
39
build.gradle
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
id 'application'
|
||||||
|
}
|
||||||
|
|
||||||
|
group 'de.siphalor'
|
||||||
|
version '1.0-SNAPSHOT'
|
||||||
|
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile "org.jetbrains:annotations:16.0.2"
|
||||||
|
|
||||||
|
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
testLogging {
|
||||||
|
events "passed", "skipped", "failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
application {
|
||||||
|
mainClassName = "de.siphalor.was.Start"
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
manifest {
|
||||||
|
attributes(
|
||||||
|
'Main-Class': 'de.siphalor.was.Start'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
183
gradlew
vendored
Normal file
183
gradlew
vendored
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2015 the original author or authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=`expr $i + 1`
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
0) set -- ;;
|
||||||
|
1) set -- "$args0" ;;
|
||||||
|
2) set -- "$args0" "$args1" ;;
|
||||||
|
3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=`save "$@"`
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
100
gradlew.bat
vendored
Normal file
100
gradlew.bat
vendored
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
1
packs/test/lang/de_de.lang
Normal file
1
packs/test/lang/de_de.lang
Normal file
@@ -0,0 +1 @@
|
|||||||
|
test.hello-world = Hallo Welt!
|
||||||
2
settings.gradle
Normal file
2
settings.gradle
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
rootProject.name = 'what-a-storage'
|
||||||
|
|
||||||
16
src/main/java/de/siphalor/was/Start.java
Normal file
16
src/main/java/de/siphalor/was/Start.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package de.siphalor.was;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.lang.I18n;
|
||||||
|
|
||||||
|
public class Start {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
WhatAStorage was = WhatAStorage.getInstance();
|
||||||
|
was.reload();
|
||||||
|
was.start();
|
||||||
|
|
||||||
|
I18n.setLang("de_de", was.getContentManager());
|
||||||
|
System.out.println(I18n.get("test.hello-world"));
|
||||||
|
|
||||||
|
was.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
129
src/main/java/de/siphalor/was/WhatAStorage.java
Normal file
129
src/main/java/de/siphalor/was/WhatAStorage.java
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
package de.siphalor.was;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.ContentManager;
|
||||||
|
import de.siphalor.was.content.lang.I18n;
|
||||||
|
import de.siphalor.was.content.pack.FileContentPack;
|
||||||
|
import de.siphalor.was.content.pack.JarContentPack;
|
||||||
|
import de.siphalor.was.content.product.ProductManager;
|
||||||
|
import de.siphalor.was.content.quest.QuestManager;
|
||||||
|
import de.siphalor.was.state.MainMenuState;
|
||||||
|
import de.siphalor.was.state.State;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ComponentAdapter;
|
||||||
|
import java.awt.event.ComponentEvent;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class WhatAStorage {
|
||||||
|
public static final String TITLE = "What a Storage";
|
||||||
|
private static final WhatAStorage INSTANCE = new WhatAStorage();
|
||||||
|
|
||||||
|
public static WhatAStorage getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ContentManager contentManager;
|
||||||
|
private final JarContentPack mainPack;
|
||||||
|
private final ProductManager productManager;
|
||||||
|
private final QuestManager questManager;
|
||||||
|
|
||||||
|
private Frame frame;
|
||||||
|
private State state;
|
||||||
|
|
||||||
|
private long lastTick;
|
||||||
|
private long minTickTime = 1000 / 60;
|
||||||
|
private Canvas canvas;
|
||||||
|
|
||||||
|
private WhatAStorage() {
|
||||||
|
contentManager = new ContentManager();
|
||||||
|
mainPack = new JarContentPack("", "content");
|
||||||
|
contentManager.addPack(mainPack);
|
||||||
|
productManager = new ProductManager();
|
||||||
|
questManager = new QuestManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentManager getContentManager() {
|
||||||
|
return contentManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductManager getProductManager() {
|
||||||
|
return productManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuestManager getQuestManager() {
|
||||||
|
return questManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reload() {
|
||||||
|
contentManager.clear();
|
||||||
|
|
||||||
|
contentManager.addPack(mainPack);
|
||||||
|
|
||||||
|
File[] packDirs = Path.of("packs").toFile().listFiles(File::isDirectory);
|
||||||
|
for (File dir : packDirs) {
|
||||||
|
contentManager.addPack(new FileContentPack(dir.getName(), dir.toPath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
I18n.reload(contentManager);
|
||||||
|
|
||||||
|
productManager.clear();
|
||||||
|
questManager.clear();
|
||||||
|
productManager.reload(contentManager);
|
||||||
|
questManager.reload(contentManager);
|
||||||
|
|
||||||
|
System.out.println("Reloaded game content");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
frame = new Frame(TITLE);
|
||||||
|
frame.setVisible(true);
|
||||||
|
frame.addWindowListener(new WindowAdapter() {
|
||||||
|
@Override
|
||||||
|
public void windowClosing(WindowEvent e) {
|
||||||
|
super.windowClosing(e);
|
||||||
|
frame.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
frame.addComponentListener(new ComponentAdapter() {
|
||||||
|
@Override
|
||||||
|
public void componentResized(ComponentEvent e) {
|
||||||
|
super.componentResized(e);
|
||||||
|
canvas.setSize(frame.getSize());
|
||||||
|
state.onResize(frame.getWidth(), frame.getHeight());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
canvas = new Canvas();
|
||||||
|
canvas.setSize(frame.getSize());
|
||||||
|
frame.add(canvas);
|
||||||
|
|
||||||
|
changeState(new MainMenuState(canvas.getWidth(), canvas.getHeight()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
long time, timeDelta = minTickTime;
|
||||||
|
lastTick = System.currentTimeMillis();
|
||||||
|
|
||||||
|
while (frame.isVisible()) {
|
||||||
|
time = System.currentTimeMillis();
|
||||||
|
timeDelta = time - lastTick - minTickTime;
|
||||||
|
|
||||||
|
if (timeDelta >= 0) {
|
||||||
|
state.tick();
|
||||||
|
state.render(canvas.getGraphics());
|
||||||
|
lastTick = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changeState(State newState) {
|
||||||
|
if (state != null) {
|
||||||
|
state.leave();
|
||||||
|
}
|
||||||
|
state = newState;
|
||||||
|
state.enter();
|
||||||
|
state.onResize(canvas.getWidth(), canvas.getHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/main/java/de/siphalor/was/assets/AssetsManager.java
Normal file
41
src/main/java/de/siphalor/was/assets/AssetsManager.java
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package de.siphalor.was.assets;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class AssetsManager {
|
||||||
|
private static final Map<String, Image> imageCache = new HashMap<>();
|
||||||
|
|
||||||
|
public static final Image MISSINGNO = getImage("assets/missingno.png");
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static InputStream getResource(@NotNull String path) {
|
||||||
|
return Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Image getImage(@NotNull String path) {
|
||||||
|
Image image = imageCache.get(path);
|
||||||
|
if (image == null) {
|
||||||
|
InputStream inputStream = getResource(path);
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
image = ImageIO.read(inputStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
image = MISSINGNO;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
image = MISSINGNO;
|
||||||
|
}
|
||||||
|
imageCache.put(path, image);
|
||||||
|
}
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
}
|
||||||
77
src/main/java/de/siphalor/was/content/ContentManager.java
Normal file
77
src/main/java/de/siphalor/was/content/ContentManager.java
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package de.siphalor.was.content;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.pack.ContentPack;
|
||||||
|
import de.siphalor.was.content.resource.Resource;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class ContentManager {
|
||||||
|
private final List<ContentPack> packs = new LinkedList<>();
|
||||||
|
|
||||||
|
public ContentManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
packs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPack(ContentPack pack) {
|
||||||
|
packs.add(pack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ContentPack> getPacks() {
|
||||||
|
return packs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Stream<Resource> getResources(@NotNull String location, @NotNull String type) {
|
||||||
|
return packs.stream().flatMap(pack -> pack.getResources(location, type)).distinct();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Optional<Resource> getResource(@NotNull String location) {
|
||||||
|
Resource resource;
|
||||||
|
for (ContentPack pack : packs) {
|
||||||
|
resource = pack.getResource(location);
|
||||||
|
if (resource != null) {
|
||||||
|
return Optional.of(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Stream<Resource> getAllOfResource(@NotNull String location) {
|
||||||
|
return packs.stream().flatMap(pack -> Stream.ofNullable(pack.getResource(location)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Optional<Image> getImage(@NotNull String location) {
|
||||||
|
return getResource(location).map(resource -> {
|
||||||
|
InputStream inputStream = resource.getInputStream();
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
return ImageIO.read(inputStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/main/java/de/siphalor/was/content/lang/I18n.java
Normal file
50
src/main/java/de/siphalor/was/content/lang/I18n.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package de.siphalor.was.content.lang;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.ContentManager;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class I18n {
|
||||||
|
public static final String DEFAULT = "en_us";
|
||||||
|
private static final Lang DEFAULT_LANG = new Lang(DEFAULT);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static Lang lang;
|
||||||
|
|
||||||
|
public static void setLang(@NotNull String code, @NotNull ContentManager contentManager) {
|
||||||
|
if (lang == null || !lang.getCode().equals(code)) {
|
||||||
|
lang = new Lang(code);
|
||||||
|
lang.load(contentManager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reload(@NotNull ContentManager contentManager) {
|
||||||
|
DEFAULT_LANG.load(contentManager);
|
||||||
|
if (lang != null) {
|
||||||
|
lang.load(contentManager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static String get(@NotNull String key) {
|
||||||
|
String val;
|
||||||
|
if (lang != null) {
|
||||||
|
val = lang.get(key);
|
||||||
|
if (val == null) {
|
||||||
|
val = DEFAULT_LANG.get(key);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val = DEFAULT_LANG.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val == null) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static String format(@NotNull String key, @Nullable Object... args) {
|
||||||
|
return String.format(get(key), args);
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/main/java/de/siphalor/was/content/lang/Lang.java
Normal file
53
src/main/java/de/siphalor/was/content/lang/Lang.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package de.siphalor.was.content.lang;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.ContentManager;
|
||||||
|
import de.siphalor.was.content.resource.Resource;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
public class Lang {
|
||||||
|
private final String code;
|
||||||
|
private final Properties properties = new Properties();
|
||||||
|
|
||||||
|
public Lang(@NotNull String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(@NotNull ContentManager contentManager) {
|
||||||
|
properties.clear();
|
||||||
|
contentManager.getAllOfResource("lang/" + code + ".lang").forEachOrdered(resource -> {
|
||||||
|
InputStream inputStream = resource.getInputStream();
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
properties.load(inputStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (properties.isEmpty()) {
|
||||||
|
System.out.println("Failed to load lang file for " + code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String get(@NotNull String key) {
|
||||||
|
return (String) properties.get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/main/java/de/siphalor/was/content/pack/ContentPack.java
Normal file
16
src/main/java/de/siphalor/was/content/pack/ContentPack.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package de.siphalor.was.content.pack;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.resource.Resource;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public interface ContentPack {
|
||||||
|
@NotNull
|
||||||
|
Stream<Resource> getResources(@NotNull String location, @NotNull String type);
|
||||||
|
@Nullable
|
||||||
|
Resource getResource(@NotNull String location);
|
||||||
|
@NotNull
|
||||||
|
String getId();
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package de.siphalor.was.content.pack;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.resource.FileResource;
|
||||||
|
import de.siphalor.was.content.resource.Resource;
|
||||||
|
import de.siphalor.was.util.Util;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class FileContentPack implements ContentPack {
|
||||||
|
private final String id;
|
||||||
|
private final Path base;
|
||||||
|
|
||||||
|
public FileContentPack(@NotNull String id, @NotNull Path base) {
|
||||||
|
this.id = id;
|
||||||
|
this.base = base;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Stream<Resource> getResources(@NotNull String location, @NotNull String type) {
|
||||||
|
final String extension = "." + type;
|
||||||
|
Path dir = base.resolve(Path.of(location));
|
||||||
|
if (dir.toFile().isDirectory()) {
|
||||||
|
try {
|
||||||
|
return Files.find(dir, Integer.MAX_VALUE, (fPath, fileAttributes) -> fileAttributes.isRegularFile() && fPath.endsWith(extension)).map(path ->
|
||||||
|
new FileResource(Util.pathToId(id, path.relativize(base).toString()), path.toFile())
|
||||||
|
);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resource getResource(@NotNull String location) {
|
||||||
|
File file = base.resolve(Path.of(location)).toFile();
|
||||||
|
if (file.isFile()) {
|
||||||
|
return new FileResource(Util.pathToId(id, location), file);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
109
src/main/java/de/siphalor/was/content/pack/JarContentPack.java
Normal file
109
src/main/java/de/siphalor/was/content/pack/JarContentPack.java
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package de.siphalor.was.content.pack;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.resource.FileResource;
|
||||||
|
import de.siphalor.was.content.resource.CallbackResource;
|
||||||
|
import de.siphalor.was.content.resource.Resource;
|
||||||
|
import de.siphalor.was.util.Util;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class JarContentPack implements ContentPack {
|
||||||
|
private final String id;
|
||||||
|
private final String baseLocation;
|
||||||
|
private final ClassLoader classLoader;
|
||||||
|
|
||||||
|
public JarContentPack(String id) {
|
||||||
|
this(id, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public JarContentPack(String id, String baseLocation) {
|
||||||
|
this(id, baseLocation, Thread.currentThread().getContextClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public JarContentPack(String id, String baseLocation, ClassLoader classLoader) {
|
||||||
|
this.id = id;
|
||||||
|
this.baseLocation = baseLocation;
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inspired from this: https://stackoverflow.com/a/48190582/7582022
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public Stream<Resource> getResources(@NotNull String location, @NotNull String type) {
|
||||||
|
final String extension = "." + type;
|
||||||
|
try {
|
||||||
|
URL url = classLoader.getResource(baseLocation + "/" + location);
|
||||||
|
|
||||||
|
if (url != null) {
|
||||||
|
if ("file".equals(url.getProtocol())) {
|
||||||
|
Path basePath = Path.of(url.toURI());
|
||||||
|
return Files.find(basePath, Integer.MAX_VALUE, (path, attributes) -> attributes.isRegularFile() && path.getFileName().getName(0).toString().endsWith(extension)).map(path ->
|
||||||
|
new FileResource(Util.pathToId(id, basePath.relativize(path).toString()), path.toFile())
|
||||||
|
);
|
||||||
|
} else if ("jar".equals(url.getProtocol())) {
|
||||||
|
// The url path section begins with "file:" and ends with an exclamation mark and the path inside the jar
|
||||||
|
// URLs also encode symbols with dollar sign so we need to decode them
|
||||||
|
String urlPath = url.getPath();
|
||||||
|
String jarPath = URLDecoder.decode(urlPath.substring(5, urlPath.indexOf('!')), StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
JarFile jarFile = new JarFile(jarPath);
|
||||||
|
Enumeration<JarEntry> entries = jarFile.entries();
|
||||||
|
|
||||||
|
final String absLocation = baseLocation + "/" + location + "/";
|
||||||
|
final int absLength = absLocation.length();
|
||||||
|
|
||||||
|
ArrayList<Resource> resources = new ArrayList<>();
|
||||||
|
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
JarEntry entry = entries.nextElement();
|
||||||
|
String name = entry.getName();
|
||||||
|
if (name.startsWith(absLocation) && name.length() != absLocation.length()) {
|
||||||
|
resources.add(new CallbackResource(Util.pathToId(id, name.substring(absLength)), () -> classLoader.getResourceAsStream(name)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resources.stream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException | URISyntaxException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Resource getResource(@NotNull String location) {
|
||||||
|
try {
|
||||||
|
URL url = classLoader.getResource(baseLocation + "/" + location);
|
||||||
|
if (url != null) {
|
||||||
|
if ("file".equals(url.getProtocol())) {
|
||||||
|
return new FileResource(Util.pathToId(id, location), new File(url.toURI()));
|
||||||
|
} else if ("jar".equals(url.getProtocol())) {
|
||||||
|
return new CallbackResource(Util.pathToId(id, location), () -> classLoader.getResourceAsStream(baseLocation + "/" + location));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/main/java/de/siphalor/was/content/product/Product.java
Normal file
14
src/main/java/de/siphalor/was/content/product/Product.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package de.siphalor.was.content.product;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public interface Product {
|
||||||
|
@NotNull
|
||||||
|
String getPropertySpecifier();
|
||||||
|
|
||||||
|
int getDepth();
|
||||||
|
boolean testY(int y);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
ProductType<?> getType();
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package de.siphalor.was.content.product;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.ContentManager;
|
||||||
|
import de.siphalor.was.util.ResourceManager;
|
||||||
|
import de.siphalor.was.content.product.dynamic.DynamicProductType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ProductManager implements ResourceManager<ProductType<?>> {
|
||||||
|
private final Map<String, ProductType<?>> productTypes = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
productTypes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload(@NotNull ContentManager contentManager) {
|
||||||
|
contentManager.getResources("products", "properties").forEach(resource -> {
|
||||||
|
InputStream inputStream = resource.getInputStream();
|
||||||
|
if (inputStream != null) {
|
||||||
|
productTypes.put(resource.getId(), DynamicProductType.from(inputStream));
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProductType<?> get(String id) {
|
||||||
|
return productTypes.get(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package de.siphalor.was.content.product;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public abstract class ProductType<T extends Product> {
|
||||||
|
|
||||||
|
public ProductType() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public abstract T getProduct(String[] values);
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package de.siphalor.was.content.product.dynamic;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.product.Product;
|
||||||
|
import de.siphalor.was.content.product.ProductType;
|
||||||
|
import de.siphalor.was.util.Util;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.function.IntPredicate;
|
||||||
|
|
||||||
|
public class DynamicProduct implements Product {
|
||||||
|
private ProductType<?> type;
|
||||||
|
private final String[] properties;
|
||||||
|
private int depth = 1;
|
||||||
|
@NotNull
|
||||||
|
private IntPredicate yPredicate = Util.dummyIntPredicate();
|
||||||
|
|
||||||
|
public DynamicProduct(String[] properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public String getPropertySpecifier() {
|
||||||
|
return String.join("_", properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDepth(int depth) {
|
||||||
|
this.depth = depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDepth() {
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean testY(int y) {
|
||||||
|
return yPredicate.test(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function exists to resolve the circular references of ProductType <-> Product on creation
|
||||||
|
void setType(ProductType<?> type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public ProductType<?> getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYPredicate(@NotNull IntPredicate yPredicate) {
|
||||||
|
this.yPredicate = yPredicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "DynamicProduct{" +
|
||||||
|
"properties=" + Arrays.toString(properties) +
|
||||||
|
", depth=" + depth +
|
||||||
|
", yPredicate=" + yPredicate +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
package de.siphalor.was.content.product.dynamic;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.product.ProductType;
|
||||||
|
import de.siphalor.was.util.Util;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.IntPredicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class DynamicProductType extends ProductType<DynamicProduct> {
|
||||||
|
private final Map<String, DynamicProduct> variations;
|
||||||
|
private final String[] properties;
|
||||||
|
|
||||||
|
public DynamicProductType(List<DynamicProduct> variations, String[] properties) {
|
||||||
|
this.variations = new HashMap<>();
|
||||||
|
variations.forEach(p -> {
|
||||||
|
p.setType(this);
|
||||||
|
this.variations.put(p.getPropertySpecifier(), p);
|
||||||
|
});
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static DynamicProductType from(@NotNull InputStream inputStream) {
|
||||||
|
Properties propertiesFile = new Properties();
|
||||||
|
|
||||||
|
try {
|
||||||
|
propertiesFile.load(inputStream);
|
||||||
|
|
||||||
|
String[] propNames = ((String) propertiesFile.get("properties")).split(",");
|
||||||
|
|
||||||
|
if (propNames.length > 0) {
|
||||||
|
// propNameList = propNames without blank elements & all elements trimmed
|
||||||
|
List<String> propNameList = new ArrayList<>(propNames.length);
|
||||||
|
List<List<ProductPrototype>> properties = new ArrayList<>(propNames.length);
|
||||||
|
for (String propName : propNames) {
|
||||||
|
propName = propName.trim();
|
||||||
|
if (propName.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
propNameList.add(propName);
|
||||||
|
if (propertiesFile.containsKey(propName + ".variants")) {
|
||||||
|
String[] variants = ((String) propertiesFile.get(propName + ".variants")).split(",");
|
||||||
|
List<ProductPrototype> propertyVariants = new ArrayList<>(variants.length);
|
||||||
|
for (String variant : variants) {
|
||||||
|
variant = variant.trim();
|
||||||
|
propertyVariants.add(makePrototype(propertiesFile, propName, variant));
|
||||||
|
}
|
||||||
|
properties.add(propertyVariants);
|
||||||
|
} else {
|
||||||
|
// if there are no variants assume true/false flag
|
||||||
|
properties.add(List.of(
|
||||||
|
makePrototype(propertiesFile, propName, "true"),
|
||||||
|
makePrototype(propertiesFile, propName, "false")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ProductPrototype> prototypes = properties.stream().reduce((pts1, pts2) -> {
|
||||||
|
return pts1.stream().flatMap(pt -> {
|
||||||
|
return pts2.stream().map(pt::combine);
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}).get();
|
||||||
|
|
||||||
|
List<DynamicProduct> products = prototypes.stream().map(pt -> {
|
||||||
|
DynamicProduct product = new DynamicProduct(pt.value.split(";"));
|
||||||
|
pt.apply(product);
|
||||||
|
return product;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
return new DynamicProductType(products, propNameList.toArray(String[]::new));
|
||||||
|
}
|
||||||
|
} catch (IOException | NullPointerException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DynamicProductType(List.of(new DynamicProduct(Util.emptyArray())), Util.emptyArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ProductPrototype makePrototype(Properties propertiesFile, String property, String variant) {
|
||||||
|
ProductPrototype prototype = new ProductPrototype(variant);
|
||||||
|
String base = property + "." + variant + ".";
|
||||||
|
if (propertiesFile.containsKey(base + "depth")) {
|
||||||
|
prototype.depth = Integer.parseInt((String) propertiesFile.get(base + "depth"));
|
||||||
|
}
|
||||||
|
if (propertiesFile.containsKey(base + "y")) {
|
||||||
|
String val = (String) propertiesFile.get(base + "y");
|
||||||
|
switch (val.charAt(0)) {
|
||||||
|
case '>': {
|
||||||
|
int i = Integer.parseInt(val.substring(1));
|
||||||
|
prototype.yPredicate = value -> value > i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '<': {
|
||||||
|
int i = Integer.parseInt(val.substring(1));
|
||||||
|
prototype.yPredicate = value -> value < i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
int i = Integer.parseInt(val);
|
||||||
|
prototype.yPredicate = value -> value == i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prototype;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DynamicProduct getProduct(String[] values) {
|
||||||
|
return variations.get(String.join("_", values));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ProductPrototype {
|
||||||
|
String value;
|
||||||
|
|
||||||
|
Integer depth = null;
|
||||||
|
IntPredicate yPredicate = null;
|
||||||
|
|
||||||
|
public ProductPrototype(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void apply(DynamicProduct product) {
|
||||||
|
if (depth != null)
|
||||||
|
product.setDepth(depth);
|
||||||
|
if (yPredicate != null)
|
||||||
|
product.setYPredicate(yPredicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductPrototype combine(ProductPrototype prototype) {
|
||||||
|
ProductPrototype result = new ProductPrototype(value + ";" + prototype.value);
|
||||||
|
if (prototype.depth != null)
|
||||||
|
result.depth = prototype.depth;
|
||||||
|
else
|
||||||
|
result.depth = depth;
|
||||||
|
if (result.yPredicate != null)
|
||||||
|
result.yPredicate = prototype.yPredicate;
|
||||||
|
else
|
||||||
|
result.yPredicate = yPredicate;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "DynamicProductType{" +
|
||||||
|
"properties=" + String.join(" & ", properties) +
|
||||||
|
", variations=\n" + variations.values().stream().map(Object::toString).collect(Collectors.joining(System.lineSeparator())) +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/main/java/de/siphalor/was/content/quest/Quest.java
Normal file
36
src/main/java/de/siphalor/was/content/quest/Quest.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package de.siphalor.was.content.quest;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.product.Product;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class Quest {
|
||||||
|
@NotNull
|
||||||
|
private final Type type;
|
||||||
|
private final int reward;
|
||||||
|
@NotNull
|
||||||
|
private final Product product;
|
||||||
|
|
||||||
|
public Quest(@NotNull Type type, int reward, @NotNull Product product) {
|
||||||
|
this.product = product;
|
||||||
|
this.reward = reward;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Product getProduct() {
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getReward() {
|
||||||
|
return reward;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
IN, OUT
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package de.siphalor.was.content.quest;
|
||||||
|
|
||||||
|
public interface QuestGenerator {
|
||||||
|
/**
|
||||||
|
* Restarts this generator
|
||||||
|
*/
|
||||||
|
void restart();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next {@link Quest} but doesn't advance
|
||||||
|
* @return the next {@link Quest}
|
||||||
|
* @see QuestGenerator#next()
|
||||||
|
*/
|
||||||
|
Quest peek();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next {@link Quest} and advances
|
||||||
|
* @return the next {@link Quest}
|
||||||
|
* @see QuestGenerator#peek()
|
||||||
|
*/
|
||||||
|
Quest next();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether another {@link Quest} can be generated
|
||||||
|
* @return whether the generator is at its end
|
||||||
|
* @see QuestGenerator#restart()
|
||||||
|
*/
|
||||||
|
boolean hasNext();
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package de.siphalor.was.content.quest;
|
||||||
|
|
||||||
|
import de.siphalor.was.WhatAStorage;
|
||||||
|
import de.siphalor.was.content.ContentManager;
|
||||||
|
import de.siphalor.was.util.ResourceManager;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class QuestManager implements ResourceManager<QuestGenerator> {
|
||||||
|
private final Map<String, QuestGenerator> questGenerators = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
questGenerators.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reload(@NotNull ContentManager contentManager) {
|
||||||
|
contentManager.getResources("quests", "csv").forEach(resource -> {
|
||||||
|
InputStream inputStream = resource.getInputStream();
|
||||||
|
if (inputStream != null) {
|
||||||
|
questGenerators.put(resource.getId(), StaticQuestGenerator.fromCsv(inputStream, WhatAStorage.getInstance().getProductManager()));
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QuestGenerator get(String id) {
|
||||||
|
return questGenerators.get(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package de.siphalor.was.content.quest;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.product.Product;
|
||||||
|
import de.siphalor.was.content.product.ProductManager;
|
||||||
|
import de.siphalor.was.content.product.ProductType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class StaticQuestGenerator implements QuestGenerator {
|
||||||
|
@NotNull
|
||||||
|
private final List<Quest> quests;
|
||||||
|
private int index = 0;
|
||||||
|
|
||||||
|
public StaticQuestGenerator(@NotNull List<Quest> quests) {
|
||||||
|
this.quests = quests;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static StaticQuestGenerator fromCsv(@NotNull InputStream inputStream, @NotNull ProductManager productManager) {
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
|
String line;
|
||||||
|
|
||||||
|
List<Quest> quests = new ArrayList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
try {
|
||||||
|
String[] parts = line.split(",");
|
||||||
|
if (parts.length >= 3) {
|
||||||
|
Quest.Type type = Quest.Type.valueOf(parts[0].toUpperCase(Locale.ENGLISH));
|
||||||
|
ProductType<?> productType = productManager.get(parts[1]);
|
||||||
|
if (productType != null) {
|
||||||
|
int reward = Integer.parseInt(parts[2]);
|
||||||
|
|
||||||
|
Product product = productType.getProduct(Arrays.copyOfRange(parts, 3, parts.length));
|
||||||
|
|
||||||
|
if (product != null) {
|
||||||
|
quests.add(new Quest(type, reward, product));
|
||||||
|
} else {
|
||||||
|
System.out.println("Invalid product in quest: " + line);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("Invalid product in quest: " + parts[2]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.out.println("Invalid line in quests file: " + line);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Failed to load quest in csv file in line: " + line);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new StaticQuestGenerator(quests);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("Failed to load quest csv file:");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restart() {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Quest peek() {
|
||||||
|
return quests.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Quest next() {
|
||||||
|
return quests.get(index++);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return index < quests.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package de.siphalor.was.content.resource;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class CallbackResource extends Resource {
|
||||||
|
Supplier<InputStream> supplier;
|
||||||
|
|
||||||
|
public CallbackResource(String id, Supplier<InputStream> supplier) {
|
||||||
|
super(id);
|
||||||
|
this.supplier = supplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable InputStream getInputStream() {
|
||||||
|
return supplier.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package de.siphalor.was.content.resource;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class FileResource extends Resource {
|
||||||
|
private final File file;
|
||||||
|
|
||||||
|
public FileResource(String id, File file) {
|
||||||
|
super(id);
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() {
|
||||||
|
try {
|
||||||
|
return new FileInputStream(file);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/main/java/de/siphalor/was/content/resource/Resource.java
Normal file
20
src/main/java/de/siphalor/was/content/resource/Resource.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package de.siphalor.was.content.resource;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public abstract class Resource {
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
protected Resource(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public abstract InputStream getInputStream();
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/main/java/de/siphalor/was/game/Storage.java
Normal file
5
src/main/java/de/siphalor/was/game/Storage.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package de.siphalor.was.game;
|
||||||
|
|
||||||
|
public class Storage {
|
||||||
|
|
||||||
|
}
|
||||||
35
src/main/java/de/siphalor/was/state/GameState.java
Normal file
35
src/main/java/de/siphalor/was/state/GameState.java
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package de.siphalor.was.state;
|
||||||
|
|
||||||
|
import de.siphalor.was.assets.AssetsManager;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
public class GameState extends State {
|
||||||
|
private BufferedImage main;
|
||||||
|
|
||||||
|
public GameState(int width, int height) {
|
||||||
|
super(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(Graphics graphics) {
|
||||||
|
graphics.drawImage(main, 0, 0, getWidth(), getHeight(), (img, infoflags, x, y, width, height) -> false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResize(int width, int height) {
|
||||||
|
super.onResize(width, height);
|
||||||
|
main = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||||
|
redrawBg(main.getGraphics());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void redrawBg(Graphics graphics) {
|
||||||
|
graphics.drawImage(AssetsManager.getImage("assets/menu/bg.png"), 0, 0, getWidth(), getHeight(), (img, infoflags, x, y, width, height) -> false);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/main/java/de/siphalor/was/state/MainMenuState.java
Normal file
31
src/main/java/de/siphalor/was/state/MainMenuState.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package de.siphalor.was.state;
|
||||||
|
|
||||||
|
import de.siphalor.was.assets.AssetsManager;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class MainMenuState extends State {
|
||||||
|
private boolean bgDirty = true;
|
||||||
|
|
||||||
|
public MainMenuState(int width, int height) {
|
||||||
|
super(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(Graphics graphics) {
|
||||||
|
if (bgDirty) {
|
||||||
|
graphics.drawImage(AssetsManager.getImage("assets/bg.png"), 0, 0, getWidth() - 1, getHeight() - 1, (img, infoflags, x, y, width, height) -> false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResize(int width, int height) {
|
||||||
|
super.onResize(width, height);
|
||||||
|
bgDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/main/java/de/siphalor/was/state/State.java
Normal file
37
src/main/java/de/siphalor/was/state/State.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package de.siphalor.was.state;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public abstract class State {
|
||||||
|
private int width, height;
|
||||||
|
|
||||||
|
public State(int width, int height) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
onResize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enter() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void leave() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void tick();
|
||||||
|
public abstract void render(Graphics graphics);
|
||||||
|
|
||||||
|
public void onResize(int width, int height) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/main/java/de/siphalor/was/util/Pair.java
Normal file
39
src/main/java/de/siphalor/was/util/Pair.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package de.siphalor.was.util;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class Pair<A, B> {
|
||||||
|
private final A first;
|
||||||
|
private final B second;
|
||||||
|
|
||||||
|
public static <A, B> Pair<A, B> of(A first, B second) {
|
||||||
|
return new Pair<>(first, second);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair(A first, B second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
public A getFirst() {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
public B getSecond() {
|
||||||
|
return second;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Pair<?, ?> pair = (Pair<?, ?>) o;
|
||||||
|
return Objects.equals(first, pair.first) &&
|
||||||
|
Objects.equals(second, pair.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(first, second);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/main/java/de/siphalor/was/util/ResourceManager.java
Normal file
11
src/main/java/de/siphalor/was/util/ResourceManager.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package de.siphalor.was.util;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.ContentManager;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public interface ResourceManager<T> {
|
||||||
|
void clear();
|
||||||
|
void reload(@NotNull ContentManager contentManager);
|
||||||
|
|
||||||
|
T get(String id);
|
||||||
|
}
|
||||||
37
src/main/java/de/siphalor/was/util/Util.java
Normal file
37
src/main/java/de/siphalor/was/util/Util.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package de.siphalor.was.util;
|
||||||
|
|
||||||
|
import java.util.function.IntPredicate;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
public class Util {
|
||||||
|
private static final Predicate<?> DUMMY_PREDICATE = o -> true;
|
||||||
|
private static final IntPredicate DUMMY_INT_PREDICATE = value -> true;
|
||||||
|
|
||||||
|
private static final Object[] EMPTY_ARRAY = new Object[0];
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> Predicate<T> dummyPredicate() {
|
||||||
|
return (Predicate<T>) DUMMY_PREDICATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntPredicate dummyIntPredicate() {
|
||||||
|
return DUMMY_INT_PREDICATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> T[] emptyArray() {
|
||||||
|
return (T[]) EMPTY_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String pathToId(String packId, String path) {
|
||||||
|
int dot = path.lastIndexOf('.');
|
||||||
|
if (dot >= 0) {
|
||||||
|
path = path.substring(0, dot);
|
||||||
|
}
|
||||||
|
path = path.replace('/', '.').replace('\\', '.');
|
||||||
|
if (packId.isEmpty()) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
return packId + "." + path;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
src/main/resources/assets/missingno.png
Normal file
BIN
src/main/resources/assets/missingno.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 342 B |
34
src/main/resources/content/lang/en_us.lang
Normal file
34
src/main/resources/content/lang/en_us.lang
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
test.hello-world = Hello World!
|
||||||
|
|
||||||
|
quests.normal = Normal
|
||||||
|
|
||||||
|
products.paper = Paper
|
||||||
|
products.paper.color = Color
|
||||||
|
products.paper.color.green = Green
|
||||||
|
products.paper.color.blue = Blue
|
||||||
|
products.paper.color.white = White
|
||||||
|
# These paper formats are not equivalent but at least kind of similar in the amount they're used
|
||||||
|
products.paper.format = Format
|
||||||
|
products.paper.format.a3 = Ledger
|
||||||
|
products.paper.format.a4 = Legal
|
||||||
|
products.paper.format.a5 = Letter
|
||||||
|
|
||||||
|
products.wood = Wood
|
||||||
|
products.wood.type = Type
|
||||||
|
products.wood.type.beech = Beech
|
||||||
|
products.wood.type.oak = Oak
|
||||||
|
products.wood.type.pine = Pine
|
||||||
|
products.wood.form = Form
|
||||||
|
products.wood.form.pieces = Pieces
|
||||||
|
products.wood.form.boards = Boards
|
||||||
|
products.wood.form.beams = Beams
|
||||||
|
|
||||||
|
products.stone = Stone
|
||||||
|
products.stone.type = Type
|
||||||
|
products.stone.type.granite = Granite
|
||||||
|
products.stone.type.marble = Marble
|
||||||
|
products.stone.type.sandstone = Sandstone
|
||||||
|
products.stone.weight = Weight
|
||||||
|
products.stone.weight.light = Light
|
||||||
|
products.stone.weight.medium = Medium
|
||||||
|
products.stone.weight.heavy = Heavy
|
||||||
3
src/main/resources/content/products/paper.properties
Normal file
3
src/main/resources/content/products/paper.properties
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
properties = color, format
|
||||||
|
color.variants =white, green, blue
|
||||||
|
format.variants = a3, a4, a5
|
||||||
4
src/main/resources/content/products/stone.properties
Normal file
4
src/main/resources/content/products/stone.properties
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
properties = type, weight
|
||||||
|
type.variants = marble, granite, sandstone
|
||||||
|
weight.variants = light, medium, heavy
|
||||||
|
weight.heavy.y = 1
|
||||||
4
src/main/resources/content/products/wood.properties
Normal file
4
src/main/resources/content/products/wood.properties
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
properties = type, form
|
||||||
|
type.variants = pine, beech, oak
|
||||||
|
form.variants = boards, pieces, beams
|
||||||
|
form.beams.depth = 3
|
||||||
47
src/main/resources/content/quests/normal.csv
Normal file
47
src/main/resources/content/quests/normal.csv
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
in,paper,200,white,a4
|
||||||
|
in,paper,300,blue,a5
|
||||||
|
in,wood,200,pine,boards
|
||||||
|
in,wood,500,beech,beams
|
||||||
|
in,wood,200,oak,pieces
|
||||||
|
in,paper,200,blue,a5
|
||||||
|
in,paper,200,blue,a5
|
||||||
|
in,stone,400,marble,medium
|
||||||
|
in,stone,500,granite,heavy
|
||||||
|
in,stone,200,sandstone,light
|
||||||
|
out,paper,1000,blue,a5
|
||||||
|
out,wood,1200,oak,pieces
|
||||||
|
out,stone,1000,marble,medium
|
||||||
|
out,paper,1500,white,a5
|
||||||
|
in,wood,400,oak,beams
|
||||||
|
in,wood,600,oak,pieces
|
||||||
|
in,wood,200,beech,pieces
|
||||||
|
in,stone,400,granite,light
|
||||||
|
in,paper,200,blue,a3
|
||||||
|
in,paper,200,blue,a5
|
||||||
|
in,wood,600,oak,pieces
|
||||||
|
in,wood,600,beech,beams
|
||||||
|
in,stone,200,sandstone,heavy
|
||||||
|
in,stone,600,granite,heavy
|
||||||
|
in,wood,400,beech,boards
|
||||||
|
in,wood,200,beech,pieces
|
||||||
|
out,wood,1000,beech,pieces
|
||||||
|
out,paper,1200,blue,a5
|
||||||
|
out,stone,1500,granite,heavy
|
||||||
|
out,wood,1000,beech,beams
|
||||||
|
out,stone,1300,sandstone,heavy
|
||||||
|
in,stone,400,granite,heavy
|
||||||
|
in,stone,600,marble,medium
|
||||||
|
in,stone,400,granite,light
|
||||||
|
in,stone,400,granite,light
|
||||||
|
in,paper,400,white,a4
|
||||||
|
in,stone,400,granite,light
|
||||||
|
in,wood,600,beech,boards
|
||||||
|
in,wood,600,pine,boards
|
||||||
|
in,stone,400,sandstone,light
|
||||||
|
out,paper,1000,white,a4
|
||||||
|
out,stone,1200,marble,medium
|
||||||
|
out,wood,1100,beech,boards
|
||||||
|
out,paper,1500,white,a4
|
||||||
|
out,wood,1000,pine,boards
|
||||||
|
out,stone,1200,sandstone,light
|
||||||
|
out,wood,1100,pine,boards
|
||||||
|
2
src/test/java/Tests.java
Normal file
2
src/test/java/Tests.java
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
public class Tests {
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user