1.0
RelicCraft/pipeline/head This commit looks good Details

Initial Commit
This commit is contained in:
TheBrokenRail 2020-04-03 22:32:34 -04:00
commit c19790efc4
90 changed files with 3601 additions and 0 deletions

27
.gitignore vendored Normal file
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
CHANGELOG.md Normal file
View File

@ -0,0 +1,4 @@
# Changelog
**1.0**
* Initial Release

19
Jenkinsfile vendored Normal file
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
LICENSE Normal file
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
README.md Normal file
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
build.gradle Normal file
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
gradle.properties Normal file
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 vendored Normal file

Binary file not shown.

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
gradlew vendored Executable file
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
gradlew.bat vendored Normal file
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
settings.gradle Normal file
View File

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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
public boolean hasEnchantmentGlint(ItemStack stack) {
RelicData data = getData(stack);
return super.hasEnchantmentGlint(stack) || data.enchantmentGlint;
}
@Override
public boolean postHit(ItemStack stack, LivingEntity target, LivingEntity attacker) {
if (attacker instanceof PlayerEntity) {
RelicData data = getData(stack);
if (!attacker.getEntityWorld().isClient()) {
String id = data.attack[RANDOM.nextInt(data.attack.length)];
Action action = Actions.get(id);
action.execute(attacker.getEntityWorld(), attacker, target);
}
damage(stack, (PlayerEntity) attacker, Hand.MAIN_HAND);
return true;
} else {
return false;
}
}
@Override
public boolean canMine(BlockState state, World world, BlockPos pos, PlayerEntity miner) {
RelicData data = getData(miner.getMainHandStack());
if (!world.isClient()) {
String id = data.attack[RANDOM.nextInt(data.attack.length)];
Action action = Actions.get(id);
action.execute(miner.getEntityWorld(), miner, pos);
}
damage(miner.getMainHandStack(), miner, Hand.MAIN_HAND);
return false;
}
@Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
ItemStack stack = user.getStackInHand(hand);
RelicData data = getData(stack);
if (data.use.mode == RelicData.UseData.Mode.PROJECTILE) {
if (!world.isClient()) {
RelicEntity entity = new RelicEntity(world, user);
entity.setItem(stack);
entity.setProperties(user, user.pitch, user.yaw, 0.0f, 1.5f, 1.0f);
world.spawnEntity(entity);
}
damage(stack, user, hand);
return new TypedActionResult<>(ActionResult.SUCCESS, stack);
} else if (data.use.mode == RelicData.UseData.Mode.SELF) {
if (!world.isClient()) {
String id = data.use.actions[RANDOM.nextInt(data.use.actions.length)];
Action action = Actions.get(id);
action.execute(user.getEntityWorld(), user, user);
}
damage(stack, user, hand);
return new TypedActionResult<>(ActionResult.SUCCESS, stack);
} else {
return new TypedActionResult<>(ActionResult.PASS, stack);
}
}
@Override
public boolean useOnEntity(ItemStack stack, PlayerEntity user, LivingEntity entity, Hand hand) {
RelicData data = getData(stack);
if (data.use.mode == RelicData.UseData.Mode.TARGET) {
if (!user.getEntityWorld().isClient()) {
String id = data.use.actions[RANDOM.nextInt(data.use.actions.length)];
Action action = Actions.get(id);
action.execute(user.getEntityWorld(), user, entity);
}
damage(stack, user, hand);
return true;
} else {
return false;
}
}
@Override
public ActionResult useOnBlock(ItemUsageContext context) {
assert context.getPlayer() != null;
RelicData data = getData(context.getStack());
if (data.use.mode == RelicData.UseData.Mode.TARGET) {
if (!context.getWorld().isClient()) {
String id = data.use.actions[RANDOM.nextInt(data.use.actions.length)];
Action action = Actions.get(id);
action.execute(context.getPlayer().getEntityWorld(), context.getPlayer(), context.getBlockPos());
}
damage(context.getStack(), context.getPlayer(), context.getHand());
return ActionResult.SUCCESS;
} else {
return ActionResult.PASS;
}
}
@Override
public boolean canRepair(ItemStack stack, ItemStack ingredient) {
return ingredient.getItem() == Items.BLAZE_POWDER;
}
public static final String RELIC_REVEALED_KEY = "RelicRevealed";
@Environment(EnvType.CLIENT)
@Override
public void appendTooltip(ItemStack stack, World world, List<Text> tooltip, TooltipContext context) {
super.appendTooltip(stack, world, tooltip, context);
CompoundTag tag = stack.getTag();
if (tag == null) {
tag = new CompoundTag();
}
byte revealed = tag.getByte(RELIC_REVEALED_KEY);
if (revealed >= 2) {
RelicData data = getData(stack);
tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_attack").formatted(Formatting.WHITE));
for (String action : data.attack) {
tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_attack.action", new TranslatableText("text." + RelicCraft.NAMESPACE + ".relic.action." + action).formatted(Formatting.GRAY)));
}
tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_use").formatted(Formatting.WHITE));
tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_use.mode", new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_use.mode." + data.use.mode.name().toLowerCase()).formatted(Formatting.GRAY)).formatted(Formatting.WHITE));
tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_use.actions").formatted(Formatting.WHITE));
for (String action : data.use.actions) {
tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.on_use.actions.action", new TranslatableText("text." + RelicCraft.NAMESPACE + ".relic.action." + action).formatted(Formatting.GRAY)));
}
} else if (revealed == 1) {
tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.relic.not_crafted").formatted(Formatting.WHITE));
}
}
@Override
public void inventoryTick(ItemStack stack, World world, Entity entity, int slot, boolean selected) {
CompoundTag tag = stack.getTag();
if (tag == null) {
tag = new CompoundTag();
}
byte revealed = tag.getByte(RELIC_REVEALED_KEY);
if (revealed == 1) {
if (entity instanceof ServerPlayerEntity) {
RelicCraft.REVEAL_RELIC_CRITERION.trigger((ServerPlayerEntity) entity);
}
tag.putByte(RELIC_REVEALED_KEY, (byte) 2);
}
stack.setTag(tag);
}
private void damage(ItemStack stack, PlayerEntity player, Hand hand) {
stack.damage(RANDOM.nextInt(4) + 1, player, e -> e.sendToolBreakStatus(hand));
player.getItemCooldownManager().set(this, 10);
RelicCraft.playRelicSound(player);
}
}

View File

@ -0,0 +1,116 @@
package com.thebrokenrail.reliccraft.item;
import com.thebrokenrail.reliccraft.RelicCraft;
import com.thebrokenrail.reliccraft.block.AbstractDragonEggHolderBlock;
import com.thebrokenrail.reliccraft.block.TeleportationRestrictorBlock;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.LiteralText;
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.Identifier;
import net.minecraft.util.Language;
import net.minecraft.util.Rarity;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;
import java.util.List;
public class TargetedEnderPearlItem extends Item {
public TargetedEnderPearlItem() {
super(new Settings().rarity(Rarity.UNCOMMON).maxCount(16));
}
@Override
public boolean hasEnchantmentGlint(ItemStack stack) {
return true;
}
@Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
ItemStack stack = user.getStackInHand(hand);
if (!world.isClient()) {
RelicCraft.playRelicSound(user);
CompoundTag tag = stack.getTag();
if (tag == null) {
tag = new CompoundTag();
}
BlockPos target = new BlockPos(tag.getInt("TargetX"), tag.getInt("TargetY"), tag.getInt("TargetZ"));
Vec3d teleportTarget = new Vec3d(target.getX() + 0.5d, target.getY() + 1.0d, target.getZ() + 0.5d);
DimensionType dimension = DimensionType.byId(new Identifier(tag.getString("TargetDimension")));
if (user.dimension != dimension || dimension == null) {
user.sendMessage(new TranslatableText("chat." + RelicCraft.NAMESPACE + ".teleportation_beacon_in_different_dimension"));
} else {
if (((TeleportationRestrictorBlock.TeleportingEntity) user).cannotTeleport()) {
user.sendMessage(new TranslatableText("chat." + RelicCraft.NAMESPACE + ".teleportation_beacon_restricted"));
} else if (world.getBlockState(target).getBlock() != RelicCraft.TELEPORTATION_BEACON_BLOCK || !world.getBlockState(target).get(AbstractDragonEggHolderBlock.ACTIVE)) {
user.sendMessage(new TranslatableText("chat." + RelicCraft.NAMESPACE + ".missing_teleportation_beacon"));
} else {
Vec3d oldPos = user.getPos();
if (user.teleport(teleportTarget.getX(), teleportTarget.getY(), teleportTarget.getZ(), true)) {
world.playSound(null, oldPos.getX(), oldPos.getY(), oldPos.getZ(), SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT, SoundCategory.PLAYERS, 1.0f, 1.0f);
world.playSound(null, teleportTarget.getX(), teleportTarget.getY(), teleportTarget.getZ(), SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT, SoundCategory.PLAYERS, 1.0f, 1.0f);
RelicCraft.USE_TARGETED_ENDER_PEARL.trigger((ServerPlayerEntity) user);
user.damage(DamageSource.FALL, 16.0f);
user.fallDistance = 0f;
} else {
user.sendMessage(new TranslatableText("chat." + RelicCraft.NAMESPACE + ".teleportation_beacon_obstructed"));
}
}
}
}
if (!user.isCreative()) {
stack.decrement(1);
}
return new TypedActionResult<>(ActionResult.SUCCESS, stack);
}
@Override
@Environment(EnvType.CLIENT)
public void appendTooltip(ItemStack stack, World world, List<Text> tooltip, TooltipContext context) {
super.appendTooltip(stack, world, tooltip, context);
CompoundTag tag = stack.getTag();
if (tag == null) {
tag = new CompoundTag();
}
tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.targeted_ender_pearl.x", new LiteralText(String.valueOf(tag.getInt("TargetX"))).formatted(Formatting.GRAY)).formatted(Formatting.WHITE));
tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.targeted_ender_pearl.y", new LiteralText(String.valueOf(tag.getInt("TargetY"))).formatted(Formatting.GRAY)).formatted(Formatting.WHITE));
tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.targeted_ender_pearl.z", new LiteralText(String.valueOf(tag.getInt("TargetZ"))).formatted(Formatting.GRAY)).formatted(Formatting.WHITE));
Identifier id = new Identifier(tag.getString("TargetDimension"));
String key = "text." + RelicCraft.NAMESPACE + ".dimension." + id.getNamespace() + '.' + id.getPath();
Text dimensionText;
if (Language.getInstance().hasTranslation(key)) {
dimensionText = new TranslatableText(key);
} else {
dimensionText = new LiteralText(id.toString());
}
dimensionText.formatted(Formatting.GRAY);
tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.targeted_ender_pearl.dimension", dimensionText).formatted(Formatting.WHITE));
}
}

View File

@ -0,0 +1,92 @@
package com.thebrokenrail.reliccraft.item;
import com.thebrokenrail.reliccraft.RelicCraft;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
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.world.World;
import java.util.List;
public class TimeDilaterItem extends Item {
public enum TimeSpeed {
NORMAL,
FAST,
VERY_FAST
}
public interface DilatedWorld {
void setTimeSpeed(TimeSpeed speed);
TimeSpeed getTimeSpeed();
}
public TimeDilaterItem() {
super(new Settings().group(ItemGroup.MISC).maxDamage(9).rarity(Rarity.UNCOMMON));
}
@Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
ItemStack stack = user.getStackInHand(hand);
if (!world.isClient()) {
DilatedWorld dilatedWorld = (DilatedWorld) world;
switch (dilatedWorld.getTimeSpeed()) {
case FAST: {
dilatedWorld.setTimeSpeed(TimeSpeed.VERY_FAST);
break;
}
case VERY_FAST: {
dilatedWorld.setTimeSpeed(TimeSpeed.NORMAL);
break;
}
case NORMAL: {
dilatedWorld.setTimeSpeed(TimeSpeed.FAST);
break;
}
}
assert world.getServer() != null;
world.getServer().getPlayerManager().sendToAll(new TranslatableText("chat." + RelicCraft.NAMESPACE + ".announce_time_speed_change", user.getDisplayName(), new LiteralText("[").append(new TranslatableText("chat." + RelicCraft.NAMESPACE + ".announce_time_speed_change." + dilatedWorld.getTimeSpeed().name().toLowerCase())).append("]").formatted(Formatting.YELLOW)));
RelicCraft.DILATE_TIME_CRITERION.trigger((ServerPlayerEntity) user);
}
RelicCraft.playRelicSound(user);
stack.damage(1, user, e -> e.sendToolBreakStatus(hand));
return new TypedActionResult<>(ActionResult.SUCCESS, stack);
}
@Override
@Environment(EnvType.CLIENT)
public void appendTooltip(ItemStack stack, World world, List<Text> tooltip, TooltipContext context) {
super.appendTooltip(stack, world, tooltip, context);
if (world != null) {
tooltip.add(new TranslatableText("item." + RelicCraft.NAMESPACE + ".tooltip.time_dilater", new TranslatableText("chat." + RelicCraft.NAMESPACE + ".announce_time_speed_change." + ((DilatedWorld) world).getTimeSpeed().name().toLowerCase()).formatted(Formatting.GRAY)).formatted(Formatting.WHITE));
}
}
@Override
public void inventoryTick(ItemStack stack, World world, Entity entity, int slot, boolean selected) {
CompoundTag tag = stack.getTag();
if (tag == null) {
tag = new CompoundTag();
}
if (entity instanceof ServerPlayerEntity && tag.getByte("Artificial") == 1) {
RelicCraft.DUPLICATE_TIME_DILATER_CRITERION.trigger((ServerPlayerEntity) entity);
tag.putByte("Artificial", (byte) 2);
}
}
}

View File

@ -0,0 +1,14 @@
package com.thebrokenrail.reliccraft.mixin;
import net.minecraft.advancement.criterion.Criterion;
import net.minecraft.advancement.criterion.Criterions;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(Criterions.class)
public interface CriteriaRegistryHook {
@Invoker("register")
static <T extends Criterion<?>> T callRegister(T criterion) {
return criterion;
}
}

View File

@ -0,0 +1,46 @@
package com.thebrokenrail.reliccraft.mixin;
import com.thebrokenrail.reliccraft.RelicCraft;
import com.thebrokenrail.reliccraft.entity.RelicEntity;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@SuppressWarnings("unused")
@Environment(EnvType.CLIENT)
@Mixin(ClientPlayNetworkHandler.class)
public class MixinClientPlayNetworkHandler {
@Shadow
private ClientWorld world;
@Inject(method = "onEntitySpawn", at = @At(value = "TAIL"))
public void onEntitySpawn(EntitySpawnS2CPacket packet, CallbackInfo info) {
EntityType<?> entityType = packet.getEntityTypeId();
Entity entity = null;
if (entityType == RelicCraft.RELIC_ENTITY) {
entity = new RelicEntity(world, packet.getX(), packet.getY(), packet.getZ());
}
if (entity != null) {
double x = packet.getX();
double y = packet.getY();
double z = packet.getZ();
entity.updateTrackedPosition(x, y, z);
entity.pitch = (float) (packet.getPitch() * 360) / 250F;
entity.yaw = (float) (packet.getYaw() * 360) / 250F;
entity.setEntityId(packet.getId());
entity.setUuid(packet.getUuid());
world.addEntity(packet.getId(), entity);
}
}
}

View File

@ -0,0 +1,17 @@
package com.thebrokenrail.reliccraft.mixin;
import net.minecraft.entity.boss.dragon.EnderDragonFight;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@SuppressWarnings("unused")
@Mixin(EnderDragonFight.class)
public class MixinEnderDragonFight {
@SuppressWarnings("SameReturnValue")
@Redirect(at = @At(value = "FIELD", target = "Lnet/minecraft/entity/boss/dragon/EnderDragonFight;previouslyKilled:Z", opcode = Opcodes.GETFIELD), method = "dragonKilled")
public boolean forceDragonEggSpawn(EnderDragonFight enderDragonFight) {
return false;
}
}

View File

@ -0,0 +1,70 @@
package com.thebrokenrail.reliccraft.mixin;
import com.thebrokenrail.reliccraft.RelicCraft;
import com.thebrokenrail.reliccraft.block.AbstractDragonEggHolderBlock;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.EnderPearlItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;
import org.spongepowered.asm.mixin.Mixin;
import java.util.Objects;
@SuppressWarnings("unused")
@Mixin(EnderPearlItem.class)
public class MixinEnderPearlItem extends Item {
public MixinEnderPearlItem(Settings settings) {
super(settings);
}
@Override
public ActionResult useOnBlock(ItemUsageContext context) {
World world = context.getWorld();
BlockPos pos = context.getBlockPos();
String dimension = Objects.requireNonNull(DimensionType.getId(world.getDimension().getType())).toString();
BlockState state = world.getBlockState(pos);
PlayerEntity user = context.getPlayer();
if (!world.isClient()) {
assert user != null;
RelicCraft.playRelicSound(user);
}
if (user != null && state.getBlock() == RelicCraft.TELEPORTATION_BEACON_BLOCK && state.get(AbstractDragonEggHolderBlock.ACTIVE)) {
CompoundTag tag = new CompoundTag();
tag.putInt("TargetX", pos.getX());
tag.putInt("TargetY", pos.getY());
tag.putInt("TargetZ", pos.getZ());
tag.putString("TargetDimension", dimension);
ItemStack itemStack = new ItemStack(RelicCraft.TARGETED_ENDER_PEARL_ITEM);
itemStack.setTag(tag);
ItemStack itemStack2 = user.getStackInHand(context.getHand());
if (!user.isCreative()) {
itemStack2.decrement(1);
}
if (!user.inventory.insertStack(itemStack.copy())) {
user.dropItem(itemStack, false);
}
if (!world.isClient()) {
RelicCraft.USE_TELEPORTATION_BEACON_CRITERION.trigger((ServerPlayerEntity) user);
}
return ActionResult.SUCCESS;
} else {
return ActionResult.PASS;
}
}
}

View File

@ -0,0 +1,33 @@
package com.thebrokenrail.reliccraft.mixin;
import com.thebrokenrail.reliccraft.block.TeleportationRestrictorBlock;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@SuppressWarnings("unused")
@Mixin(Entity.class)
public class MixinEntity implements TeleportationRestrictorBlock.TeleportingEntity {
@Unique
private int teleportCooldown = 0;
@Override
public void resetTeleportCooldown() {
teleportCooldown = 5;
}
@Inject(at = @At("HEAD"), method = "tick")
public void tick(CallbackInfo info) {
if (teleportCooldown > 0) {
teleportCooldown--;
}
}
@Override
public boolean cannotTeleport() {
return teleportCooldown > 0;
}
}

View File

@ -0,0 +1,19 @@
package com.thebrokenrail.reliccraft.mixin;
import com.thebrokenrail.reliccraft.item.RelicItem;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@SuppressWarnings("unused")
@Mixin(ItemStack.class)
public class MixinItemStack {
@Inject(at = @At("HEAD"), method = "getMaxDamage", cancellable = true)
public void getMaxDamage(CallbackInfoReturnable<Integer> info) {
if (((ItemStack) (Object) this).getItem() instanceof RelicItem) {
info.setReturnValue(((RelicItem) ((ItemStack) (Object) this).getItem()).getMaxDamage((ItemStack) (Object) this));
}
}
}

View File

@ -0,0 +1,41 @@
package com.thebrokenrail.reliccraft.mixin;
import com.mojang.datafixers.DataFixer;
import com.thebrokenrail.reliccraft.item.TimeDilaterItem;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.LevelProperties;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@SuppressWarnings("unused")
@Mixin(LevelProperties.class)
public class MixinLevelProperties implements TimeDilaterItem.DilatedWorld {
@Unique
private TimeDilaterItem.TimeSpeed timeSpeed = TimeDilaterItem.TimeSpeed.NORMAL;
@Inject(at = @At("RETURN"), method = "<init>(Lnet/minecraft/nbt/CompoundTag;Lcom/mojang/datafixers/DataFixer;ILnet/minecraft/nbt/CompoundTag;)V")
public void init(CompoundTag compoundTag, DataFixer dataFixer, int i, CompoundTag compoundTag2, CallbackInfo info) {
try {
timeSpeed = TimeDilaterItem.TimeSpeed.valueOf(compoundTag.getString("RelicCraftTimeSpeed"));
} catch (IllegalArgumentException ignored) {
}
}
@Inject(at = @At("RETURN"), method = "updateProperties")
public void updateProperties(CompoundTag levelTag, CompoundTag playerTag, CallbackInfo ci) {
levelTag.putString("RelicCraftTimeSpeed", timeSpeed.name());
}
@Override
public TimeDilaterItem.TimeSpeed getTimeSpeed() {
return timeSpeed;
}
@Override
public void setTimeSpeed(TimeDilaterItem.TimeSpeed timeSpeed) {
this.timeSpeed = timeSpeed;
}
}

View File

@ -0,0 +1,18 @@
package com.thebrokenrail.reliccraft.mixin;
import net.minecraft.entity.LivingEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@SuppressWarnings("unused")
@Mixin(LivingEntity.class)
public class MixinLivingEntity extends MixinEntity {
@Inject(at = @At("HEAD"), method = "teleport", cancellable = true)
public void teleport(double x, double y, double z, boolean particleEffects, CallbackInfoReturnable<Boolean> info) {
if (cannotTeleport()) {
info.setReturnValue(false);
}
}
}

View File

@ -0,0 +1,27 @@
package com.thebrokenrail.reliccraft.mixin;
import com.mojang.brigadier.CommandDispatcher;
import com.thebrokenrail.reliccraft.RelicCraft;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.LocateCommand;
import net.minecraft.server.command.ServerCommandSource;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@SuppressWarnings("unused")
@Mixin(LocateCommand.class)
public abstract class MixinLocateCommand {
@Shadow
private static int execute(ServerCommandSource source, String structure) {
throw new UnsupportedOperationException();
}
@Inject(method = "register", at = @At(value = "RETURN"))
private static void onRegister(CommandDispatcher<ServerCommandSource> dispatcher, CallbackInfo info) {
dispatcher.register(CommandManager.literal("locate").requires(source -> source.hasPermissionLevel(2))
.then(CommandManager.literal("RelicCraft_Time_Temple").executes(ctx -> execute(ctx.getSource(), RelicCraft.TIME_TEMPLE_ID))));
}
}

View File

@ -0,0 +1,16 @@
package com.thebrokenrail.reliccraft.mixin;
import net.minecraft.item.Item;
import net.minecraft.item.NetherStarItem;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
@SuppressWarnings("unused")
@Mixin(NetherStarItem.class)
public class MixinNetherStarItem {
@ModifyVariable(at = @At("HEAD"), method = "<init>", argsOnly = true)
private static Item.Settings init(Item.Settings settings) {
return settings.maxDamage(6);
}
}

View File

@ -0,0 +1,19 @@
package com.thebrokenrail.reliccraft.mixin;
import com.thebrokenrail.reliccraft.packet.UpdateTimeDilationS2CPacket;
import net.minecraft.server.world.ServerWorld;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.function.BooleanSupplier;
@SuppressWarnings("unused")
@Mixin(ServerWorld.class)
public abstract class MixinServerWorld extends MixinWorld {
@Inject(at = @At("RETURN"), method = "tick")
public void tick(BooleanSupplier shouldKeepTicking, CallbackInfo info) {
UpdateTimeDilationS2CPacket.send((ServerWorld) (Object) this, getTimeSpeed());
}
}

View File

@ -0,0 +1,23 @@
package com.thebrokenrail.reliccraft.mixin;
import com.thebrokenrail.reliccraft.block.TeleportationRestrictorBlock;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.thrown.ThrownEnderpearlEntity;
import net.minecraft.util.hit.HitResult;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@SuppressWarnings("unused")
@Mixin(ThrownEnderpearlEntity.class)
public class MixinThrownEnderpearlEntity {
@Inject(at = @At("HEAD"), method = "onCollision", cancellable = true)
public void onCollision(HitResult hitResult, CallbackInfo info) {
LivingEntity owner = ((ThrownEnderpearlEntity) (Object) this).getOwner();
if (owner != null && ((TeleportationRestrictorBlock.TeleportingEntity) owner).cannotTeleport()) {
((ThrownEnderpearlEntity) (Object) this).remove();
info.cancel();
}
}
}

View File

@ -0,0 +1,50 @@
package com.thebrokenrail.reliccraft.mixin;
import com.thebrokenrail.reliccraft.item.TimeDilaterItem;
import net.minecraft.world.World;
import net.minecraft.world.level.LevelProperties;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.ModifyConstant;
@SuppressWarnings("unused")
@Mixin(World.class)
public abstract class MixinWorld implements TimeDilaterItem.DilatedWorld {
@Shadow
public abstract boolean isClient();
@Shadow
@Final
protected LevelProperties properties;
@Shadow
public abstract long getTime();
@ModifyConstant(constant = @Constant(longValue = 1L), method = "tickTime")
public long tickTime(long value) {
switch (getTimeSpeed()) {
case FAST: {
return value * 4L;
}
case VERY_FAST: {
return value * 8L;
}
default:
case NORMAL: {
return value;
}
}
}
@Override
public void setTimeSpeed(TimeDilaterItem.TimeSpeed timeSpeed) {
((TimeDilaterItem.DilatedWorld) properties).setTimeSpeed(timeSpeed);
}
@Override
public TimeDilaterItem.TimeSpeed getTimeSpeed() {
return ((TimeDilaterItem.DilatedWorld) properties).getTimeSpeed();
}
}

View File

@ -0,0 +1,39 @@
package com.thebrokenrail.reliccraft.packet;
import com.thebrokenrail.reliccraft.RelicCraft;
import com.thebrokenrail.reliccraft.item.TimeDilaterItem;
import io.netty.buffer.Unpooled;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.network.PacketContext;
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.Packet;
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
import net.minecraft.world.World;
@SuppressWarnings("unused")
public class UpdateTimeDilationS2CPacket {
public static void send(World world, TimeDilaterItem.TimeSpeed speed) {
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
buf.writeString(speed.name());
Packet<?> packet = new CustomPayloadS2CPacket(new Identifier(RelicCraft.NAMESPACE, "update_time_dilation"), buf);
for (PlayerEntity player : world.getPlayers()) {
ServerSidePacketRegistry.INSTANCE.sendToPlayer(player, packet);
}
}
@Environment(EnvType.CLIENT)
public static void handle(PacketContext context, PacketByteBuf buf) {
TimeDilaterItem.TimeSpeed speed = TimeDilaterItem.TimeSpeed.valueOf(buf.readString());
MinecraftClient client = MinecraftClient.getInstance();
assert client.world != null;
((TimeDilaterItem.DilatedWorld) client.world).setTimeSpeed(speed);
}
}

View File

@ -0,0 +1,102 @@
package com.thebrokenrail.reliccraft.recipe;
import com.thebrokenrail.reliccraft.RelicCraft;
import com.thebrokenrail.reliccraft.item.RelicItem;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.SpecialCraftingRecipe;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
import java.util.Random;
public class RevealRelicRecipe extends SpecialCraftingRecipe {
public RevealRelicRecipe(Identifier id) {
super(id);
}
public boolean matches(CraftingInventory craftingInventory, World world) {
ItemStack itemStack = ItemStack.EMPTY;
int netherStar = 0;
for (int i = 0; i < craftingInventory.getInvSize(); ++i) {
ItemStack itemStack2 = craftingInventory.getInvStack(i);
if (!itemStack2.isEmpty()) {
if (itemStack2.getItem() instanceof RelicItem) {
if (!itemStack.isEmpty()) {
return false;
}
itemStack = itemStack2;
} else if (itemStack2.getItem() == Items.NETHER_STAR) {
netherStar++;
} else {
return false;
}
}
}
return !itemStack.isEmpty() && netherStar == 1;
}
public ItemStack craft(CraftingInventory craftingInventory) {
ItemStack itemStack = ItemStack.EMPTY;
for (int i = 0; i < craftingInventory.getInvSize(); i++) {
ItemStack itemStack2 = craftingInventory.getInvStack(i);
if (!itemStack2.isEmpty()) {
Item item = itemStack2.getItem();
if (item instanceof RelicItem) {
if (!itemStack.isEmpty()) {
return ItemStack.EMPTY;
}
itemStack = itemStack2.copy();
break;
}
}
}
if (!itemStack.isEmpty()) {
CompoundTag tag = itemStack.getTag();
if (tag == null) {
tag = new CompoundTag();
}
tag.putByte(RelicItem.RELIC_REVEALED_KEY, (byte) 1);
itemStack.setTag(tag);
return itemStack;
} else {
return ItemStack.EMPTY;
}
}
@Environment(EnvType.CLIENT)
public boolean fits(int width, int height) {
return width * height >= 2;
}
public RecipeSerializer<?> getSerializer() {
return RelicCraft.REVEAL_RELIC_RECIPE;
}
@Override
public DefaultedList<ItemStack> getRemainingStacks(CraftingInventory inventory) {
DefaultedList<ItemStack> defaultedList = DefaultedList.ofSize(inventory.getInvSize(), ItemStack.EMPTY);
for (int i = 0; i < defaultedList.size(); i++) {
ItemStack stack = inventory.getInvStack(i);
if (stack.getItem().hasRecipeRemainder()) {
defaultedList.set(i, new ItemStack(stack.getItem().getRecipeRemainder()));
} else if (stack.getItem() == Items.NETHER_STAR && !stack.damage(1, new Random(), null)) {
defaultedList.set(i, stack.copy());
}
}
return defaultedList;
}
}

View File

@ -0,0 +1,51 @@
package com.thebrokenrail.reliccraft.recipe;
import com.thebrokenrail.reliccraft.RelicCraft;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.recipe.Ingredient;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.ShapelessRecipe;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Identifier;
import java.util.Random;
public class TimeDilaterRecipe extends ShapelessRecipe {
private static final DefaultedList<Ingredient> INGREDIENTS;
private static final ItemStack OUTPUT;
static {
INGREDIENTS = DefaultedList.of();
INGREDIENTS.add(Ingredient.ofItems(Items.NETHER_STAR));
INGREDIENTS.add(Ingredient.ofItems(RelicCraft.TIME_DILATER_ITEM));
INGREDIENTS.add(Ingredient.ofItems(Items.CLOCK));
OUTPUT = new ItemStack(RelicCraft.TIME_DILATER_ITEM);
CompoundTag tag = new CompoundTag();
tag.putByte("Artificial", (byte) 1);
OUTPUT.setTag(tag);
}
public TimeDilaterRecipe(Identifier id) {
super(id, "", OUTPUT, INGREDIENTS);
}
public RecipeSerializer<?> getSerializer() {
return RelicCraft.TIME_DILATER_RECIPE;
}
@Override
public DefaultedList<ItemStack> getRemainingStacks(CraftingInventory inventory) {
DefaultedList<ItemStack> defaultedList = DefaultedList.ofSize(inventory.getInvSize(), ItemStack.EMPTY);
for (int i = 0; i < defaultedList.size(); i++) {
ItemStack stack = inventory.getInvStack(i);
if (stack.getItem() == Items.NETHER_STAR && !stack.damage(1, new Random(), null) || stack.getItem() == RelicCraft.TIME_DILATER_ITEM) {
defaultedList.set(i, stack.copy());
}
}
return defaultedList;
}
}

View File

@ -0,0 +1,34 @@
package com.thebrokenrail.reliccraft.structure;
import com.mojang.datafixers.Dynamic;
import com.thebrokenrail.reliccraft.RelicCraft;
import net.minecraft.world.gen.feature.AbstractTempleFeature;
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import java.util.function.Function;
public class TimeTempleFeature extends AbstractTempleFeature<DefaultFeatureConfig> {
public TimeTempleFeature(Function<Dynamic<?>, ? extends DefaultFeatureConfig> configFactory) {
super(configFactory);
}
@Override
protected int getSeedModifier() {
return 0;
}
@Override
public StructureStartFactory getStructureStartFactory() {
return TimeTempleStructureStart::new;
}
@Override
public String getName() {
return RelicCraft.TIME_TEMPLE_ID;
}
@Override
public int getRadius() {
return 8;
}
}

View File

@ -0,0 +1,127 @@
package com.thebrokenrail.reliccraft.structure;
import com.thebrokenrail.reliccraft.RelicCraft;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.state.property.Property;
import net.minecraft.structure.SimpleStructurePiece;
import net.minecraft.structure.Structure;
import net.minecraft.structure.StructureManager;
import net.minecraft.structure.StructurePiece;
import net.minecraft.structure.StructurePlacementData;
import net.minecraft.structure.processor.BlockIgnoreStructureProcessor;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.Heightmap;
import net.minecraft.world.IWorld;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import java.util.Collection;
import java.util.List;
import java.util.Random;
public class TimeTempleGenerator {
public static void addPieces(StructureManager structureManager, BlockPos blockPos, BlockRotation rotation, List<StructurePiece> list) {
list.add(new Piece(structureManager, new Identifier(RelicCraft.NAMESPACE, "time_temple"), blockPos, rotation));
}
public static class Piece extends SimpleStructurePiece {
private final Identifier template;
private final BlockRotation rotation;
public Piece(StructureManager manager, Identifier identifier, BlockPos pos, BlockRotation rotation) {
super(RelicCraft.TIME_TEMPLE_STRUCTURE_PIECE, 0);
this.template = identifier;
this.pos = pos;
this.rotation = rotation;
initializeStructureData(manager);
}
public Piece(StructureManager manager, CompoundTag tag) {
super(RelicCraft.TIME_TEMPLE_STRUCTURE_PIECE, tag);
template = new Identifier(tag.getString("Template"));
rotation = BlockRotation.valueOf(tag.getString("Rot"));
initializeStructureData(manager);
}
private void initializeStructureData(StructureManager manager) {
Structure structure = manager.getStructureOrBlank(template);
StructurePlacementData structurePlacementData = new StructurePlacementData().setRotation(rotation).setMirrored(BlockMirror.NONE).setIgnoreEntities(true).addProcessor(BlockIgnoreStructureProcessor.IGNORE_STRUCTURE_BLOCKS);
setStructureData(structure, pos, structurePlacementData);
}
@Override
protected void toNbt(CompoundTag tag) {
super.toNbt(tag);
tag.putString("Template", template.toString());
tag.putString("Rot", rotation.name());
}
@Override
public boolean generate(IWorld world, ChunkGenerator<?> generator, Random random, BlockBox box, ChunkPos chunkPos) {
int yHeight = 0;
int area = 0;
for (int x = getBoundingBox().minX; x <= getBoundingBox().maxX; x++) {
for (int z = getBoundingBox().minZ; z <= getBoundingBox().maxZ; z++) {
yHeight = yHeight + world.getTopY(Heightmap.Type.WORLD_SURFACE_WG, x, z);
area++;
}
}
yHeight = yHeight / area;
BlockPos originalPos = pos;
pos = pos.add(0, yHeight - 90, 0);
boolean result = super.generate(world, generator, random, box, chunkPos);
if (result) {
for (int x = getBoundingBox().minX; x <= getBoundingBox().maxX; x++) {
for (int y = getBoundingBox().minY; y <= getBoundingBox().maxY; y++) {
for (int z = getBoundingBox().minZ; z <= getBoundingBox().maxZ; z++) {
BlockPos blockPos = new BlockPos(x, y, z);
if (box.contains(blockPos)) {
BlockState state = world.getBlockState(blockPos);
boolean damaged = random.nextFloat() < 0.6f;
if (damaged) {
if (state.getBlock() == Blocks.STONE_BRICKS) {
boolean mossy = random.nextFloat() < 0.5f;
world.setBlockState(blockPos, convertState(state, mossy ? Blocks.MOSSY_STONE_BRICKS : Blocks.CRACKED_STONE_BRICKS), 3);
} else if (world.getBlockState(blockPos).getBlock() == Blocks.STONE_BRICK_STAIRS) {
world.setBlockState(blockPos, convertState(state, Blocks.MOSSY_STONE_BRICK_STAIRS), 3);
} else if (world.getBlockState(blockPos).getBlock() == Blocks.STONE_BRICK_SLAB) {
world.setBlockState(blockPos, convertState(state, Blocks.MOSSY_STONE_BRICK_SLAB), 3);
}
}
}
}
}
}
}
pos = originalPos;
return result;
}
private BlockState convertState(BlockState oldState, Block newBlock) {
BlockState newState = newBlock.getDefaultState();
Collection<Property<?>> properties = oldState.getProperties();
//noinspection rawtypes
for (Property property : properties) {
//noinspection unchecked
newState = newState.with(property, oldState.get(property));
}
return newState;
}
@Override
protected void handleMetadata(String metadata, BlockPos pos, IWorld world, Random random, BlockBox boundingBox) {
}
}
}

View File

@ -0,0 +1,26 @@
package com.thebrokenrail.reliccraft.structure;
import net.minecraft.structure.StructureManager;
import net.minecraft.structure.StructureStart;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.feature.StructureFeature;
public class TimeTempleStructureStart extends StructureStart {
public TimeTempleStructureStart(StructureFeature<?> feature, int chunkX, int chunkZ, BlockBox box, int references, long l) {
super(feature, chunkX, chunkZ, box, references, l);
}
@Override
public void initialize(ChunkGenerator<?> chunkGenerator, StructureManager structureManager, int x, int z, Biome biome) {
int i = x * 16;
int j = z * 16;
BlockPos blockPos = new BlockPos(i, 90, j);
BlockRotation blockRotation = BlockRotation.values()[random.nextInt(BlockRotation.values().length)];
TimeTempleGenerator.addPieces(structureManager, blockPos, blockRotation, children);
setBoundingBoxFromChildren();
}
}

View File

@ -0,0 +1,10 @@
{
"variants": {
"active=false": {
"model": "reliccraft:block/teleportation_beacon"
},
"active=true": {
"model": "reliccraft:block/active_teleportation_beacon"
}
}
}

View File

@ -0,0 +1,10 @@
{
"variants": {
"active=false": {
"model": "reliccraft:block/teleportation_restrictor"
},
"active=true": {
"model": "reliccraft:block/active_teleportation_restrictor"
}
}
}

View File

@ -0,0 +1,67 @@
{
"text.reliccraft.relic.title_variant.0": "The %s of %s",
"text.reliccraft.relic.title_variant.1": "%s of %s",
"text.reliccraft.relic.title_variant.2": "The %s %s",
"text.reliccraft.relic.magic_word.0": "Solarus",
"text.reliccraft.relic.magic_word.1": "Galagus",
"text.reliccraft.relic.magic_word.2": "Galactus",
"text.reliccraft.relic.magic_word.3": "Galagon",
"text.reliccraft.relic.magic_word.4": "Extremus",
"text.reliccraft.relic.magic_word.5": "Enchantus",
"text.reliccraft.relic.magic_word.6": "Magicus",
"item.reliccraft.orb": "Orb",
"item.reliccraft.staff": "Staff",
"item.reliccraft.targeted_ender_pearl": "Targeted Ender Pearl",
"item.reliccraft.time_dilater": "Time Dilater",
"chat.reliccraft.announce_time_speed_change": "%s has dilated the world's speed to %s",
"chat.reliccraft.announce_time_speed_change.fast": "Fast",
"chat.reliccraft.announce_time_speed_change.very_fast": "Very Fast",
"chat.reliccraft.announce_time_speed_change.normal": "Normal",
"chat.reliccraft.missing_teleportation_beacon": "Your Teleportation Beacon has been deactivated or destroyed",
"chat.reliccraft.teleportation_beacon_obstructed": "Your Teleportation Beacon is obstructed",
"chat.reliccraft.teleportation_beacon_restricted": "A Teleportation Restrictor is im effect",
"chat.reliccraft.teleportation_beacon_in_different_dimension": "Your Teleportation Beacon is in a different dimension",
"item.reliccraft.tooltip.relic.on_use": "On Use:",
"item.reliccraft.tooltip.relic.on_use.mode": " Mode: %s",
"item.reliccraft.tooltip.relic.on_use.mode.projectile": "Shoot Projectile",
"item.reliccraft.tooltip.relic.on_use.mode.target": "Use On Target",
"item.reliccraft.tooltip.relic.on_use.mode.self": "Use On Self",
"item.reliccraft.tooltip.relic.on_use.actions": " Actions:",
"item.reliccraft.tooltip.relic.on_use.actions.action": " %s",
"item.reliccraft.tooltip.relic.on_attack": "On Attack:",
"item.reliccraft.tooltip.relic.on_attack.action": " %s",
"item.reliccraft.tooltip.relic.not_crafted": "Craft To Reveal Secrets",
"item.reliccraft.tooltip.time_dilater": "Current Time Dilation: %s",
"item.reliccraft.tooltip.targeted_ender_pearl.x": "X: %s",
"item.reliccraft.tooltip.targeted_ender_pearl.y": "Y: %s",
"item.reliccraft.tooltip.targeted_ender_pearl.z": "Z: %s",
"item.reliccraft.tooltip.targeted_ender_pearl.dimension": "Dimension: %s",
"text.reliccraft.relic.action.heal_action": "Heal",
"text.reliccraft.relic.action.bedrock_action": "Turn To Bedrock",
"text.reliccraft.relic.action.gold_action": "Turn Coal To Gold",
"text.reliccraft.relic.action.diamond_action": "Turn Gold To Diamond",
"text.reliccraft.relic.action.end_action": "Go To The End",
"text.reliccraft.relic.action.nether_action": "Go To The Nether",
"text.reliccraft.relic.action.dirt_action": "Turn To Dirt",
"text.reliccraft.relic.action.zombify_action": "Zombify",
"text.reliccraft.relic.action.random_action": "Randomize",
"text.reliccraft.relic.action.half_heart_action": "Half-Heart",
"text.reliccraft.relic.action.swap_block_action": "Swap Blocks",
"block.reliccraft.teleportation_restrictor": "Teleportation Restrictor",
"block.reliccraft.teleportation_beacon": "Teleportation Beacon",
"advancements.reliccraft.root.title": "RelicCraft",
"advancements.reliccraft.root.description": "Explore Ancient Relics and Magic!",
"advancements.reliccraft.activate_teleportation_restrictor.title": "Teleportation Ban",
"advancements.reliccraft.activate_teleportation_restrictor.description": "Activate a Teleportation Restrictor with a Dragon Egg",
"advancements.reliccraft.activate_teleportation_beacon.title": "Teleportation Master",
"advancements.reliccraft.activate_teleportation_beacon.description": "Activate a Teleportation Beacon with a Dragon Egg, then create a Targeted Ender Pearl by using an Ender Pearl on it, and then finally use the Targeted Ender Pearl",
"advancements.reliccraft.reveal_relic.title": "Master Archaeologist",
"advancements.reliccraft.reveal_relic.description": "Combine a Relic with a Nether Star",
"advancements.reliccraft.dilate_time.title": "Time Master",
"advancements.reliccraft.dilate_time.description": "Use a Time Dilater",
"advancements.reliccraft.duplicate_time_dilater.title": "Time Lord",
"advancements.reliccraft.duplicate_time_dilater.description": "Duplicate a Time Dilater",
"text.reliccraft.dimension.minecraft.overworld": "The Overworld",
"text.reliccraft.dimension.minecraft.the_nether": "The Nether",
"text.reliccraft.dimension.minecraft.the_end": "The End"
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "reliccraft:block/active_teleportation_beacon"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "reliccraft:block/active_teleportation_restrictor"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "reliccraft:block/teleportation_beacon"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "reliccraft:block/teleportation_restrictor"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "reliccraft:item/orb"
}
}

View File

@ -0,0 +1,7 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "reliccraft:item/staff_orb",
"layer1": "reliccraft:item/staff_handle"
}
}

View File

@ -0,0 +1,3 @@
{
"parent": "minecraft:item/ender_pearl"
}

View File

@ -0,0 +1,11 @@
{
"parent": "reliccraft:block/teleportation_beacon",
"overrides": [
{
"predicate": {
"custom_model_data": 1
},
"model": "reliccraft:block/active_teleportation_beacon"
}
]
}

View File

@ -0,0 +1,11 @@
{
"parent": "reliccraft:block/teleportation_restrictor",
"overrides": [
{
"predicate": {
"custom_model_data": 1
},
"model": "reliccraft:block/active_teleportation_restrictor"
}
]
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "reliccraft:item/time_dilater"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

View File

@ -0,0 +1,33 @@
{
"parent": "reliccraft:root",
"display": {
"icon": {
"item": "reliccraft:teleportation_beacon",
"nbt": "{CustomModelData: 1}"
},
"title": {
"translate": "advancements.reliccraft.activate_teleportation_beacon.title"
},
"description": {
"translate": "advancements.reliccraft.activate_teleportation_beacon.description"
},
"frame": "challenge",
"show_toast": true,
"announce_to_chat": true,
"hidden": false
},
"criteria": {
"activate": {
"trigger": "reliccraft:activate_teleportation_beacon"
},
"create_pearl": {
"trigger": "reliccraft:use_teleportation_beacon"
},
"use_pearl": {
"trigger": "reliccraft:use_targeted_ender_pearl"
}
},
"rewards": {
"experience": 100
}
}

View File

@ -0,0 +1,27 @@
{
"parent": "reliccraft:root",
"display": {
"icon": {
"item": "reliccraft:teleportation_restrictor",
"nbt": "{CustomModelData: 1}"
},
"title": {
"translate": "advancements.reliccraft.activate_teleportation_restrictor.title"
},
"description": {
"translate": "advancements.reliccraft.activate_teleportation_restrictor.description"
},
"frame": "challenge",
"show_toast": true,
"announce_to_chat": true,
"hidden": false
},
"criteria": {
"activate": {
"trigger": "reliccraft:activate_teleportation_restrictor"
}
},
"rewards": {
"experience": 100
}
}

View File

@ -0,0 +1,28 @@
{
"parent": "reliccraft:root",
"display": {
"icon": {
"item": "reliccraft:time_dilater"
},
"title": {
"translate": "advancements.reliccraft.dilate_time.title"
},
"description": {
"translate": "advancements.reliccraft.dilate_time.description"
},
"frame": "task",
"show_toast": true,
"announce_to_chat": true,
"hidden": false
},
"criteria": {
"dilate_time": {
"trigger": "reliccraft:dilate_time"
}
},
"rewards": {
"recipes": [
"sorcerycraft:time_dilater"
]
}
}

View File

@ -0,0 +1,26 @@
{
"parent": "reliccraft:dilate_time",
"display": {
"icon": {
"item": "reliccraft:time_dilater"
},
"title": {
"translate": "advancements.reliccraft.duplicate_time_dilater.title"
},
"description": {
"translate": "advancements.reliccraft.duplicate_time_dilater.description"
},
"frame": "challenge",
"show_toast": true,
"announce_to_chat": true,
"hidden": false
},
"criteria": {
"duplicate_time_dilater": {
"trigger": "reliccraft:duplicate_time_dilater"
}
},
"rewards": {
"experience": 100
}
}

View File

@ -0,0 +1,26 @@
{
"parent": "reliccraft:root",
"display": {
"icon": {
"item": "minecraft:nether_star"
},
"title": {
"translate": "advancements.reliccraft.reveal_relic.title"
},
"description": {
"translate": "advancements.reliccraft.reveal_relic.description"
},
"frame": "challenge",
"show_toast": true,
"announce_to_chat": true,
"hidden": false
},
"criteria": {
"reveal_relic": {
"trigger": "reliccraft:reveal_relic"
}
},
"rewards": {
"experience": 100
}
}

View File

@ -0,0 +1,36 @@
{
"display": {
"icon": {
"item": "minecraft:ender_chest"
},
"title": {
"translate": "advancements.reliccraft.root.title"
},
"description": {
"translate": "advancements.reliccraft.root.description"
},
"frame": "task",
"show_toast": false,
"announce_to_chat": false,
"hidden": false,
"background": "minecraft:textures/gui/advancements/backgrounds/stone.png"
},
"criteria": {
"obtain_relic": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"tag": "reliccraft:relics"
}
]
}
}
},
"rewards": {
"recipes": [
"reliccraft:teleportation_restrictor",
"reliccraft:teleportation_beacon"
]
}
}

View File

@ -0,0 +1,19 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "reliccraft:teleportation_beacon"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}

View File

@ -0,0 +1,19 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "reliccraft:teleportation_restrictor"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}

View File

@ -0,0 +1,3 @@
{
"type": "reliccraft:reveal_relic"
}

View File

@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"BIB",
"ISI",
"BIB"
],
"key": {
"B": {
"item": "minecraft:blaze_powder"
},
"S": {
"item": "minecraft:nether_star"
},
"I": {
"item": "minecraft:iron_ingot"
}
},
"result": {
"item": "reliccraft:teleportation_beacon"
}
}

View File

@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"OIO",
"ISI",
"OIO"
],
"key": {
"O": {
"item": "minecraft:obsidian"
},
"S": {
"item": "minecraft:nether_star"
},
"I": {
"item": "minecraft:iron_ingot"
}
},
"result": {
"item": "reliccraft:teleportation_restrictor"
}
}

View File

@ -0,0 +1,3 @@
{
"type": "reliccraft:time_dilater"
}

View File

@ -0,0 +1,10 @@
{
"replace": false,
"values": [
"reliccraft:staff",
"reliccraft:orb",
"reliccraft:time_dilater",
"reliccraft:teleportation_restrictor",
"reliccraft:teleportation_beacon"
]
}

View File

@ -0,0 +1,34 @@
{
"schemaVersion": 1,
"id": "reliccraft",
"version": "${version}",
"name": "${name}",
"description": "Find magical relics throughout the world!",
"authors": [
"TheBrokenRail"
],
"contact": {
"homepage": "https://thebrokenrail.com/",
"sources": "https://gitea.thebrokenrail.com/TheBrokenRail/RelicCraft.git",
"issues": "https://gitea.thebrokenrail.com/TheBrokenRail/RelicCraft/issues"
},
"license": "MIT",
"icon": "assets/reliccraft/textures/item/time_dilater.png",
"environment": "*",
"entrypoints": {
"main": [
"com.thebrokenrail.reliccraft.RelicCraft"
],
"client": [
"com.thebrokenrail.reliccraft.client.RelicCraftClient"
]
},
"mixins": [
"reliccraft.mixins.json"
],
"depends": {
"fabricloader": ">=0.7.4",
"fabric": "*",
"minecraft": "1.15.x"
}
}

View File

@ -0,0 +1,25 @@
{
"required": true,
"package": "com.thebrokenrail.reliccraft.mixin",
"compatibilityLevel": "JAVA_8",
"client": [
"MixinClientPlayNetworkHandler"
],
"mixins": [
"CriteriaRegistryHook",
"MixinEnderDragonFight",
"MixinEnderPearlItem",
"MixinEntity",
"MixinItemStack",
"MixinLevelProperties",
"MixinLivingEntity",
"MixinLocateCommand",
"MixinNetherStarItem",
"MixinServerWorld",
"MixinThrownEnderpearlEntity",
"MixinWorld"
],
"injectors": {
"defaultRequire": 1
}
}