Browse Source

1.0

Initial Commit
tags/1.0+1.15.2
TheBrokenRail 6 months ago
commit
c19790efc4
90 changed files with 3601 additions and 0 deletions
  1. +27
    -0
      .gitignore
  2. +4
    -0
      CHANGELOG.md
  3. +19
    -0
      Jenkinsfile
  4. +21
    -0
      LICENSE
  5. +16
    -0
      README.md
  6. +105
    -0
      build.gradle
  7. +21
    -0
      gradle.properties
  8. BIN
      gradle/wrapper/gradle-wrapper.jar
  9. +6
    -0
      gradle/wrapper/gradle-wrapper.properties
  10. +188
    -0
      gradlew
  11. +100
    -0
      gradlew.bat
  12. +12
    -0
      settings.gradle
  13. +189
    -0
      src/main/java/com/thebrokenrail/reliccraft/RelicCraft.java
  14. +42
    -0
      src/main/java/com/thebrokenrail/reliccraft/RelicLootTableFunction.java
  15. +34
    -0
      src/main/java/com/thebrokenrail/reliccraft/advancement/ActivateTeleportationBeaconCriterion.java
  16. +34
    -0
      src/main/java/com/thebrokenrail/reliccraft/advancement/ActivateTeleportationRestrictorCriterion.java
  17. +34
    -0
      src/main/java/com/thebrokenrail/reliccraft/advancement/DilateTimeCriterion.java
  18. +34
    -0
      src/main/java/com/thebrokenrail/reliccraft/advancement/DuplicateTimeDilaterCriterion.java
  19. +34
    -0
      src/main/java/com/thebrokenrail/reliccraft/advancement/RevealRelicCriterion.java
  20. +34
    -0
      src/main/java/com/thebrokenrail/reliccraft/advancement/UseTargetedEnderPearlCriterion.java
  21. +34
    -0
      src/main/java/com/thebrokenrail/reliccraft/advancement/UseTeleportationBeaconCriterion.java
  22. +129
    -0
      src/main/java/com/thebrokenrail/reliccraft/block/AbstractDragonEggHolderBlock.java
  23. +121
    -0
      src/main/java/com/thebrokenrail/reliccraft/block/DragonEggHolderBlockEntity.java
  24. +27
    -0
      src/main/java/com/thebrokenrail/reliccraft/block/TeleportationBeaconBlock.java
  25. +42
    -0
      src/main/java/com/thebrokenrail/reliccraft/block/TeleportationRestrictorBlock.java
  26. +60
    -0
      src/main/java/com/thebrokenrail/reliccraft/client/RelicCraftClient.java
  27. +20
    -0
      src/main/java/com/thebrokenrail/reliccraft/client/entity/RelicEntityRenderer.java
  28. +23
    -0
      src/main/java/com/thebrokenrail/reliccraft/data/Action.java
  29. +357
    -0
      src/main/java/com/thebrokenrail/reliccraft/data/Actions.java
  30. +63
    -0
      src/main/java/com/thebrokenrail/reliccraft/data/RelicData.java
  31. +82
    -0
      src/main/java/com/thebrokenrail/reliccraft/entity/RelicEntity.java
  32. +221
    -0
      src/main/java/com/thebrokenrail/reliccraft/item/RelicItem.java
  33. +116
    -0
      src/main/java/com/thebrokenrail/reliccraft/item/TargetedEnderPearlItem.java
  34. +92
    -0
      src/main/java/com/thebrokenrail/reliccraft/item/TimeDilaterItem.java
  35. +14
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/CriteriaRegistryHook.java
  36. +46
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/MixinClientPlayNetworkHandler.java
  37. +17
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/MixinEnderDragonFight.java
  38. +70
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/MixinEnderPearlItem.java
  39. +33
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/MixinEntity.java
  40. +19
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/MixinItemStack.java
  41. +41
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/MixinLevelProperties.java
  42. +18
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/MixinLivingEntity.java
  43. +27
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/MixinLocateCommand.java
  44. +16
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/MixinNetherStarItem.java
  45. +19
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/MixinServerWorld.java
  46. +23
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/MixinThrownEnderpearlEntity.java
  47. +50
    -0
      src/main/java/com/thebrokenrail/reliccraft/mixin/MixinWorld.java
  48. +39
    -0
      src/main/java/com/thebrokenrail/reliccraft/packet/UpdateTimeDilationS2CPacket.java
  49. +102
    -0
      src/main/java/com/thebrokenrail/reliccraft/recipe/RevealRelicRecipe.java
  50. +51
    -0
      src/main/java/com/thebrokenrail/reliccraft/recipe/TimeDilaterRecipe.java
  51. +34
    -0
      src/main/java/com/thebrokenrail/reliccraft/structure/TimeTempleFeature.java
  52. +127
    -0
      src/main/java/com/thebrokenrail/reliccraft/structure/TimeTempleGenerator.java
  53. +26
    -0
      src/main/java/com/thebrokenrail/reliccraft/structure/TimeTempleStructureStart.java
  54. +10
    -0
      src/main/resources/assets/reliccraft/blockstates/teleportation_beacon.json
  55. +10
    -0
      src/main/resources/assets/reliccraft/blockstates/teleportation_restrictor.json
  56. +67
    -0
      src/main/resources/assets/reliccraft/lang/en_us.json
  57. +6
    -0
      src/main/resources/assets/reliccraft/models/block/active_teleportation_beacon.json
  58. +6
    -0
      src/main/resources/assets/reliccraft/models/block/active_teleportation_restrictor.json
  59. +6
    -0
      src/main/resources/assets/reliccraft/models/block/teleportation_beacon.json
  60. +6
    -0
      src/main/resources/assets/reliccraft/models/block/teleportation_restrictor.json
  61. +6
    -0
      src/main/resources/assets/reliccraft/models/item/orb.json
  62. +7
    -0
      src/main/resources/assets/reliccraft/models/item/staff.json
  63. +3
    -0
      src/main/resources/assets/reliccraft/models/item/targeted_ender_pearl.json
  64. +11
    -0
      src/main/resources/assets/reliccraft/models/item/teleportation_beacon.json
  65. +11
    -0
      src/main/resources/assets/reliccraft/models/item/teleportation_restrictor.json
  66. +6
    -0
      src/main/resources/assets/reliccraft/models/item/time_dilater.json
  67. BIN
      src/main/resources/assets/reliccraft/textures/block/active_teleportation_beacon.png
  68. BIN
      src/main/resources/assets/reliccraft/textures/block/active_teleportation_restrictor.png
  69. BIN
      src/main/resources/assets/reliccraft/textures/block/teleportation_beacon.png
  70. BIN
      src/main/resources/assets/reliccraft/textures/block/teleportation_restrictor.png
  71. BIN
      src/main/resources/assets/reliccraft/textures/item/orb.png
  72. BIN
      src/main/resources/assets/reliccraft/textures/item/staff_handle.png
  73. BIN
      src/main/resources/assets/reliccraft/textures/item/staff_orb.png
  74. BIN
      src/main/resources/assets/reliccraft/textures/item/time_dilater.png
  75. +33
    -0
      src/main/resources/data/reliccraft/advancements/activate_teleportation_beacon.json
  76. +27
    -0
      src/main/resources/data/reliccraft/advancements/activate_teleportation_restrictor.json
  77. +28
    -0
      src/main/resources/data/reliccraft/advancements/dilate_time.json
  78. +26
    -0
      src/main/resources/data/reliccraft/advancements/duplicate_time_dilater.json
  79. +26
    -0
      src/main/resources/data/reliccraft/advancements/reveal_relic.json
  80. +36
    -0
      src/main/resources/data/reliccraft/advancements/root.json
  81. +19
    -0
      src/main/resources/data/reliccraft/loot_tables/blocks/teleportation_beacon.json
  82. +19
    -0
      src/main/resources/data/reliccraft/loot_tables/blocks/teleportation_restrictor.json
  83. +3
    -0
      src/main/resources/data/reliccraft/recipes/reveal_relic.json
  84. +22
    -0
      src/main/resources/data/reliccraft/recipes/teleportation_beacon.json
  85. +22
    -0
      src/main/resources/data/reliccraft/recipes/teleportation_restrictor.json
  86. +3
    -0
      src/main/resources/data/reliccraft/recipes/time_dilater.json
  87. BIN
      src/main/resources/data/reliccraft/structures/time_temple.nbt
  88. +10
    -0
      src/main/resources/data/reliccraft/tags/items/relics.json
  89. +34
    -0
      src/main/resources/fabric.mod.json
  90. +25
    -0
      src/main/resources/reliccraft.mixins.json

+ 27
- 0
.gitignore View File

@@ -0,0 +1,27 @@
# gradle

.gradle/
build/
out/
classes/

# idea

.idea/
*.iml
*.ipr
*.iws

# vscode

.settings/
.vscode/
bin/
.classpath
.project

# fabric

run/

remappedSrc/

+ 4
- 0
CHANGELOG.md View File

@@ -0,0 +1,4 @@
# Changelog

**1.0**
* Initial Release

+ 19
- 0
Jenkinsfile View File

@@ -0,0 +1,19 @@
pipeline {
agent {
docker {
image 'openjdk:8-jdk'
}
}
stages {
stage('Build') {
steps {
sh './gradlew build'
}
post {
success {
archiveArtifacts artifacts: 'build/libs/*', fingerprint: true
}
}
}
}
}

+ 21
- 0
LICENSE View File

@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020 TheBrokenRail

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

+ 16
- 0
README.md View File

@@ -0,0 +1,16 @@
# RelicCraft
Find magical relics throughout the world!

This mod adds several magical items and blocks that can be found randomly throughout the world.

This mod was created for [ModFest 1.15](https://modfest.github.io/1.15/)

## Features
* Magical Orbs and Staffs With Randomly-Generated Actions
* Randomly-Generated Time Temples
* Time Dilaters
* Teleportation Restrictors
* Teleportation Beacons

## Changelog
[View Changelog](CHANGELOG.md)

+ 105
- 0
build.gradle View File

@@ -0,0 +1,105 @@
plugins {
id 'fabric-loom' version '0.2.7-SNAPSHOT'
id 'com.matthewprenger.cursegradle' version '1.4.0'
id "com.github.johnrengelman.shadow" version "5.2.0"
}

compileJava {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

archivesBaseName = project.archives_base_name
def mod_version = project.mod_version as Object
version = "${mod_version}+${project.minecraft_version}"
group = project.maven_group as Object

minecraft {
}

repositories {
jcenter()
maven {
url "https://dl.bintray.com/shedaniel/autoconfig1u/"
}
}

dependencies {
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.minecraft_version}+build.${project.yarn_build}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.fabric_loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"

modImplementation "io.github.prospector:modmenu:${project.mod_menu_version}"

implementation "com.squareup.moshi:moshi:${project.moshi_version}"
shadow "com.squareup.moshi:moshi:${project.moshi_version}"
}

processResources {
inputs.property 'version', mod_version
inputs.property 'name', rootProject.name

from(sourceSets.main.resources.srcDirs) {
include 'fabric.mod.json'
expand 'version': mod_version, 'name': rootProject.name
}

from(sourceSets.main.resources.srcDirs) {
exclude 'fabric.mod.json'
}
}

// ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}

// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this task, sources will not be generated.
task sourcesJar(type: Jar, dependsOn: classes) {
classifier 'sources'
from sourceSets.main.allSource
}

task javadocJar(type: Jar, dependsOn: javadoc) {
classifier 'javadoc'
from javadoc.destinationDir
}

artifacts {
archives sourcesJar
archives javadocJar
}

jar {
from "LICENSE"
}

if (project.hasProperty('curseforge.api_key')) {
curseforge {
apiKey = project.getProperty('curseforge.api_key')
project {
id = project.curseforge_id
changelog = 'A changelog can be found at https://gitea.thebrokenrail.com/TheBrokenRail/RelicCraft/src/branch/master/CHANGELOG.md'
releaseType = 'release'
addGameVersion project.simple_minecraft_version
addGameVersion 'Fabric'
mainArtifact(remapJar) {
displayName = "RelicCraft v${mod_version} for ${project.minecraft_version}"
}
afterEvaluate {
uploadTask.dependsOn('remapJar')
}
relations {
requiredDependency 'fabric-api'
}
}
options {
forgeGradleIntegration = false
}
}
}

+ 21
- 0
gradle.properties View File

@@ -0,0 +1,21 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs = -Xmx1G

# Fabric Properties
# check these on https://fabricmc.net/use
minecraft_version = 1.15.2
curseforge_id = 373074
simple_minecraft_version = 1.15.2
yarn_build = 14
fabric_loader_version = 0.7.9+build.190

# Mod Properties
mod_version = 1.0.0
maven_group = com.thebrokenrail
archives_base_name = reliccraft

# Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
fabric_api_version = 0.5.1+build.294-1.15
mod_menu_version = 1.10.2+build.32
moshi_version = 1.9.2

BIN
gradle/wrapper/gradle-wrapper.jar View File


+ 6
- 0
gradle/wrapper/gradle-wrapper.properties View File

@@ -0,0 +1,6 @@
#Sat Feb 29 21:58:32 EST 2020
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-all.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

+ 188
- 0
gradlew View File

@@ -0,0 +1,188 @@
#!/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, switch paths to Windows format before running java
if $cygwin ; 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=$((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"

# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi

exec "$JAVACMD" "$@"

+ 100
- 0
gradlew.bat View 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

+ 12
- 0
settings.gradle View File

@@ -0,0 +1,12 @@
pluginManagement {
repositories {
jcenter()
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
gradlePluginPortal()
}
}

rootProject.name = 'RelicCraft'

+ 189
- 0
src/main/java/com/thebrokenrail/reliccraft/RelicCraft.java View File

@@ -0,0 +1,189 @@
package com.thebrokenrail.reliccraft;

import com.thebrokenrail.reliccraft.advancement.ActivateTeleportationBeaconCriterion;
import com.thebrokenrail.reliccraft.advancement.ActivateTeleportationRestrictorCriterion;
import com.thebrokenrail.reliccraft.advancement.DilateTimeCriterion;
import com.thebrokenrail.reliccraft.advancement.DuplicateTimeDilaterCriterion;
import com.thebrokenrail.reliccraft.advancement.RevealRelicCriterion;
import com.thebrokenrail.reliccraft.advancement.UseTargetedEnderPearlCriterion;
import com.thebrokenrail.reliccraft.advancement.UseTeleportationBeaconCriterion;
import com.thebrokenrail.reliccraft.block.DragonEggHolderBlockEntity;
import com.thebrokenrail.reliccraft.block.TeleportationBeaconBlock;
import com.thebrokenrail.reliccraft.block.TeleportationRestrictorBlock;
import com.thebrokenrail.reliccraft.entity.RelicEntity;
import com.thebrokenrail.reliccraft.item.TargetedEnderPearlItem;
import com.thebrokenrail.reliccraft.item.TimeDilaterItem;
import com.thebrokenrail.reliccraft.item.RelicItem;
import com.thebrokenrail.reliccraft.mixin.CriteriaRegistryHook;
import com.thebrokenrail.reliccraft.recipe.RevealRelicRecipe;
import com.thebrokenrail.reliccraft.recipe.TimeDilaterRecipe;
import com.thebrokenrail.reliccraft.structure.TimeTempleFeature;
import com.thebrokenrail.reliccraft.structure.TimeTempleGenerator;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.entity.FabricEntityTypeBuilder;
import net.fabricmc.fabric.api.loot.v1.FabricLootPoolBuilder;
import net.fabricmc.fabric.api.loot.v1.event.LootTableLoadingCallback;
import net.fabricmc.fabric.api.tag.TagRegistry;
import net.minecraft.block.Block;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.EntityCategory;
import net.minecraft.entity.EntityDimensions;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.loot.BinomialLootTableRange;
import net.minecraft.loot.LootTables;
import net.minecraft.loot.entry.ItemEntry;
import net.minecraft.recipe.SpecialRecipeSerializer;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
import net.minecraft.structure.StructurePieceType;
import net.minecraft.util.Identifier;
import net.minecraft.util.Rarity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.chunk.FlatChunkGeneratorConfig;
import net.minecraft.world.gen.decorator.Decorator;
import net.minecraft.world.gen.decorator.DecoratorConfig;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.FeatureConfig;
import net.minecraft.world.gen.feature.StructureFeature;

import java.util.Locale;

public class RelicCraft implements ModInitializer {
public static final String NAMESPACE = "reliccraft";

public static Item ORB_ITEM;
public static Item STAFF_ITEM;
public static Item TIME_DILATER_ITEM;

public static Item TARGETED_ENDER_PEARL_ITEM;

public static EntityType<RelicEntity> RELIC_ENTITY;

public static SpecialRecipeSerializer<RevealRelicRecipe> REVEAL_RELIC_RECIPE;
public static SpecialRecipeSerializer<TimeDilaterRecipe> TIME_DILATER_RECIPE;

public static Block TELEPORTATION_RESTRICTOR_BLOCK;
public static Block TELEPORTATION_BEACON_BLOCK;
public static BlockEntityType<DragonEggHolderBlockEntity> DRAGON_EGG_HOLDER_BLOCK_ENTITY;

public static final Identifier[] LOOT_TABLES = new Identifier[]{
LootTables.SIMPLE_DUNGEON_CHEST,
LootTables.END_CITY_TREASURE_CHEST,
LootTables.NETHER_BRIDGE_CHEST,
LootTables.ABANDONED_MINESHAFT_CHEST,
LootTables.SHIPWRECK_TREASURE_CHEST,
LootTables.DESERT_PYRAMID_CHEST,
LootTables.JUNGLE_TEMPLE_CHEST,
LootTables.STRONGHOLD_LIBRARY_CHEST,
LootTables.PILLAGER_OUTPOST_CHEST,
LootTables.WOODLAND_MANSION_CHEST,
LootTables.BURIED_TREASURE_CHEST,
LootTables.FISHING_TREASURE_GAMEPLAY
};

public static ActivateTeleportationRestrictorCriterion ACTIVATE_TELEPORTATION_RESTRICTOR_CRITERION;
public static RevealRelicCriterion REVEAL_RELIC_CRITERION;
public static DilateTimeCriterion DILATE_TIME_CRITERION;
public static DuplicateTimeDilaterCriterion DUPLICATE_TIME_DILATER_CRITERION;
public static ActivateTeleportationBeaconCriterion ACTIVATE_TELEPORTATION_BEACON_CRITERION;
public static UseTeleportationBeaconCriterion USE_TELEPORTATION_BEACON_CRITERION;
public static UseTargetedEnderPearlCriterion USE_TARGETED_ENDER_PEARL;

private boolean isSelectedLootTable(Identifier lootTable) {
for (Identifier id : LOOT_TABLES) {
if (id.equals(lootTable)) {
return true;
}
}
return false;
}

private static final SoundEvent RELIC_SOUND_EFFECT = SoundEvents.BLOCK_ENCHANTMENT_TABLE_USE;
private static final SoundEvent INTERACT_TELEPORT_RESTRICTOR_SOUND_EFFECT = SoundEvents.BLOCK_END_PORTAL_FRAME_FILL;

public static void playRelicSound(PlayerEntity player) {
player.playSound(RELIC_SOUND_EFFECT, SoundCategory.PLAYERS, 1.0f, 1.0f);
}

public static void playInteractTeleportRestrictorSound(World world, BlockPos pos) {
world.playSound(null, pos, INTERACT_TELEPORT_RESTRICTOR_SOUND_EFFECT, SoundCategory.BLOCKS, 1.0f, 1.0f);
}

public static StructureFeature<DefaultFeatureConfig> TIME_TEMPLE_STRUCTURE_FEATURE;
public static StructurePieceType TIME_TEMPLE_STRUCTURE_PIECE;
public static final String TIME_TEMPLE_ID = "RelicCraft Time Temple";

@Override
public void onInitialize() {
ORB_ITEM = Registry.register(Registry.ITEM, new Identifier(NAMESPACE, "orb"), new RelicItem());
STAFF_ITEM = Registry.register(Registry.ITEM, new Identifier(NAMESPACE, "staff"), new RelicItem());
TIME_DILATER_ITEM = Registry.register(Registry.ITEM, new Identifier(NAMESPACE, "time_dilater"), new TimeDilaterItem());

TARGETED_ENDER_PEARL_ITEM = Registry.register(Registry.ITEM, new Identifier(NAMESPACE, "targeted_ender_pearl"), new TargetedEnderPearlItem());

RELIC_ENTITY = FabricEntityTypeBuilder.create(EntityCategory.MISC, (EntityType.EntityFactory<RelicEntity>) RelicEntity::new).size(EntityDimensions.fixed(0.25f, 0.25f)).build();

LootTableLoadingCallback.EVENT.register((resourceManager, lootManager, id, supplier, setter) -> {
if (isSelectedLootTable(id)) {
FabricLootPoolBuilder poolBuilder = FabricLootPoolBuilder.builder()
.withRolls(new BinomialLootTableRange(2, 0.5f))
.withEntry(ItemEntry.builder(ORB_ITEM))
.withEntry(ItemEntry.builder(STAFF_ITEM))
.withFunction(new RelicLootTableFunction.Builder());

supplier.withPool(poolBuilder);
}
});

REVEAL_RELIC_RECIPE = Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(NAMESPACE, "reveal_relic"), new SpecialRecipeSerializer<>(RevealRelicRecipe::new));
TIME_DILATER_RECIPE = Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(NAMESPACE, "time_dilater"), new SpecialRecipeSerializer<>(TimeDilaterRecipe::new));

TELEPORTATION_RESTRICTOR_BLOCK = Registry.register(Registry.BLOCK, new Identifier(NAMESPACE, "teleportation_restrictor"), new TeleportationRestrictorBlock());
TELEPORTATION_BEACON_BLOCK = Registry.register(Registry.BLOCK, new Identifier(NAMESPACE, "teleportation_beacon"), new TeleportationBeaconBlock());
DRAGON_EGG_HOLDER_BLOCK_ENTITY = Registry.register(Registry.BLOCK_ENTITY_TYPE, new Identifier(NAMESPACE, "dragon_egg_holder"), BlockEntityType.Builder.create(DragonEggHolderBlockEntity::new, TELEPORTATION_RESTRICTOR_BLOCK, TELEPORTATION_BEACON_BLOCK).build(null));

Registry.register(Registry.ITEM, new Identifier(NAMESPACE, "teleportation_restrictor"), new BlockItem(TELEPORTATION_RESTRICTOR_BLOCK, new Item.Settings().group(ItemGroup.MISC).rarity(Rarity.UNCOMMON)));
Registry.register(Registry.ITEM, new Identifier(NAMESPACE, "teleportation_beacon"), new BlockItem(TELEPORTATION_BEACON_BLOCK, new Item.Settings().group(ItemGroup.MISC).rarity(Rarity.UNCOMMON)));

ACTIVATE_TELEPORTATION_RESTRICTOR_CRITERION = CriteriaRegistryHook.callRegister(new ActivateTeleportationRestrictorCriterion());
REVEAL_RELIC_CRITERION = CriteriaRegistryHook.callRegister(new RevealRelicCriterion());
DILATE_TIME_CRITERION = CriteriaRegistryHook.callRegister(new DilateTimeCriterion());
DUPLICATE_TIME_DILATER_CRITERION = CriteriaRegistryHook.callRegister(new DuplicateTimeDilaterCriterion());
ACTIVATE_TELEPORTATION_BEACON_CRITERION = CriteriaRegistryHook.callRegister(new ActivateTeleportationBeaconCriterion());
USE_TELEPORTATION_BEACON_CRITERION = CriteriaRegistryHook.callRegister(new UseTeleportationBeaconCriterion());
USE_TARGETED_ENDER_PEARL = CriteriaRegistryHook.callRegister(new UseTargetedEnderPearlCriterion());

//noinspection ResultOfMethodCallIgnored
TagRegistry.item(new Identifier(NAMESPACE, "relics"));

TIME_TEMPLE_STRUCTURE_PIECE = Registry.register(Registry.STRUCTURE_PIECE, new Identifier(NAMESPACE, "time_temple"), TimeTempleGenerator.Piece::new);
TIME_TEMPLE_STRUCTURE_FEATURE = Registry.register(Registry.FEATURE, new Identifier(NAMESPACE, "time_temple"), new TimeTempleFeature(DefaultFeatureConfig::deserialize));
Registry.register(Registry.STRUCTURE_FEATURE, new Identifier(NAMESPACE, "time_temple"), TIME_TEMPLE_STRUCTURE_FEATURE);

Feature.STRUCTURES.put(TIME_TEMPLE_ID.toLowerCase(Locale.ROOT), TIME_TEMPLE_STRUCTURE_FEATURE);

ConfiguredFeature<?, ?> configuredFeature = TIME_TEMPLE_STRUCTURE_FEATURE.configure(FeatureConfig.DEFAULT).createDecoratedFeature(Decorator.NOPE.configure(DecoratorConfig.DEFAULT));

for (Biome biome : Registry.BIOME) {
biome.addFeature(GenerationStep.Feature.SURFACE_STRUCTURES, configuredFeature);
if (biome.getCategory() == Biome.Category.PLAINS) {
biome.addStructureFeature(TIME_TEMPLE_STRUCTURE_FEATURE.configure(FeatureConfig.DEFAULT));
}
}

FlatChunkGeneratorConfig.FEATURE_TO_GENERATION_STEP.put(configuredFeature, GenerationStep.Feature.SURFACE_STRUCTURES);
FlatChunkGeneratorConfig.FEATURE_TO_FEATURE_CONFIG.put(configuredFeature, FeatureConfig.DEFAULT);
FlatChunkGeneratorConfig.STRUCTURE_TO_FEATURES.put(NAMESPACE + "_time_temple", new ConfiguredFeature[]{configuredFeature});
}
}

+ 42
- 0
src/main/java/com/thebrokenrail/reliccraft/RelicLootTableFunction.java View File

@@ -0,0 +1,42 @@
package com.thebrokenrail.reliccraft;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.thebrokenrail.reliccraft.data.RelicData;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.condition.LootCondition;
import net.minecraft.loot.context.LootContext;
import net.minecraft.loot.function.ConditionalLootFunction;
import net.minecraft.loot.function.LootFunction;
import net.minecraft.nbt.CompoundTag;

public class RelicLootTableFunction extends ConditionalLootFunction {
private RelicLootTableFunction(LootCondition[] conditions) {
super(conditions);
}

public ItemStack process(ItemStack stack, LootContext context) {
CompoundTag tag = new CompoundTag();
Moshi moshi = new Moshi.Builder().build();
JsonAdapter<RelicData> jsonAdapter = moshi.adapter(RelicData.class);
tag.putString("RelicData", jsonAdapter.toJson(RelicData.generate(context.getRandom())));
stack.setTag(tag);
double chance = 1.0d;
while (!(context.getRandom().nextDouble() > chance)) {
chance = chance * 0.25d;
}
return stack;
}

public static class Builder extends ConditionalLootFunction.Builder<RelicLootTableFunction.Builder> {
@Override
protected RelicLootTableFunction.Builder getThisBuilder() {
return this;
}

public LootFunction build() {
return new RelicLootTableFunction(getConditions());
}
}
}


+ 34
- 0
src/main/java/com/thebrokenrail/reliccraft/advancement/ActivateTeleportationBeaconCriterion.java View File

@@ -0,0 +1,34 @@
package com.thebrokenrail.reliccraft.advancement;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.thebrokenrail.reliccraft.RelicCraft;
import net.minecraft.advancement.criterion.AbstractCriterion;
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;

public class ActivateTeleportationBeaconCriterion extends AbstractCriterion<ActivateTeleportationBeaconCriterion.Conditions> {
private static final Identifier ID = new Identifier(RelicCraft.NAMESPACE, "activate_teleportation_beacon");

public ActivateTeleportationBeaconCriterion() {
}

public Identifier getId() {
return ID;
}

public Conditions conditionsFromJson(JsonObject jsonObject, JsonDeserializationContext jsonDeserializationContext) {
return new Conditions();
}

public void trigger(ServerPlayerEntity player) {
test(player.getAdvancementTracker(), conditions -> true);
}

public static class Conditions extends AbstractCriterionConditions {
public Conditions() {
super(ID);
}
}
}

+ 34
- 0
src/main/java/com/thebrokenrail/reliccraft/advancement/ActivateTeleportationRestrictorCriterion.java View File

@@ -0,0 +1,34 @@
package com.thebrokenrail.reliccraft.advancement;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.thebrokenrail.reliccraft.RelicCraft;
import net.minecraft.advancement.criterion.AbstractCriterion;
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;

public class ActivateTeleportationRestrictorCriterion extends AbstractCriterion<ActivateTeleportationRestrictorCriterion.Conditions> {
private static final Identifier ID = new Identifier(RelicCraft.NAMESPACE, "activate_teleportation_restrictor");

public ActivateTeleportationRestrictorCriterion() {
}

public Identifier getId() {
return ID;
}

public Conditions conditionsFromJson(JsonObject jsonObject, JsonDeserializationContext jsonDeserializationContext) {
return new Conditions();
}

public void trigger(ServerPlayerEntity player) {
test(player.getAdvancementTracker(), conditions -> true);
}

public static class Conditions extends AbstractCriterionConditions {
public Conditions() {
super(ID);
}
}
}

+ 34
- 0
src/main/java/com/thebrokenrail/reliccraft/advancement/DilateTimeCriterion.java View File

@@ -0,0 +1,34 @@
package com.thebrokenrail.reliccraft.advancement;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.thebrokenrail.reliccraft.RelicCraft;
import net.minecraft.advancement.criterion.AbstractCriterion;
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;

public class DilateTimeCriterion extends AbstractCriterion<DilateTimeCriterion.Conditions> {
private static final Identifier ID = new Identifier(RelicCraft.NAMESPACE, "dilate_time");

public DilateTimeCriterion() {
}

public Identifier getId() {
return ID;
}

public Conditions conditionsFromJson(JsonObject jsonObject, JsonDeserializationContext jsonDeserializationContext) {
return new Conditions();
}

public void trigger(ServerPlayerEntity player) {
test(player.getAdvancementTracker(), conditions -> true);
}

public static class Conditions extends AbstractCriterionConditions {
public Conditions() {
super(ID);
}
}
}

+ 34
- 0
src/main/java/com/thebrokenrail/reliccraft/advancement/DuplicateTimeDilaterCriterion.java View File

@@ -0,0 +1,34 @@
package com.thebrokenrail.reliccraft.advancement;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.thebrokenrail.reliccraft.RelicCraft;
import net.minecraft.advancement.criterion.AbstractCriterion;
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;

public class DuplicateTimeDilaterCriterion extends AbstractCriterion<DuplicateTimeDilaterCriterion.Conditions> {
private static final Identifier ID = new Identifier(RelicCraft.NAMESPACE, "duplicate_time_dilater");

public DuplicateTimeDilaterCriterion() {
}

public Identifier getId() {
return ID;
}

public Conditions conditionsFromJson(JsonObject jsonObject, JsonDeserializationContext jsonDeserializationContext) {
return new Conditions();
}

public void trigger(ServerPlayerEntity player) {
test(player.getAdvancementTracker(), conditions -> true);
}

public static class Conditions extends AbstractCriterionConditions {
public Conditions() {
super(ID);
}
}
}

+ 34
- 0
src/main/java/com/thebrokenrail/reliccraft/advancement/RevealRelicCriterion.java View File

@@ -0,0 +1,34 @@
package com.thebrokenrail.reliccraft.advancement;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.thebrokenrail.reliccraft.RelicCraft;
import net.minecraft.advancement.criterion.AbstractCriterion;
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;

public class RevealRelicCriterion extends AbstractCriterion<RevealRelicCriterion.Conditions> {
private static final Identifier ID = new Identifier(RelicCraft.NAMESPACE, "reveal_relic");

public RevealRelicCriterion() {
}

public Identifier getId() {
return ID;
}

public Conditions conditionsFromJson(JsonObject jsonObject, JsonDeserializationContext jsonDeserializationContext) {
return new Conditions();
}

public void trigger(ServerPlayerEntity player) {
test(player.getAdvancementTracker(), conditions -> true);
}

public static class Conditions extends AbstractCriterionConditions {
public Conditions() {
super(ID);
}
}
}

+ 34
- 0
src/main/java/com/thebrokenrail/reliccraft/advancement/UseTargetedEnderPearlCriterion.java View File

@@ -0,0 +1,34 @@
package com.thebrokenrail.reliccraft.advancement;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.thebrokenrail.reliccraft.RelicCraft;
import net.minecraft.advancement.criterion.AbstractCriterion;
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;

public class UseTargetedEnderPearlCriterion extends AbstractCriterion<UseTargetedEnderPearlCriterion.Conditions> {
private static final Identifier ID = new Identifier(RelicCraft.NAMESPACE, "use_targeted_ender_pearl");

public UseTargetedEnderPearlCriterion() {
}

public Identifier getId() {
return ID;
}

public Conditions conditionsFromJson(JsonObject jsonObject, JsonDeserializationContext jsonDeserializationContext) {
return new Conditions();
}

public void trigger(ServerPlayerEntity player) {
test(player.getAdvancementTracker(), conditions -> true);
}

public static class Conditions extends AbstractCriterionConditions {
public Conditions() {
super(ID);
}
}
}

+ 34
- 0
src/main/java/com/thebrokenrail/reliccraft/advancement/UseTeleportationBeaconCriterion.java View File

@@ -0,0 +1,34 @@
package com.thebrokenrail.reliccraft.advancement;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.thebrokenrail.reliccraft.RelicCraft;
import net.minecraft.advancement.criterion.AbstractCriterion;
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;

public class UseTeleportationBeaconCriterion extends AbstractCriterion<UseTeleportationBeaconCriterion.Conditions> {
private static final Identifier ID = new Identifier(RelicCraft.NAMESPACE, "use_teleportation_beacon");

public UseTeleportationBeaconCriterion() {
}

public Identifier getId() {
return ID;
}

public Conditions conditionsFromJson(JsonObject jsonObject, JsonDeserializationContext jsonDeserializationContext) {
return new Conditions();
}

public void trigger(ServerPlayerEntity player) {
test(player.getAdvancementTracker(), conditions -> true);
}

public static class Conditions extends AbstractCriterionConditions {
public Conditions() {
super(ID);
}
}
}

+ 129
- 0
src/main/java/com/thebrokenrail/reliccraft/block/AbstractDragonEggHolderBlock.java View File

@@ -0,0 +1,129 @@
package com.thebrokenrail.reliccraft.block;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.Block;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.container.Container;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;

import java.util.Random;

@SuppressWarnings("deprecation")
public abstract class AbstractDragonEggHolderBlock extends Block implements BlockEntityProvider {
public static final BooleanProperty ACTIVE = BooleanProperty.of("active");

public AbstractDragonEggHolderBlock(Settings settings) {
super(settings);
setDefaultState(getStateManager().getDefaultState().with(ACTIVE, false));
}

@Override
public int getLuminance(BlockState state) {
return state.get(ACTIVE) ? 7 : 0;
}

@Override
public BlockEntity createBlockEntity(BlockView view) {
return new DragonEggHolderBlockEntity();
}

@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
Inventory blockEntity = (Inventory) world.getBlockEntity(pos);

if (blockEntity != null) {
ItemStack stack = player.getStackInHand(hand);

if (!stack.isEmpty()) {
if (blockEntity.isValidInvStack(0, stack) && blockEntity.getInvStack(0).isEmpty()) {
blockEntity.setInvStack(0, stack.split(1));
if (!world.isClient()) {
grantAdvancement(player);
}
return ActionResult.SUCCESS;
} else {
return ActionResult.PASS;
}
} else {
if (!blockEntity.getInvStack(0).isEmpty()) {
player.inventory.offerOrDrop(world, blockEntity.getInvStack(0));
blockEntity.removeInvStack(0);
return ActionResult.SUCCESS;
} else {
return ActionResult.PASS;
}
}
} else {
return ActionResult.PASS;
}
}

private boolean isActive(World world, BlockPos pos) {
return world.getBlockState(pos).get(ACTIVE);
}

@Override
@Environment(EnvType.CLIENT)
public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) {
if (isActive(world, pos)) {
if (random.nextInt(100) == 0) {
world.playSound(null, pos, SoundEvents.BLOCK_PORTAL_AMBIENT, SoundCategory.BLOCKS, 0.5F, random.nextFloat() * 0.4F + 0.8F);
}

for (int i = 0; i < 24; ++i) {
double x = (double) pos.getX() + 0.5D + (double) (0.5F - random.nextFloat());
double y = (double) pos.getY() + 0.5D + (double) (0.5F - random.nextFloat());
double z = (double) pos.getZ() + 0.5D + (double) (0.5F - random.nextFloat());
world.addParticle(ParticleTypes.PORTAL, x, y, z, (random.nextDouble() - 0.5D) * 2.0D, -random.nextDouble(), (random.nextDouble() - 0.5D) * 2.0D);
}
}
}

@Override
public void onBlockRemoved(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if (state.getBlock() != newState.getBlock()) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof Inventory) {
ItemScatterer.spawn(world, pos, (Inventory) blockEntity);
}

super.onBlockRemoved(state, world, pos, newState, moved);
}
}

@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(ACTIVE);
}

@Override
public boolean hasComparatorOutput(BlockState state) {
return true;
}

@Override
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
return Container.calculateComparatorOutput(world.getBlockEntity(pos));
}

public abstract void tick(World world, BlockPos pos, Inventory inventory);

public abstract void grantAdvancement(PlayerEntity player);
}

+ 121
- 0
src/main/java/com/thebrokenrail/reliccraft/block/DragonEggHolderBlockEntity.java View File

@@ -0,0 +1,121 @@
package com.thebrokenrail.reliccraft.block;

import com.thebrokenrail.reliccraft.RelicCraft;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventories;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Tickable;

public class DragonEggHolderBlockEntity extends BlockEntity implements Inventory, Tickable {
public DragonEggHolderBlockEntity() {
super(RelicCraft.DRAGON_EGG_HOLDER_BLOCK_ENTITY);
}

@Override
public void fromTag(CompoundTag tag) {
super.fromTag(tag);
DefaultedList<ItemStack> list = DefaultedList.ofSize(getInvSize(), ItemStack.EMPTY);
Inventories.fromTag(tag, list);
stack = list.get(0);
}

@Override
public CompoundTag toTag(CompoundTag tag) {
DefaultedList<ItemStack> list = DefaultedList.ofSize(getInvSize(), ItemStack.EMPTY);
list.set(0, stack);
Inventories.toTag(tag, list);
return super.toTag(tag);
}

private ItemStack stack = ItemStack.EMPTY;

@Override
public int getInvSize() {
return 1;
}

@Override
public int getInvMaxStackAmount() {
return 1;
}

@Override
public boolean isInvEmpty() {
return stack.isEmpty();
}

@Override
public ItemStack getInvStack(int slot) {
return stack;
}

@Override
public ItemStack takeInvStack(int slot, int amount) {
ItemStack newStack = getInvStack(0).split(amount);
markDirty();
return newStack;
}

@Override
public ItemStack removeInvStack(int slot) {
ItemStack newStack = getInvStack(0).copy();
setInvStack(0, ItemStack.EMPTY);
return newStack;
}

@Override
public void setInvStack(int slot, ItemStack stack) {
this.stack = stack;
if (stack.getCount() > getInvMaxStackAmount()) {
stack.setCount(getInvMaxStackAmount());
}
markDirty();
}

@Override
public boolean canPlayerUseInv(PlayerEntity player) {
return true;
}

@Override
public void clear() {
setInvStack(0, ItemStack.EMPTY);
}

@Override
public void tick() {
if (hasWorld()) {
assert getWorld() != null;
Block block = getWorld().getBlockState(getPos()).getBlock();
if (block instanceof AbstractDragonEggHolderBlock) {
((AbstractDragonEggHolderBlock) block).tick(getWorld(), getPos(), this);
}
}
}

@Override
public boolean isValidInvStack(int slot, ItemStack stack) {
return stack.getItem() == Items.DRAGON_EGG;
}

@Override
public void markDirty() {
super.markDirty();
if (hasWorld()) {
assert getWorld() != null;
BlockState state = getWorld().getBlockState(pos);
boolean active = !getInvStack(0).isEmpty();
if (state.get(TeleportationRestrictorBlock.ACTIVE) != active) {
getWorld().setBlockState(getPos(), state.with(TeleportationRestrictorBlock.ACTIVE, active));
RelicCraft.playInteractTeleportRestrictorSound(getWorld(), getPos());
}
}
}
}

+ 27
- 0
src/main/java/com/thebrokenrail/reliccraft/block/TeleportationBeaconBlock.java View File

@@ -0,0 +1,27 @@
package com.thebrokenrail.reliccraft.block;

import com.thebrokenrail.reliccraft.RelicCraft;
import net.fabricmc.fabric.api.block.FabricBlockSettings;
import net.minecraft.block.Material;
import net.minecraft.block.MaterialColor;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

public class TeleportationBeaconBlock extends AbstractDragonEggHolderBlock {
public TeleportationBeaconBlock() {
super(FabricBlockSettings.of(Material.METAL, MaterialColor.IRON).strength(5.0F, 6.0F).sounds(BlockSoundGroup.METAL).build());
}

@Override
public void tick(World world, BlockPos pos, Inventory inventory) {
}

@Override
public void grantAdvancement(PlayerEntity player) {
RelicCraft.ACTIVATE_TELEPORTATION_BEACON_CRITERION.trigger((ServerPlayerEntity) player);
}
}

+ 42
- 0
src/main/java/com/thebrokenrail/reliccraft/block/TeleportationRestrictorBlock.java View File

@@ -0,0 +1,42 @@
package com.thebrokenrail.reliccraft.block;

import com.thebrokenrail.reliccraft.RelicCraft;
import net.fabricmc.fabric.api.block.FabricBlockSettings;
import net.minecraft.block.Material;
import net.minecraft.block.MaterialColor;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.world.World;

import java.util.List;

public class TeleportationRestrictorBlock extends AbstractDragonEggHolderBlock {
public interface TeleportingEntity {
boolean cannotTeleport();

void resetTeleportCooldown();
}

public TeleportationRestrictorBlock() {
super(FabricBlockSettings.of(Material.STONE, MaterialColor.BLACK).strength(50.0F, 1200.0F).build());
}

@Override
public void tick(World world, BlockPos pos, Inventory inventory) {
int radius = !inventory.getInvStack(0).isEmpty() ? 128 : 0;
Box box = new Box(pos).expand(radius);
List<LivingEntity> list = world.getNonSpectatingEntities(LivingEntity.class, box);
for (LivingEntity entity : list) {
((TeleportingEntity) entity).resetTeleportCooldown();
}
}

@Override
public void grantAdvancement(PlayerEntity player) {
RelicCraft.ACTIVATE_TELEPORTATION_RESTRICTOR_CRITERION.trigger((ServerPlayerEntity) player);
}
}

+ 60
- 0
src/main/java/com/thebrokenrail/reliccraft/client/RelicCraftClient.java View File

@@ -0,0 +1,60 @@
package com.thebrokenrail.reliccraft.client;

import com.thebrokenrail.reliccraft.RelicCraft;
import com.thebrokenrail.reliccraft.client.entity.RelicEntityRenderer;
import com.thebrokenrail.reliccraft.item.RelicItem;
import com.thebrokenrail.reliccraft.packet.UpdateTimeDilationS2CPacket;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry;
import net.fabricmc.fabric.impl.networking.ClientSidePacketRegistryImpl;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;

@SuppressWarnings("unused")
@Environment(EnvType.CLIENT)
public class RelicCraftClient implements ClientModInitializer {
public static int generateColor(float h, float s, float v) {
float r, g, b, i, f, p, q, t;
i = (float) Math.floor(h * 6);
f = h * 6 - i;
p = v * (1 - s);
q = v * (1 - f * s);
t = v * (1 - (1 - f) * s);
switch ((int) (i % 6)) {
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;
default: throw new UnsupportedOperationException();
}
return rgbToDecimal(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
}

private static int rgbToDecimal(int r, int g, int b) {
return (r << 16) | (g << 8) | b;
}

private static int getStackColor(ItemStack stack) {
if (stack.getName().asString().equals("jeb_")) {
return generateColor(Util.getMeasuringTimeMs() / 3600f, 1f, 1f);
} else {
return RelicItem.getData(stack).color;
}
}

@Override
public void onInitializeClient() {
ColorProviderRegistry.ITEM.register((stack, tintIndex) -> tintIndex > 0 ? -1 : getStackColor(stack), RelicCraft.ORB_ITEM);
ColorProviderRegistry.ITEM.register((stack, tintIndex) -> tintIndex > 0 ? -1 : getStackColor(stack), RelicCraft.STAFF_ITEM);

EntityRendererRegistry.INSTANCE.register(RelicCraft.RELIC_ENTITY, (entityRenderDispatcher, context) -> new RelicEntityRenderer(entityRenderDispatcher));

ClientSidePacketRegistryImpl.INSTANCE.register(new Identifier(RelicCraft.NAMESPACE, "update_time_dilation"), UpdateTimeDilationS2CPacket::handle);
}
}

+ 20
- 0
src/main/java/com/thebrokenrail/reliccraft/client/entity/RelicEntityRenderer.java View File

@@ -0,0 +1,20 @@
package com.thebrokenrail.reliccraft.client.entity;

import com.thebrokenrail.reliccraft.entity.RelicEntity;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.util.Identifier;

@Environment(EnvType.CLIENT)
public class RelicEntityRenderer extends EntityRenderer<RelicEntity> {
public RelicEntityRenderer(EntityRenderDispatcher entityRenderDispatcher) {
super(entityRenderDispatcher);
}

@Override
public Identifier getTexture(RelicEntity relicEntity) {
return null;
}
}

+ 23
- 0
src/main/java/com/thebrokenrail/reliccraft/data/Action.java View File

@@ -0,0 +1,23 @@
package com.thebrokenrail.reliccraft.data;

import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

public interface Action {
void execute(World world, LivingEntity attacker, Entity target);

void execute(World world, LivingEntity attacker, BlockPos pos);

int getCost();

default PlayerEntity convertToPlayer(LivingEntity entity) {
if (entity instanceof PlayerEntity) {
return (PlayerEntity) entity;
} else {
return null;
}
}
}

+ 357
- 0
src/main/java/com/thebrokenrail/reliccraft/data/Actions.java View File

@@ -0,0 +1,357 @@
package com.thebrokenrail.reliccraft.data;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.SpawnType;
import net.minecraft.entity.mob.ZombieEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class Actions {
private static final Map<String, Action> actions = new HashMap<>();

public static void register(String id, Action action) {
actions.put(id, action);
}

public static Action get(String id) {
return actions.get(id);
}

private static String getRandomAction(int budget, Random random) {
List<String> options = new ArrayList<>();

for (Map.Entry<String, Action> entry : actions.entrySet()) {
if (budget >= entry.getValue().getCost()) {
options.add(entry.getKey());
}
}

if (options.size() < 1) {
return null;
} else {
return options.get(random.nextInt(options.size()));
}
}

public static String[] getRandomActions(Random random) {
List<String> chosen = new ArrayList<>();
int amount = random.nextInt(3) + 1;
for (int i = 0; i < amount; i++) {
int budget = random.nextInt(100) + 1;
String action = getRandomAction(budget, random);
if (action != null) {
chosen.add(action);
}
}
return chosen.toArray(new String[0]);
}

public static class HalfHeartAction implements Action {
@Override
public int getCost() {
return 0;
}

@Override
public void execute(World world, LivingEntity attacker, Entity target) {
if (target instanceof LivingEntity) {
((LivingEntity) target).setHealth(1f);
}
}

@Override
public void execute(World world, LivingEntity attacker, BlockPos pos) {
}
}

public static class SwapBlockAction implements Action {
@Override
public void execute(World world, LivingEntity attacker, Entity target) {
execute(world, attacker, target.getBlockPos().down());
}

@Override
public void execute(World world, LivingEntity attacker, BlockPos pos) {
BlockState state1 = world.getBlockState(attacker.getBlockPos().down());
BlockState state2 = world.getBlockState(pos);
world.setBlockState(attacker.getBlockPos().down(), state2);
world.setBlockState(pos, state1);
}

@Override
public int getCost() {
return 0;
}
}

public static class DirtAction implements Action {
@Override
public int getCost() {
return 15;
}

@Override
public void execute(World world, LivingEntity attacker, Entity target) {
target.remove();
target.kill();
world.setBlockState(target.getBlockPos(), Blocks.DIRT.getDefaultState());
}

@Override
public void execute(World world, LivingEntity attacker, BlockPos pos) {
world.setBlockState(pos, Blocks.DIRT.getDefaultState());
}
}

public static class NetherAction implements Action {
@Override
public int getCost() {
return 25;
}

@Override
public void execute(World world, LivingEntity attacker, Entity target) {
BlockPos pos = target.getBlockPos();
BlockState state = world.getBlockState(pos);
world.setBlockState(pos, Blocks.NETHER_PORTAL.getDefaultState());
target.changeDimension(world.dimension.getType() == DimensionType.THE_NETHER ? DimensionType.OVERWORLD : DimensionType.THE_NETHER);
world.setBlockState(pos, state);
}

@Override
public void execute(World world, LivingEntity attacker, BlockPos pos) {
world.setBlockState(pos, Blocks.LAVA.getDefaultState());
}
}

public static class EndAction implements Action {
@Override
public int getCost() {
return 50;
}

@Override
public void execute(World world, LivingEntity attacker, Entity target) {
target.changeDimension(world.dimension.getType() == DimensionType.THE_END ? DimensionType.OVERWORLD : DimensionType.THE_END);
}

@Override
public void execute(World world, LivingEntity attacker, BlockPos pos) {
world.setBlockState(pos, Blocks.END_STONE.getDefaultState());
}
}

public static class DiamondAction extends ConversionAction {
@Override
public int getCost() {
return 99;
}

@Override
public Item getTargetItem() {
return Items.GOLD_INGOT;
}

@Override
public Item getConvertedItem() {
return Items.DIAMOND;
}

@Override
public Block getTargetBlock() {
return Blocks.GOLD_BLOCK;
}

@Override
public Block getConvertedBlock() {
return Blocks.DIAMOND_BLOCK;
}
}

public abstract static class ConversionAction implements Action {
@Override
public abstract int getCost();

public abstract Item getTargetItem();

public abstract Item getConvertedItem();

public abstract Block getTargetBlock();

public abstract Block getConvertedBlock();

@Override
public void execute(World world, LivingEntity attacker, Entity target) {
if (target instanceof PlayerEntity) {
PlayerEntity player = (PlayerEntity) target;
for (int i = 0; i < player.inventory.getInvSize(); i++) {
ItemStack stack = player.inventory.getInvStack(i);
if (stack.getItem() == getTargetItem()) {
player.inventory.setInvStack(i, new ItemStack(getConvertedItem(), stack.getCount()));
}
}
}
}

@Override
public void execute(World world, LivingEntity attacker, BlockPos pos) {
if (world.getBlockState(pos).getBlock() == getTargetBlock()) {
world.setBlockState(pos, getConvertedBlock().getDefaultState());
}
}
}

public static class GoldAction extends ConversionAction {
@Override
public int getCost() {
return 45;
}

@Override
public Item getTargetItem() {
return Items.COAL;
}

@Override
public Item getConvertedItem() {
return Items.GOLD_INGOT;
}

@Override
public Block getTargetBlock() {
return Blocks.COAL_BLOCK;
}

@Override
public Block getConvertedBlock() {
return Blocks.GOLD_BLOCK;
}
}

public static class BedrockAction implements Action {
@Override
public int getCost() {
return 60;
}

@Override
public void execute(World world, LivingEntity attacker, Entity target) {
target.remove();
target.kill();
world.setBlockState(target.getBlockPos(), Blocks.BEDROCK.getDefaultState());
}

@Override
public void execute(World world, LivingEntity attacker, BlockPos pos) {
world.setBlockState(pos, Blocks.BEDROCK.getDefaultState());
}
}

public static class HealAction implements Action {
@Override
public int getCost() {
return 0;
}

@Override
public void execute(World world, LivingEntity attacker, Entity target) {
if (target instanceof LivingEntity) {
((LivingEntity) target).heal(Float.MAX_VALUE);
}
}

@Override
public void execute(World world, LivingEntity attacker, BlockPos pos) {
}
}

public static class ZombifyAction implements Action {
@Override
public void execute(World world, LivingEntity attacker, Entity target) {
ZombieEntity zombie = new ZombieEntity(world);
zombie.updatePosition(target.getX(), target.getY(), target.getZ());
world.spawnEntity(zombie);
target.remove();
target.kill();
}

@Override
public void execute(World world, LivingEntity attacker, BlockPos pos) {
ZombieEntity zombie = new ZombieEntity(world);
zombie.updatePosition(attacker.getX(), attacker.getY(), attacker.getZ());
world.spawnEntity(zombie);
attacker.remove();
attacker.kill();
}

@Override
public int getCost() {
return 50;
}
}

public static class RandomAction implements Action {
@Override
public void execute(World world, LivingEntity attacker, Entity target) {
if (!target.removed) {
target.remove();
target.kill();
}
int entityID = new Random().nextInt(Registry.ENTITY_TYPE.getIds().size());
EntityType<?> entityType = Registry.ENTITY_TYPE.get(entityID);
if (entityType.isSummonable()) {
Entity entity = entityType.spawn(world, null, null, convertToPlayer(attacker), target.getBlockPos(), SpawnType.CONVERSION, false, false);
if (entity != null) {
entity.updatePosition(target.getX(), target.getY(), target.getZ());
} else {
execute(world, attacker, target);
}
} else {
execute(world, attacker, target);
}
}

@Override
public void execute(World world, LivingEntity attacker, BlockPos pos) {
int blockID = new Random().nextInt(Registry.BLOCK.getIds().size());
Block block = Registry.BLOCK.get(blockID);
world.setBlockState(pos, block.getDefaultState());
}

@Override
public int getCost() {
return 70;
}
}

static {
register("half_heart_action", new HalfHeartAction());
register("swap_block_action", new SwapBlockAction());
register("heal_action", new HealAction());
register("bedrock_action", new BedrockAction());
register("gold_action", new GoldAction());
register("diamond_action", new DiamondAction());
register("end_action", new EndAction());
register("nether_action", new NetherAction());
register("dirt_action", new DirtAction());
register("zombify_action", new ZombifyAction());
register("random_action", new RandomAction());
}
}

+ 63
- 0
src/main/java/com/thebrokenrail/reliccraft/data/RelicData.java View File

@@ -0,0 +1,63 @@
package com.thebrokenrail.reliccraft.data;

import java.util.Random;

public class RelicData {
public static class NameData {
public static final int VARIANT_MAX = 3;
public int variant = 0;
public static final int MAGIC_WORD_MAX = 7;
public int magicWord = 0;
}

public static final int[] COLORS = new int[]{
65535,
65280,
16776960,
16711935,
255,
16711680
};

public int color = COLORS[0];

public NameData name = new NameData();

public boolean enchantmentGlint = false;

public static final int MIN_DURABILITY = 20;
public static final int MAX_DURABILITY = 40;

public int maxDurability = 0;

public String[] attack = new String[0];

public static class UseData {
public enum Mode {
PROJECTILE,
TARGET,
SELF
}
public String[] actions = new String[0];
public Mode mode = Mode.SELF;
}

public UseData use = new UseData();

public static RelicData generate(Random random) {
RelicData data = new RelicData();
NameData name = new NameData();
name.variant = random.nextInt(NameData.VARIANT_MAX);
name.magicWord = random.nextInt(NameData.MAGIC_WORD_MAX);
data.name = name;
data.enchantmentGlint = random.nextBoolean();
data.maxDurability = random.nextInt(MAX_DURABILITY + 1) + MIN_DURABILITY;
data.attack = Actions.getRandomActions(random);
UseData use = new UseData();
use.mode = UseData.Mode.values()[random.nextInt(UseData.Mode.values().length)];
use.actions = Actions.getRandomActions(random);
data.use = use;
data.color = COLORS[random.nextInt(COLORS.length)];
return data;
}
}

+ 82
- 0
src/main/java/com/thebrokenrail/reliccraft/entity/RelicEntity.java View File

@@ -0,0 +1,82 @@
package com.thebrokenrail.reliccraft.entity;

import com.thebrokenrail.reliccraft.RelicCraft;
import com.thebrokenrail.reliccraft.data.Action;
import com.thebrokenrail.reliccraft.data.Actions;
import com.thebrokenrail.reliccraft.item.RelicItem;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.thrown.ThrownItemEntity;
import net.minecraft.item.Item;
import net.minecraft.network.Packet;
import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.world.World;

import java.util.List;
import java.util.Objects;

@SuppressWarnings("unused")
public class RelicEntity extends ThrownItemEntity {
public RelicEntity(EntityType<RelicEntity> entityType, World world) {
super(entityType, world);
}

public RelicEntity(World world, LivingEntity owner) {
super(RelicCraft.RELIC_ENTITY, owner, world);
}

public RelicEntity(World world, double x, double y, double z) {
super(RelicCraft.RELIC_ENTITY, x, y, z, world);
}

public RelicEntity(World world) {
super(RelicCraft.RELIC_ENTITY, world);
}

@Override
protected void onCollision(HitResult hitResult) {
if (!getEntityWorld().isClient()) {
String[] actions = RelicItem.getData(getItem()).use.actions;
String id = actions[random.nextInt(actions.length)];
Action action = Actions.get(id);
if (action != null) {
if (hitResult.getType() == HitResult.Type.BLOCK) {
BlockHitResult blockHitResult = (BlockHitResult) hitResult;
action.execute(getEntityWorld(), getOwner(), blockHitResult.getBlockPos());
} else if (hitResult.getType() == HitResult.Type.ENTITY) {
Entity entity = ((EntityHitResult) hitResult).getEntity();
action.execute(world, getOwner(), entity);
}
}
remove();
}
}

@Override
public void tick() {
super.tick();
if (!getEntityWorld().isClient()) {
List<ServerPlayerEntity> viewers = Objects.requireNonNull(getServer()).getPlayerManager().getPlayerList();
for (ServerPlayerEntity viewer : viewers) {
((ServerWorld) getEntityWorld()).spawnParticles(viewer, ParticleTypes.WITCH, true, getX(), getY(), getZ(), 8, 0.1d, 0.1d, 0.1d, 0d);
}
}
}

@Override
protected Item getDefaultItem() {
return RelicCraft.STAFF_ITEM;
}

@Override
public Packet<?> createSpawnPacket() {
return new EntitySpawnS2CPacket(this);
}
}

+ 221
- 0
src/main/java/com/thebrokenrail/reliccraft/item/RelicItem.java View File

@@ -0,0 +1,221 @@
package com.thebrokenrail.reliccraft.item;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.thebrokenrail.reliccraft.RelicCraft;
import com.thebrokenrail.reliccraft.data.Action;
import com.thebrokenrail.reliccraft.data.Actions;
import com.thebrokenrail.reliccraft.data.RelicData;
import com.thebrokenrail.reliccraft.entity.RelicEntity;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.BlockState;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Formatting;
import net.minecraft.util.Hand;
import net.minecraft.util.Rarity;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

import java.util.List;

public class RelicItem extends Item {
public RelicItem() {
super(new Settings().rarity(Rarity.UNCOMMON).maxDamage(1));
}

@Override
public Text getName(ItemStack stack) {
RelicData data = getData(stack);
return new TranslatableText("text." + RelicCraft.NAMESPACE + ".relic.title_variant." + data.name.variant, super.getName(stack), new TranslatableText("text." + RelicCraft.NAMESPACE + ".relic.magic_word." + data.name.magicWord));
}

public static RelicData getData(ItemStack stack) {
CompoundTag tag = stack.getTag();
if (tag == null) {
return new RelicData();
}

Moshi moshi = new Moshi.Builder().build();
JsonAdapter<RelicData> jsonAdapter = moshi.adapter(RelicData.class);

try {
return jsonAdapter.fromJson(tag.getString("RelicData"));
} catch (Throwable e) {
return new RelicData();
}
}

public int getMaxDamage(ItemStack stack) {
return getData(stack).maxDurability;
}

@Override