Merge pull request #54 from paulevsGitch/1.18

1.18
This commit is contained in:
paulevsGitch 2021-12-04 12:18:47 +03:00 committed by GitHub
commit bcee0f2239
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
113 changed files with 3624 additions and 2346 deletions

View file

@ -1,6 +1,6 @@
[![](https://jitpack.io/v/paulevsGitch/BCLib.svg)](https://jitpack.io/#paulevsGitch/BCLib) [![](https://jitpack.io/v/paulevsGitch/BCLib.svg)](https://jitpack.io/#paulevsGitch/BCLib)
# BCLib # BCLib
BCLib is a library mod for BetterX team mods, developed for Fabric, MC 1.17.1 BCLib is a library mod for BetterX team mods, developed for Fabric, MC 1.18
## Features: ## Features:
### Rendering ### Rendering

View file

@ -7,8 +7,8 @@ buildscript {
gradlePluginPortal() gradlePluginPortal()
} }
} }
sourceCompatibility = JavaVersion.VERSION_16 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_16 targetCompatibility = JavaVersion.VERSION_17
archivesBaseName = project.archives_base_name archivesBaseName = project.archives_base_name
version = project.mod_version version = project.mod_version
@ -89,7 +89,7 @@ processResources {
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
options.encoding = "UTF-8" options.encoding = "UTF-8"
it.options.release = 16 it.options.release = 17
} }
javadoc { javadoc {

View file

@ -2,16 +2,16 @@
org.gradle.jvmargs=-Xmx2G org.gradle.jvmargs=-Xmx2G
#Loom #Loom
loom_version=0.8-SNAPSHOT loom_version=0.10-SNAPSHOT
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/versions.html # check these on https://fabricmc.net/versions.html
minecraft_version= 1.17.1 minecraft_version= 1.18
loader_version= 0.12.5 loader_version= 0.12.6
fabric_version = 0.42.1+1.17 fabric_version = 0.43.1+1.18
# Mod Properties # Mod Properties
mod_version = 0.5.5 mod_version = 1.0.0
maven_group = ru.bclib maven_group = ru.bclib
archives_base_name = bclib archives_base_name = bclib

Binary file not shown.

View file

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

269
gradlew vendored Normal file → Executable file
View file

@ -1,7 +1,7 @@
#!/usr/bin/env sh #!/bin/sh
# #
# Copyright 2015 the original author or authors. # Copyright © 2015-2021 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -17,78 +17,113 @@
# #
############################################################################## ##############################################################################
## #
## Gradle start up script for UN*X # Gradle start up script for POSIX generated by Gradle.
## #
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
############################################################################## ##############################################################################
# Attempt to set APP_HOME # Attempt to set APP_HOME
# Resolve links: $0 may be a link # Resolve links: $0 may be a link
PRG="$0" app_path=$0
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do # Need this for daisy-chained symlinks.
ls=`ls -ld "$PRG"` while
link=`expr "$ls" : '.*-> \(.*\)$'` APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
if expr "$link" : '/.*' > /dev/null; then [ -h "$app_path" ]
PRG="$link" do
else ls=$( ls -ld "$app_path" )
PRG=`dirname "$PRG"`"/$link" link=${ls#*' -> '}
fi case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle" APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"` APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # 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"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD=maximum
warn () { warn () {
echo "$*" echo "$*"
} } >&2
die () { die () {
echo echo
echo "$*" echo "$*"
echo echo
exit 1 exit 1
} } >&2
# OS specific support (must be 'true' or 'false'). # OS specific support (must be 'true' or 'false').
cygwin=false cygwin=false
msys=false msys=false
darwin=false darwin=false
nonstop=false nonstop=false
case "`uname`" in case "$( uname )" in #(
CYGWIN* ) CYGWIN* ) cygwin=true ;; #(
cygwin=true Darwin* ) darwin=true ;; #(
;; MSYS* | MINGW* ) msys=true ;; #(
Darwin* ) NONSTOP* ) nonstop=true ;;
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables # IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java" JAVACMD=$JAVA_HOME/jre/sh/java
else else
JAVACMD="$JAVA_HOME/bin/java" JAVACMD=$JAVA_HOME/bin/java
fi fi
if [ ! -x "$JAVACMD" ] ; then if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi fi
else else
JAVACMD="java" 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. 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 Please set the JAVA_HOME variable in your environment to match the
@ -105,79 +140,95 @@ location of your Java installation."
fi fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
MAX_FD_LIMIT=`ulimit -H -n` case $MAX_FD in #(
if [ $? -eq 0 ] ; then max*)
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD=$( ulimit -H -n ) ||
MAX_FD="$MAX_FD_LIMIT" warn "Could not query maximum file descriptor limit"
fi esac
ulimit -n $MAX_FD case $MAX_FD in #(
if [ $? -ne 0 ] ; then '' | soft) :;; #(
warn "Could not set maximum file descriptor limit: $MAX_FD" *)
fi ulimit -n "$MAX_FD" ||
else warn "Could not set maximum file descriptor limit to $MAX_FD"
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac esac
fi fi
# Escape application args # Collect all arguments for the java command, stacking in reverse order:
save () { # * args from the command line
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done # * the main class name
echo " " # * -classpath
} # * -D...appname settings
APP_ARGS=`save "$@"` # * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules # For Cygwin or MSYS, switch paths to Windows format before running java
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@" exec "$JAVACMD" "$@"

22
gradlew.bat vendored
View file

@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init if "%ERRORLEVEL%" == "0" goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -54,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init if exist "%JAVA_EXE%" goto execute
echo. echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@ -64,28 +64,14 @@ echo location of your Java installation.
goto fail 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 :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @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% "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

View file

@ -20,7 +20,6 @@ import ru.bclib.util.Logger;
import ru.bclib.world.generator.BCLibEndBiomeSource; import ru.bclib.world.generator.BCLibEndBiomeSource;
import ru.bclib.world.generator.BCLibNetherBiomeSource; import ru.bclib.world.generator.BCLibNetherBiomeSource;
import ru.bclib.world.generator.GeneratorOptions; import ru.bclib.world.generator.GeneratorOptions;
import ru.bclib.world.surface.BCLSurfaceBuilders;
import java.util.List; import java.util.List;
@ -33,7 +32,6 @@ public class BCLib implements ModInitializer {
BaseRegistry.register(); BaseRegistry.register();
GeneratorOptions.init(); GeneratorOptions.init();
BaseBlockEntities.register(); BaseBlockEntities.register();
BCLSurfaceBuilders.register();
BCLibEndBiomeSource.register(); BCLibEndBiomeSource.register();
BCLibNetherBiomeSource.register(); BCLibNetherBiomeSource.register();
TagAPI.init(); TagAPI.init();
@ -42,11 +40,11 @@ public class BCLib implements ModInitializer {
DataExchangeAPI.registerMod(MOD_ID); DataExchangeAPI.registerMod(MOD_ID);
DataExchangeAPI.registerDescriptors(List.of( DataExchangeAPI.registerDescriptors(List.of(
HelloClient.DESCRIPTOR, HelloClient.DESCRIPTOR,
HelloServer.DESCRIPTOR, HelloServer.DESCRIPTOR,
RequestFiles.DESCRIPTOR, RequestFiles.DESCRIPTOR,
SendFiles.DESCRIPTOR, SendFiles.DESCRIPTOR,
Chunker.DESCRIPTOR Chunker.DESCRIPTOR
)); ));
BCLibPatch.register(); BCLibPatch.register();

View file

@ -11,7 +11,6 @@ import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess;
import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.ServerLevelData;
import java.util.ArrayList; import java.util.ArrayList;
@ -24,6 +23,13 @@ import java.util.concurrent.Executor;
public class LifeCycleAPI { public class LifeCycleAPI {
private final static List<LevelLoadBiomesCall> onLoadLevelBiomes = new ArrayList<>(2); private final static List<LevelLoadBiomesCall> onLoadLevelBiomes = new ArrayList<>(2);
private final static List<LevelLoadCall> onLoadLevel = new ArrayList<>(2); private final static List<LevelLoadCall> onLoadLevel = new ArrayList<>(2);
private final static List<BeforeLevelLoadCall> beforeLoadLevel = new ArrayList<>(2);
/**
* A callback function that is used for each new ServerLevel instance
*/
public interface BeforeLevelLoadCall {
void beforeLoad();
}
/** /**
* A callback function that is used for each new ServerLevel instance * A callback function that is used for each new ServerLevel instance
@ -52,6 +58,17 @@ public class LifeCycleAPI {
boolean bl2); boolean bl2);
} }
/**
* Register a callback that is called before a level is loaded or created,
* but after the {@link WorldDataAPI} was initialized and patches from
* the {@link ru.bclib.api.datafixer.DataFixerAPI} were applied.
*
* @param call The callback Method
*/
public static void beforeLevelLoad(BeforeLevelLoadCall call){
beforeLoadLevel.add(call);
}
/** /**
* Register a callback that is called when a new {@code ServerLevel is instantiated}. * Register a callback that is called when a new {@code ServerLevel is instantiated}.
* This callback will receive the world seed as well as it's biome registry. * This callback will receive the world seed as well as it's biome registry.
@ -70,6 +87,13 @@ public class LifeCycleAPI {
onLoadLevel.add(call); onLoadLevel.add(call);
} }
/**
* For internal use, You should not call this method!
* @param src
*/
public static void _runBeforeLevelLoad(){
beforeLoadLevel.forEach(c -> c.beforeLoad());
}
/** /**
* For internal use, You should not call this method! * For internal use, You should not call this method!
* @param minecraftServer * @param minecraftServer

View file

@ -6,7 +6,10 @@ import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.tags.Tag;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.blocks.BaseBarrelBlock; import ru.bclib.blocks.BaseBarrelBlock;
import ru.bclib.blocks.BaseChestBlock; import ru.bclib.blocks.BaseChestBlock;
import ru.bclib.blocks.BaseFurnaceBlock; import ru.bclib.blocks.BaseFurnaceBlock;
@ -16,6 +19,7 @@ import ru.bclib.client.render.BaseChestBlockEntityRenderer;
import ru.bclib.client.render.BaseSignBlockEntityRenderer; import ru.bclib.client.render.BaseSignBlockEntityRenderer;
import ru.bclib.interfaces.PostInitable; import ru.bclib.interfaces.PostInitable;
import ru.bclib.interfaces.RenderLayerProvider; import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider;
import ru.bclib.registry.BaseBlockEntities; import ru.bclib.registry.BaseBlockEntities;
import java.util.List; import java.util.List;
@ -23,6 +27,8 @@ import java.util.function.Consumer;
public class PostInitAPI { public class PostInitAPI {
private static List<Consumer<Boolean>> postInitFunctions = Lists.newArrayList(); private static List<Consumer<Boolean>> postInitFunctions = Lists.newArrayList();
private static List<Tag.Named<Block>> blockTags = Lists.newArrayList();
private static List<Tag.Named<Item>> itemTags = Lists.newArrayList();
/** /**
* Register a new function which will be called after all mods are initiated. Will be called on both client and server. * Register a new function which will be called after all mods are initiated. Will be called on both client and server.
@ -48,6 +54,8 @@ public class PostInitAPI {
} }
}); });
postInitFunctions = null; postInitFunctions = null;
blockTags = null;
itemTags = null;
BiomeAPI.loadFabricAPIBiomes(); BiomeAPI.loadFabricAPIBiomes();
} }
@ -82,5 +90,12 @@ public class PostInitAPI {
else if (block instanceof BaseFurnaceBlock) { else if (block instanceof BaseFurnaceBlock) {
BaseBlockEntities.FURNACE.registerBlock(block); BaseBlockEntities.FURNACE.registerBlock(block);
} }
if (block instanceof TagProvider) {
TagProvider.class.cast(block).addTags(blockTags, itemTags);
blockTags.forEach(tag -> TagAPI.addTag(tag, block));
itemTags.forEach(tag -> TagAPI.addTag(tag, block));
blockTags.clear();
itemTags.clear();
}
} }
} }

View file

@ -2,7 +2,9 @@ package ru.bclib.api;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import net.fabricmc.fabric.api.tag.TagFactory;
import net.fabricmc.fabric.api.tag.TagRegistry; import net.fabricmc.fabric.api.tag.TagRegistry;
import net.fabricmc.fabric.impl.tag.extension.TagDelegate;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceManager;
@ -75,7 +77,8 @@ public class TagAPI {
*/ */
public static <T> Tag.Named<T> makeTag(Supplier<TagCollection<T>> containerSupplier, ResourceLocation id) { public static <T> Tag.Named<T> makeTag(Supplier<TagCollection<T>> containerSupplier, ResourceLocation id) {
Tag<T> tag = containerSupplier.get().getTag(id); Tag<T> tag = containerSupplier.get().getTag(id);
return tag == null ? TagRegistry.create(id, containerSupplier) : (Named<T>) tag; //return tag == null ? TagRegistry.create(id, containerSupplier) : (Named<T>) tag;
return tag == null ? new TagDelegate<>(id, containerSupplier) : (Named<T>) tag;
} }
/** /**
@ -131,7 +134,8 @@ public class TagAPI {
public static Tag.Named<Block> getMCBlockTag(String name) { public static Tag.Named<Block> getMCBlockTag(String name) {
ResourceLocation id = new ResourceLocation(name); ResourceLocation id = new ResourceLocation(name);
Tag<Block> tag = BlockTags.getAllTags().getTag(id); Tag<Block> tag = BlockTags.getAllTags().getTag(id);
return tag == null ? (Named<Block>) TagRegistry.block(id) : (Named<Block>) tag; //return tag == null ? (Named<Block>) TagRegistry.block(id) : (Named<Block>) tag;
return tag == null ? (Named<Block>) TagFactory.BLOCK.create(id): (Named<Block>) tag;
} }
/** /**

View file

@ -44,6 +44,7 @@ public class WorldDataAPI {
catch (IOException e) { catch (IOException e) {
BCLib.LOGGER.error("World data loading failed", e); BCLib.LOGGER.error("World data loading failed", e);
} }
TAGS.put(modID, root);
} }
else { else {
Optional<ModContainer> optional = FabricLoader.getInstance() Optional<ModContainer> optional = FabricLoader.getInstance()
@ -58,11 +59,10 @@ public class WorldDataAPI {
.getVersion() .getVersion()
.toString()); .toString());
} }
TAGS.put(modID, root);
saveFile(modID); saveFile(modID);
} }
} }
TAGS.put(modID, root);
}); });
} }

View file

@ -0,0 +1,599 @@
package ru.bclib.api.biomes;
import net.fabricmc.fabric.api.biome.v1.BiomeModifications;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.data.worldgen.BiomeDefaultFeatures;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.Music;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.level.biome.AmbientAdditionsSettings;
import net.minecraft.world.level.biome.AmbientMoodSettings;
import net.minecraft.world.level.biome.AmbientParticleSettings;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biome.BiomeBuilder;
import net.minecraft.world.level.biome.Biome.BiomeCategory;
import net.minecraft.world.level.biome.Biome.Precipitation;
import net.minecraft.world.level.biome.BiomeGenerationSettings;
import net.minecraft.world.level.biome.BiomeSpecialEffects;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.Noises;
import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import ru.bclib.util.ColorUtil;
import ru.bclib.world.biomes.BCLBiome;
import ru.bclib.world.features.BCLFeature;
import ru.bclib.world.structures.BCLStructureFeature;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;
public class BCLBiomeBuilder {
private static final BCLBiomeBuilder INSTANCE = new BCLBiomeBuilder();
private static final SurfaceRules.ConditionSource SURFACE_NOISE = SurfaceRules.noiseCondition(Noises.SOUL_SAND_LAYER, -0.012);
private List<ConfiguredStructureFeature> structures = new ArrayList<>(16);
private BiomeGenerationSettings.Builder generationSettings;
private BiomeSpecialEffects.Builder effectsBuilder;
private MobSpawnSettings.Builder spawnSettings;
private SurfaceRules.RuleSource surfaceRule;
private Precipitation precipitation;
private ResourceLocation biomeID;
private BiomeCategory category;
private float temperature;
private float fogDensity;
private float downfall;
/**
* Starts new biome building process.
* @param biomeID {@link ResourceLocation} biome identifier.
* @return prepared {@link BCLBiomeBuilder} instance.
*/
public static BCLBiomeBuilder start(ResourceLocation biomeID) {
INSTANCE.biomeID = biomeID;
INSTANCE.precipitation = Precipitation.NONE;
INSTANCE.category = BiomeCategory.NONE;
INSTANCE.generationSettings = null;
INSTANCE.effectsBuilder = null;
INSTANCE.spawnSettings = null;
INSTANCE.structures.clear();
INSTANCE.temperature = 1.0F;
INSTANCE.fogDensity = 1.0F;
INSTANCE.downfall = 1.0F;
return INSTANCE;
}
/**
* Set biome {@link Precipitation}. Affect biome visual effects (rain, snow, none).
* @param precipitation {@link Precipitation}
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder precipitation(Precipitation precipitation) {
this.precipitation = precipitation;
return this;
}
/**
* Set biome category. Doesn't affect biome worldgen, but Fabric biome modifications can target biome by it.
* @param category {@link BiomeCategory}
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder category(BiomeCategory category) {
this.category = category;
return this;
}
/**
* Set biome temperature, affect plant color, biome generation and ice formation.
* @param temperature biome temperature.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder temperature(float temperature) {
this.temperature = temperature;
return this;
}
/**
* Set biome wetness (same as downfall). Affect plant color and biome generation.
* @param wetness biome wetness (downfall).
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder wetness(float wetness) {
this.downfall = wetness;
return this;
}
/**
* Adds mob spawning to biome.
* @param entityType {@link EntityType} mob type.
* @param weight spawn weight.
* @param minGroupCount minimum mobs in group.
* @param maxGroupCount maximum mobs in group.
* @return same {@link BCLBiomeBuilder} instance.
*/
public <M extends Mob> BCLBiomeBuilder spawn(EntityType<M> entityType, int weight, int minGroupCount, int maxGroupCount) {
getSpawns().addSpawn(entityType.getCategory(), new SpawnerData(entityType, weight, minGroupCount, maxGroupCount));
return this;
}
/**
* Adds ambient particles to thr biome.
* @param particle {@link ParticleOptions} particles (or {@link net.minecraft.core.particles.ParticleType}).
* @param probability particle spawn probability, should have low value (example: 0.01F).
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder particles(ParticleOptions particle, float probability) {
getEffects().ambientParticle(new AmbientParticleSettings(particle, probability));
return this;
}
/**
* Sets sky color for the biome. Color is in ARGB int format.
* @param color ARGB color as integer.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder skyColor(int color) {
getEffects().skyColor(color);
return this;
}
/**
* Sets sky color for the biome. Color represented as red, green and blue channel values.
* @param red red color component [0-255]
* @param green green color component [0-255]
* @param blue blue color component [0-255]
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder skyColor(int red, int green, int blue) {
red = Mth.clamp(red, 0, 255);
green = Mth.clamp(green, 0, 255);
blue = Mth.clamp(blue, 0, 255);
return skyColor(ColorUtil.color(red, green, blue));
}
/**
* Sets fog color for the biome. Color is in ARGB int format.
* @param color ARGB color as integer.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder fogColor(int color) {
getEffects().fogColor(color);
return this;
}
/**
* Sets fog color for the biome. Color represented as red, green and blue channel values.
* @param red red color component [0-255]
* @param green green color component [0-255]
* @param blue blue color component [0-255]
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder fogColor(int red, int green, int blue) {
red = Mth.clamp(red, 0, 255);
green = Mth.clamp(green, 0, 255);
blue = Mth.clamp(blue, 0, 255);
return fogColor(ColorUtil.color(red, green, blue));
}
/**
* Sets fog density for the biome.
* @param density fog density as a float, default value is 1.0F.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder fogDensity(float density) {
this.fogDensity = density;
return this;
}
/**
* Sets water color for the biome. Color is in ARGB int format.
* @param color ARGB color as integer.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder waterColor(int color) {
getEffects().waterColor(color);
return this;
}
/**
* Sets water color for the biome. Color represented as red, green and blue channel values.
* @param red red color component [0-255]
* @param green green color component [0-255]
* @param blue blue color component [0-255]
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder waterColor(int red, int green, int blue) {
red = Mth.clamp(red, 0, 255);
green = Mth.clamp(green, 0, 255);
blue = Mth.clamp(blue, 0, 255);
return waterColor(ColorUtil.color(red, green, blue));
}
/**
* Sets underwater fog color for the biome. Color is in ARGB int format.
* @param color ARGB color as integer.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder waterFogColor(int color) {
getEffects().waterFogColor(color);
return this;
}
/**
* Sets underwater fog color for the biome. Color represented as red, green and blue channel values.
* @param red red color component [0-255]
* @param green green color component [0-255]
* @param blue blue color component [0-255]
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder waterFogColor(int red, int green, int blue) {
red = Mth.clamp(red, 0, 255);
green = Mth.clamp(green, 0, 255);
blue = Mth.clamp(blue, 0, 255);
return waterFogColor(ColorUtil.color(red, green, blue));
}
/**
* Sets water and underwater fig color for the biome. Color is in ARGB int format.
* @param color ARGB color as integer.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder waterAndFogColor(int color) {
return waterColor(color).waterFogColor(color);
}
/**
* Sets water and underwater fig color for the biome. Color is in ARGB int format.
* @param red red color component [0-255]
* @param green green color component [0-255]
* @param blue blue color component [0-255]
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder waterAndFogColor(int red, int green, int blue) {
red = Mth.clamp(red, 0, 255);
green = Mth.clamp(green, 0, 255);
blue = Mth.clamp(blue, 0, 255);
return waterAndFogColor(ColorUtil.color(red, green, blue));
}
/**
* Sets grass color for the biome. Color is in ARGB int format.
* @param color ARGB color as integer.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder grassColor(int color) {
getEffects().grassColorOverride(color);
return this;
}
/**
* Sets grass color for the biome. Color represented as red, green and blue channel values.
* @param red red color component [0-255]
* @param green green color component [0-255]
* @param blue blue color component [0-255]
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder grassColor(int red, int green, int blue) {
red = Mth.clamp(red, 0, 255);
green = Mth.clamp(green, 0, 255);
blue = Mth.clamp(blue, 0, 255);
return grassColor(ColorUtil.color(red, green, blue));
}
/**
* Sets leaves and plants color for the biome. Color is in ARGB int format.
* @param color ARGB color as integer.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder foliageColor(int color) {
getEffects().foliageColorOverride(color);
return this;
}
/**
* Sets leaves and plants color for the biome. Color represented as red, green and blue channel values.
* @param red red color component [0-255]
* @param green green color component [0-255]
* @param blue blue color component [0-255]
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder foliageColor(int red, int green, int blue) {
red = Mth.clamp(red, 0, 255);
green = Mth.clamp(green, 0, 255);
blue = Mth.clamp(blue, 0, 255);
return foliageColor(ColorUtil.color(red, green, blue));
}
/**
* Sets grass, leaves and all plants color for the biome. Color is in ARGB int format.
* @param color ARGB color as integer.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder plantsColor(int color) {
return grassColor(color).foliageColor(color);
}
/**
* Sets grass, leaves and all plants color for the biome. Color represented as red, green and blue channel values.
* @param red red color component [0-255]
* @param green green color component [0-255]
* @param blue blue color component [0-255]
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder plantsColor(int red, int green, int blue) {
red = Mth.clamp(red, 0, 255);
green = Mth.clamp(green, 0, 255);
blue = Mth.clamp(blue, 0, 255);
return plantsColor(ColorUtil.color(red, green, blue));
}
/**
* Sets biome music, used for biomes in the Nether and End.
* @param music {@link Music} to use.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder music(Music music) {
getEffects().backgroundMusic(music);
return this;
}
/**
* Sets biome music, used for biomes in the Nether and End.
* @param music {@link SoundEvent} to use.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder music(SoundEvent music) {
return music(new Music(music, 600, 2400, true));
}
/**
* Sets biome ambient loop sound. Can be used for biome environment.
* @param loopSound {@link SoundEvent} to use as a loop.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder loop(SoundEvent loopSound) {
getEffects().ambientLoopSound(loopSound);
return this;
}
/**
* Sets biome mood sound. Can be used for biome environment.
* @param mood {@link SoundEvent} to use as a mood.
* @param tickDelay delay between sound events in ticks.
* @param blockSearchExtent block search radius (for area available for sound).
* @param soundPositionOffset offset in sound.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder mood(SoundEvent mood, int tickDelay, int blockSearchExtent, float soundPositionOffset) {
getEffects().ambientMoodSound(new AmbientMoodSettings(mood, tickDelay, blockSearchExtent, soundPositionOffset));
return this;
}
/**
* Sets biome mood sound. Can be used for biome environment.
* @param mood {@link SoundEvent} to use as a mood.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder mood(SoundEvent mood) {
return mood(mood, 6000, 8, 2.0F);
}
/**
* Sets biome additionsl ambient sounds.
* @param additions {@link SoundEvent} to use.
* @param intensity sound intensity. Default is 0.0111F.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder additions(SoundEvent additions, float intensity) {
getEffects().ambientAdditionsSound(new AmbientAdditionsSettings(additions, intensity));
return this;
}
/**
* Sets biome additionsl ambient sounds.
* @param additions {@link SoundEvent} to use.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder additions(SoundEvent additions) {
return additions(additions, 0.0111F);
}
/**
* Adds new feature to the biome.
* @param decoration {@link Decoration} feature step.
* @param feature {@link PlacedFeature}.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder feature(Decoration decoration, PlacedFeature feature) {
getGeneration().addFeature(decoration, feature);
return this;
}
/**
* Adds vanilla Mushrooms.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder defaultMushrooms() {
return feature(BiomeDefaultFeatures::addDefaultMushrooms);
}
/**
* Adds vanilla Nether Ores.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder netherDefaultOres() {
return feature(BiomeDefaultFeatures::addNetherDefaultOres);
}
/**
* Will add features into biome, used for vanilla feature adding functions.
* @param featureAdd {@link Consumer} with {@link BiomeGenerationSettings.Builder}.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder feature(Consumer<BiomeGenerationSettings.Builder> featureAdd) {
featureAdd.accept(getGeneration());
return this;
}
/**
* Adds new feature to the biome.
* @param feature {@link BCLFeature}.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder feature(BCLFeature feature) {
return feature(feature.getDecoration(), feature.getPlacedFeature());
}
/**
* Adds new structure feature into the biome.
* @param structure {@link ConfiguredStructureFeature} to add.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder structure(ConfiguredStructureFeature<?, ?> structure) {
structures.add(structure);
return this;
}
/**
* Adds new structure feature into thr biome. Will add building biome into the structure list.
* @param structure {@link BCLStructureFeature} to add.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder structure(BCLStructureFeature structure) {
structure.addInternalBiome(biomeID);
return structure(structure.getFeatureConfigured());
}
/**
* Adds new world carver into the biome.
* @param carver {@link ConfiguredWorldCarver} to add.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder carver(GenerationStep.Carving step, ConfiguredWorldCarver<?> carver) {
BuiltinRegistries.CONFIGURED_CARVER
.getResourceKey(carver)
.ifPresent(key -> BiomeModifications.addCarver(ctx -> ctx.getBiomeKey().location().equals(biomeID), step, key));
return this;
}
/**
* Adds new world surface rule for the given block
* @param surfaceBlock {@link Block} to use.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder surface(Block surfaceBlock) {
return surface(SurfaceRuleBuilder.start().surface(surfaceBlock.defaultBlockState()).build());
}
/**
* Adds blocks to the biome surface and below it (with specified depth).
* @param surfaceBlock {@link Block} that will cover biome.
* @param subterrainBlock {@link Block} below it with specified depth.
* @param depth thickness of bottom block layer.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder surface(Block surfaceBlock, Block subterrainBlock, int depth) {
return surface(SurfaceRuleBuilder
.start()
.surface(surfaceBlock.defaultBlockState())
.subsurface(subterrainBlock.defaultBlockState(), depth)
.build());
}
/**
* Adds surface rule to this biome.
* @param surfaceRule {link SurfaceRules.RuleSource} surface rule.
* @return same {@link BCLBiomeBuilder} instance.
*/
public BCLBiomeBuilder surface(SurfaceRules.RuleSource surfaceRule) {
this.surfaceRule = surfaceRule;
return this;
}
/**
* Finalize biome creation.
* @return created {@link BCLBiome} instance.
*/
public BCLBiome build() {
return build(BCLBiome::new);
}
/**
* Finalize biome creation.
* @param biomeConstructor {@link BiFunction} biome constructor.
* @return created {@link BCLBiome} instance.
*/
public <T extends BCLBiome> T build(BiFunction<ResourceLocation, Biome, T> biomeConstructor) {
BiomeBuilder builder = new BiomeBuilder()
.precipitation(precipitation)
.biomeCategory(category)
.temperature(temperature)
.downfall(downfall);
if (spawnSettings != null) {
builder.mobSpawnSettings(spawnSettings.build());
}
if (effectsBuilder != null) {
builder.specialEffects(effectsBuilder.build());
}
if (generationSettings != null) {
builder.generationSettings(generationSettings.build());
}
final T res = biomeConstructor.apply(biomeID, builder.build());
res.attachStructures(structures);
res.setSurface(surfaceRule);
res.setFogDensity(fogDensity);
return res;
}
/**
* Get or create {@link BiomeSpecialEffects.Builder} for biome visual effects.
* For internal usage only.
* For internal usage only.
* @return new or same {@link BiomeSpecialEffects.Builder} instance.
*/
private BiomeSpecialEffects.Builder getEffects() {
if (effectsBuilder == null) {
effectsBuilder = new BiomeSpecialEffects.Builder();
}
return effectsBuilder;
}
/**
* Get or create {@link MobSpawnSettings.Builder} for biome mob spawning.
* For internal usage only.
* @return new or same {@link MobSpawnSettings.Builder} instance.
*/
private MobSpawnSettings.Builder getSpawns() {
if (spawnSettings == null) {
spawnSettings = new MobSpawnSettings.Builder();
}
return spawnSettings;
}
/**
* Get or create {@link BiomeGenerationSettings.Builder} for biome features and generation.
* For internal usage only.
* @return new or same {@link BiomeGenerationSettings.Builder} instance.
*/
private BiomeGenerationSettings.Builder getGeneration() {
if (generationSettings == null) {
generationSettings = new BiomeGenerationSettings.Builder();
}
return generationSettings;
}
}

View file

@ -0,0 +1,190 @@
package ru.bclib.api.biomes;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource;
import net.minecraft.world.level.levelgen.placement.CaveSurface;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public class SurfaceRuleBuilder {
private static final Map<String, SurfaceRuleEntry> RULES_CACHE = Maps.newHashMap();
private static final SurfaceRuleBuilder INSTANCE = new SurfaceRuleBuilder();
private List<SurfaceRuleEntry> rules = Lists.newArrayList();
private SurfaceRuleEntry entryInstance;
private ResourceKey<Biome> biomeKey;
private SurfaceRuleBuilder() {}
public static SurfaceRuleBuilder start() {
INSTANCE.biomeKey = null;
INSTANCE.rules.clear();
return INSTANCE;
}
/**
* Restricts surface to only one biome.
* @param biomeKey {@link ResourceKey} for the {@link Biome}.
* @return same {@link SurfaceRuleBuilder} instance.
*/
public SurfaceRuleBuilder biome(ResourceKey<Biome> biomeKey) {
this.biomeKey = biomeKey;
return this;
}
/**
* Restricts surface to only one biome.
* @param biome {@link Biome}.
* @return same {@link SurfaceRuleBuilder} instance.
*/
public SurfaceRuleBuilder biome(Biome biome) {
return biome(BiomeAPI.getBiomeKey(biome));
}
/**
* Set biome surface with specified {@link BlockState}. Example - block of grass in the Overworld biomes
* @param state {@link BlockState} for the ground cover.
* @return same {@link SurfaceRuleBuilder} instance.
*/
public SurfaceRuleBuilder surface(BlockState state) {
entryInstance = getFromCache("surface_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state);
rule = SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, rule);
return new SurfaceRuleEntry(2, rule);
});
rules.add(entryInstance);
return this;
}
/**
* Set biome subsurface with specified {@link BlockState}. Example - dirt in the Overworld biomes.
* @param state {@link BlockState} for the subterrain layer.
* @param depth block layer depth.
* @return same {@link SurfaceRuleBuilder} instance.
*/
public SurfaceRuleBuilder subsurface(BlockState state, int depth) {
entryInstance = getFromCache("subsurface_" + depth + "_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state);
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(depth, false, false, CaveSurface.FLOOR), rule);
return new SurfaceRuleEntry(3, rule);
});
rules.add(entryInstance);
return this;
}
/**
* Set biome filler with specified {@link BlockState}. Example - stone in the Overworld biomes.
* @param state {@link BlockState} for filling.
* @return same {@link SurfaceRuleBuilder} instance.
*/
public SurfaceRuleBuilder filler(BlockState state) {
entryInstance = getFromCache("fill_" + state.toString(), () -> new SurfaceRuleEntry(3, SurfaceRules.state(state)));
rules.add(entryInstance);
return this;
}
/**
* Set biome ceiling with specified {@link BlockState}. Example - block of sandstone in the Overworld desert in air pockets.
* @param state {@link BlockState} for the ground cover.
* @return same {@link SurfaceRuleBuilder} instance.
*/
public SurfaceRuleBuilder ceil(BlockState state) {
entryInstance = getFromCache("ceil_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state);
return new SurfaceRuleEntry(2, SurfaceRules.ifTrue(SurfaceRules.ON_CEILING, rule));
});
rules.add(entryInstance);
return this;
}
/**
* Set biome ceiling material with specified {@link BlockState} and height. Example - sandstone in the Overworld deserts.
* @param state {@link BlockState} for the subterrain layer.
* @param height block layer height.
* @return same {@link SurfaceRuleBuilder} instance.
*/
public SurfaceRuleBuilder aboveCeil(BlockState state, int height) {
entryInstance = getFromCache("above_ceil_" + height + "_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state);
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(height, false, false, CaveSurface.CEILING), rule);
return new SurfaceRuleEntry(3, rule);
});
rules.add(entryInstance);
return this;
}
/**
* Will cover steep areas (with large terrain angle). Example - Overworld mountains.
* @param state {@link BlockState} for the steep layer.
* @param depth layer depth
* @return
*/
public SurfaceRuleBuilder steep(BlockState state, int depth) {
entryInstance = getFromCache("steep_" + depth + "_" + state.toString(), () -> {
RuleSource rule = SurfaceRules.state(state);
rule = SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(depth, false, false, CaveSurface.FLOOR), rule);
rule = SurfaceRules.ifTrue(SurfaceRules.steep(), rule);
int priority = depth < 1 ? 0 : 1;
return new SurfaceRuleEntry(priority, rule);
});
rules.add(entryInstance);
return this;
}
/**
* Allows to add custom rule.
* @param priority rule priority, lower values = higher priority (rule will be applied before others).
* @param rule custom {@link SurfaceRules.RuleSource}.
* @return same {@link SurfaceRuleBuilder} instance.
*/
public SurfaceRuleBuilder rule(int priority, SurfaceRules.RuleSource rule) {
rules.add(new SurfaceRuleEntry(priority, rule));
return this;
}
/**
* Allows to add custom rule.
* @param rule custom {@link SurfaceRules.RuleSource}.
* @return same {@link SurfaceRuleBuilder} instance.
*/
public SurfaceRuleBuilder rule(SurfaceRules.RuleSource rule) {
return rule(7, rule);
}
/**
* Finalise rule building process.
* @return {@link SurfaceRules.RuleSource}.
*/
public SurfaceRules.RuleSource build() {
Collections.sort(rules);
List<SurfaceRules.RuleSource> ruleList = rules.stream().map(entry -> entry.getRule()).toList();
SurfaceRules.RuleSource[] ruleArray = ruleList.toArray(new SurfaceRules.RuleSource[ruleList.size()]);
SurfaceRules.RuleSource rule = SurfaceRules.sequence(ruleArray);
if (biomeKey != null) {
rule = SurfaceRules.ifTrue(SurfaceRules.isBiome(biomeKey), rule);
}
return rule;
}
/**
* Internal function, will take entry from cache or create it if necessary.
* @param name {@link String} entry internal name.
* @param supplier {@link Supplier} for {@link SurfaceRuleEntry}.
* @return new or existing {@link SurfaceRuleEntry}.
*/
private static SurfaceRuleEntry getFromCache(String name, Supplier<SurfaceRuleEntry> supplier) {
SurfaceRuleEntry entry = RULES_CACHE.get(name);
if (entry == null) {
entry = supplier.get();
RULES_CACHE.put(name, entry);
}
return entry;
}
}

View file

@ -0,0 +1,24 @@
package ru.bclib.api.biomes;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.level.levelgen.SurfaceRules;
import org.jetbrains.annotations.NotNull;
public class SurfaceRuleEntry<M extends Mob> implements Comparable<SurfaceRuleEntry> {
private final SurfaceRules.RuleSource rule;
private final byte priority;
public SurfaceRuleEntry(int priority, SurfaceRules.RuleSource rule) {
this.priority = (byte) priority;
this.rule = rule;
}
protected SurfaceRules.RuleSource getRule() {
return rule;
}
@Override
public int compareTo(@NotNull SurfaceRuleEntry entry) {
return Integer.compare(priority, entry.priority);
}
}

View file

@ -189,7 +189,7 @@ public class Chunker extends DataHandler.FromServer {
public static final int MAX_PACKET_SIZE = 1024*1024; public static final int MAX_PACKET_SIZE = 1024*1024;
private static final int MAX_PAYLOAD_SIZE = MAX_PACKET_SIZE - HEADER_SIZE; private static final int MAX_PAYLOAD_SIZE = MAX_PACKET_SIZE - HEADER_SIZE;
public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "chunker"), Chunker::new, false, false); public static final DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "chunker"), Chunker::new, false, false);
private int serialNo; private int serialNo;
private UUID uuid; private UUID uuid;

View file

@ -48,7 +48,7 @@ public class HelloClient extends DataHandler.FromServer {
public interface IServerModMap extends Map<String, OfferedModInfo> {} public interface IServerModMap extends Map<String, OfferedModInfo> {}
public static class ServerModMap extends HashMap<String, OfferedModInfo> implements IServerModMap {} public static class ServerModMap extends HashMap<String, OfferedModInfo> implements IServerModMap {}
public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "hello_client"), HelloClient::new, false, false); public static final DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "hello_client"), HelloClient::new, false, false);
public HelloClient() { public HelloClient() {
super(DESCRIPTOR.IDENTIFIER); super(DESCRIPTOR.IDENTIFIER);

View file

@ -57,7 +57,7 @@ import java.io.File;
* </table> * </table>
*/ */
public class HelloServer extends DataHandler.FromClient { public class HelloServer extends DataHandler.FromClient {
public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "hello_server"), HelloServer::new, true, false); public static final DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "hello_server"), HelloServer::new, true, false);
protected String bclibVersion = "0.0.0"; protected String bclibVersion = "0.0.0";

View file

@ -17,7 +17,7 @@ import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class RequestFiles extends DataHandler.FromClient { public class RequestFiles extends DataHandler.FromClient {
public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "request_files"), RequestFiles::new, false, false); public static final DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "request_files"), RequestFiles::new, false, false);
static String currentToken = ""; static String currentToken = "";
protected List<AutoSyncID> files; protected List<AutoSyncID> files;

View file

@ -24,7 +24,7 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class SendFiles extends DataHandler.FromServer { public class SendFiles extends DataHandler.FromServer {
public static DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "send_files"), SendFiles::new, false, false); public static final DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID, "send_files"), SendFiles::new, false, false);
protected List<AutoFileSyncEntry> files; protected List<AutoFileSyncEntry> files;
private String token; private String token;

View file

@ -35,6 +35,7 @@ import java.io.DataOutputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -459,9 +460,10 @@ public class DataFixerAPI {
private static void fixRegion(MigrationProfile data, State state, File file) { private static void fixRegion(MigrationProfile data, State state, File file) {
try { try {
LOGGER.info("Inspecting " + file); Path path = file.toPath();
LOGGER.info("Inspecting " + path);
boolean[] changed = new boolean[1]; boolean[] changed = new boolean[1];
RegionFile region = new RegionFile(file, file.getParentFile(), true); RegionFile region = new RegionFile(path, path.getParent(), true);
for (int x = 0; x < 32; x++) { for (int x = 0; x < 32; x++) {
for (int z = 0; z < 32; z++) { for (int z = 0; z < 32; z++) {

View file

@ -13,8 +13,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
public abstract class Patch { public abstract class Patch {
private static final List<Patch> ALL = new ArrayList<>(10);
private static List<Patch> ALL = new ArrayList<>(10);
/** /**
* The Patch-Level derived from {@link #version} * The Patch-Level derived from {@link #version}
@ -50,12 +49,7 @@ public abstract class Patch {
* @return The highest Patch-Version that was found * @return The highest Patch-Version that was found
*/ */
public static String maxPatchVersion(@NotNull String modID) { public static String maxPatchVersion(@NotNull String modID) {
return ALL.stream() return ALL.stream().filter(p -> p.modID.equals(modID)).map(p -> p.version).reduce((p, c) -> c).orElse("0.0.0");
.filter(p -> p.modID
.equals(modID))
.map(p -> p.version)
.reduce((p, c) -> c)
.orElse("0.0.0");
} }
/** /**
@ -66,12 +60,7 @@ public abstract class Patch {
* @return The highest Patch-Level that was found * @return The highest Patch-Level that was found
*/ */
public static int maxPatchLevel(@NotNull String modID) { public static int maxPatchLevel(@NotNull String modID) {
return ALL.stream() return ALL.stream().filter(p -> p.modID.equals(modID)).mapToInt(p -> p.level).max().orElse(0);
.filter(p -> p.modID
.equals(modID))
.mapToInt(p -> p.level)
.max()
.orElse(0);
} }
/** /**
@ -103,21 +92,18 @@ public abstract class Patch {
*/ */
Patch(@NotNull String modID, String version, boolean alwaysApply) { Patch(@NotNull String modID, String version, boolean alwaysApply) {
//Patchlevels need to be unique and registered in ascending order //Patchlevels need to be unique and registered in ascending order
if (modID == null || "".equals(modID)) { if (modID == null || modID.isEmpty()) {
throw new RuntimeException("[INTERNAL ERROR] Patches need a valid modID!"); throw new RuntimeException("[INTERNAL ERROR] Patches need a valid modID!");
} }
if (version == null || "".equals(version)) { if (version == null || version.isEmpty()) {
throw new RuntimeException("Invalid Mod-Version"); throw new RuntimeException("Invalid Mod-Version");
} }
this.version = version; this.version = version;
this.alwaysApply = alwaysApply; this.alwaysApply = alwaysApply;
this.level = ModUtil.convertModVersion(version); this.level = ModUtil.convertModVersion(version);
if (!ALL.stream() if (!ALL.stream().filter(p -> p.modID.equals(modID)).noneMatch(p -> p.level >= this.level) || this.level <= 0) {
.filter(p -> p.modID
.equals(modID))
.noneMatch(p -> p.level >= this.level) || this.level <= 0) {
throw new RuntimeException("[INTERNAL ERROR] Patch-levels need to be created in ascending order beginning with 1."); throw new RuntimeException("[INTERNAL ERROR] Patch-levels need to be created in ascending order beginning with 1.");
} }
@ -239,5 +225,4 @@ public abstract class Patch {
public List<String> getWorldDataIDPaths() { public List<String> getWorldDataIDPaths() {
return null; return null;
} }
} }

View file

@ -19,7 +19,7 @@ public class SpawnRuleEntry<M extends Mob> implements Comparable<SpawnRuleEntry>
this.rule = rule; this.rule = rule;
} }
boolean canSpawn(EntityType<M> type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) { protected boolean canSpawn(EntityType<M> type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) {
return rule.canSpawn(type, world, spawnReason, pos, random); return rule.canSpawn(type, world, spawnReason, pos, random);
} }

View file

@ -35,14 +35,15 @@ public class BaseBarrelBlockEntity extends RandomizableContainerBlockEntity {
public BaseBarrelBlockEntity(BlockPos blockPos, BlockState blockState) { public BaseBarrelBlockEntity(BlockPos blockPos, BlockState blockState) {
this(BaseBlockEntities.BARREL, blockPos, blockState); this(BaseBlockEntities.BARREL, blockPos, blockState);
} }
public CompoundTag save(CompoundTag tag) { @Override
super.save(tag); public void saveAdditional(CompoundTag tag) {
super.saveAdditional(tag);
if (!this.trySaveLootTable(tag)) { if (!this.trySaveLootTable(tag)) {
ContainerHelper.saveAllItems(tag, this.inventory); ContainerHelper.saveAllItems(tag, this.inventory);
} }
return tag; //return tag;
} }
public void load(CompoundTag tag) { public void load(CompoundTag tag) {
@ -93,7 +94,7 @@ public class BaseBarrelBlockEntity extends RandomizableContainerBlockEntity {
} }
private void scheduleUpdate() { private void scheduleUpdate() {
level.getBlockTicks().scheduleTick(getBlockPos(), getBlockState().getBlock(), 5); level.scheduleTick(getBlockPos(), getBlockState().getBlock(), 5);
} }
public void tick() { public void tick() {

View file

@ -15,6 +15,7 @@ import net.minecraft.world.item.PickaxeItem;
import net.minecraft.world.level.block.AnvilBlock; import net.minecraft.world.level.block.AnvilBlock;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.IntegerProperty; import net.minecraft.world.level.block.state.properties.IntegerProperty;
@ -40,7 +41,11 @@ public abstract class BaseAnvilBlock extends AnvilBlock implements BlockModelPro
public IntegerProperty durability; public IntegerProperty durability;
public BaseAnvilBlock(MaterialColor color) { public BaseAnvilBlock(MaterialColor color) {
super(FabricBlockSettings.copyOf(Blocks.ANVIL).mapColor(color)); this(FabricBlockSettings.copyOf(Blocks.ANVIL).color(color));
}
public BaseAnvilBlock(BlockBehaviour.Properties properties) {
super(properties);
} }
@Override @Override

View file

@ -22,6 +22,7 @@ import net.minecraft.world.level.block.BarrelBlock;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
@ -40,7 +41,11 @@ import java.util.Random;
public class BaseBarrelBlock extends BarrelBlock implements BlockModelProvider { public class BaseBarrelBlock extends BarrelBlock implements BlockModelProvider {
public BaseBarrelBlock(Block source) { public BaseBarrelBlock(Block source) {
super(FabricBlockSettings.copyOf(source).noOcclusion()); this(FabricBlockSettings.copyOf(source).noOcclusion());
}
public BaseBarrelBlock(BlockBehaviour.Properties properties) {
super(properties);
} }
@Override @Override

View file

@ -6,7 +6,6 @@ import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
public class BaseBlockNotFull extends BaseBlock { public class BaseBlockNotFull extends BaseBlock {
public BaseBlockNotFull(Properties settings) { public BaseBlockNotFull(Properties settings) {
super(settings); super(settings);
} }

View file

@ -10,6 +10,7 @@ import net.minecraft.world.item.Items;
import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
@ -24,7 +25,11 @@ import java.util.Optional;
public class BaseBookshelfBlock extends BaseBlock { public class BaseBookshelfBlock extends BaseBlock {
public BaseBookshelfBlock(Block source) { public BaseBookshelfBlock(Block source) {
super(FabricBlockSettings.copyOf(source)); this(FabricBlockSettings.copyOf(source));
}
public BaseBookshelfBlock(BlockBehaviour.Properties properties) {
super(properties);
} }
@Override @Override

View file

@ -25,7 +25,6 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
public abstract class BaseButtonBlock extends ButtonBlock implements BlockModelProvider { public abstract class BaseButtonBlock extends ButtonBlock implements BlockModelProvider {
private final Block parent; private final Block parent;
protected BaseButtonBlock(Block parent, Properties properties, boolean sensitive) { protected BaseButtonBlock(Block parent, Properties properties, boolean sensitive) {

View file

@ -10,6 +10,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.ChainBlock; import net.minecraft.world.level.block.ChainBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.MaterialColor; import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
@ -28,7 +29,11 @@ import java.util.Optional;
public class BaseChainBlock extends ChainBlock implements BlockModelProvider, RenderLayerProvider { public class BaseChainBlock extends ChainBlock implements BlockModelProvider, RenderLayerProvider {
public BaseChainBlock(MaterialColor color) { public BaseChainBlock(MaterialColor color) {
super(FabricBlockSettings.copyOf(Blocks.CHAIN).mapColor(color)); this(FabricBlockSettings.copyOf(Blocks.CHAIN).color(color));
}
public BaseChainBlock(BlockBehaviour.Properties properties) {
super(properties);
} }
@Override @Override

View file

@ -8,6 +8,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.CraftingTableBlock; import net.minecraft.world.level.block.CraftingTableBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -23,7 +24,11 @@ import java.util.Optional;
public class BaseCraftingTableBlock extends CraftingTableBlock implements BlockModelProvider { public class BaseCraftingTableBlock extends CraftingTableBlock implements BlockModelProvider {
public BaseCraftingTableBlock(Block source) { public BaseCraftingTableBlock(Block source) {
super(FabricBlockSettings.copyOf(source)); this(FabricBlockSettings.copyOf(source));
}
public BaseCraftingTableBlock(BlockBehaviour.Properties properties) {
super(properties);
} }
@Override @Override

View file

@ -2,7 +2,6 @@ package ru.bclib.blocks;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
@ -31,19 +30,25 @@ import java.util.List;
import java.util.Random; import java.util.Random;
public class BaseCropBlock extends BasePlantBlock { public class BaseCropBlock extends BasePlantBlock {
private static final VoxelShape SHAPE = Block.box(2, 0, 2, 14, 14, 14);
public static final IntegerProperty AGE = IntegerProperty.create("age", 0, 3); public static final IntegerProperty AGE = IntegerProperty.create("age", 0, 3);
private static final VoxelShape SHAPE = Block.box(2, 0, 2, 14, 14, 14);
private final Block[] terrain; private final Block[] terrain;
private final Item drop; private final Item drop;
public BaseCropBlock(Item drop, Block... terrain) { public BaseCropBlock(Item drop, Block... terrain) {
super(FabricBlockSettings.of(Material.PLANT) this(
.breakByTool(FabricToolTags.HOES) FabricBlockSettings.of(Material.PLANT)
.breakByHand(true) .breakByHand(true)
.sound(SoundType.GRASS) .sound(SoundType.GRASS)
.randomTicks() .randomTicks()
.noCollission()); .noCollission(),
drop, terrain
);
}
public BaseCropBlock(BlockBehaviour.Properties properties, Item drop, Block... terrain) {
super(properties);
this.drop = drop; this.drop = drop;
this.terrain = terrain; this.terrain = terrain;
this.registerDefaultState(defaultBlockState().setValue(AGE, 0)); this.registerDefaultState(defaultBlockState().setValue(AGE, 0));

View file

@ -12,6 +12,7 @@ import net.minecraft.util.StringRepresentable;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.DoorBlock; import net.minecraft.world.level.block.DoorBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.DoorHingeSide; import net.minecraft.world.level.block.state.properties.DoorHingeSide;
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
@ -31,7 +32,11 @@ import java.util.Optional;
public class BaseDoorBlock extends DoorBlock implements RenderLayerProvider, BlockModelProvider { public class BaseDoorBlock extends DoorBlock implements RenderLayerProvider, BlockModelProvider {
public BaseDoorBlock(Block source) { public BaseDoorBlock(Block source) {
super(FabricBlockSettings.copyOf(source).strength(3F, 3F).noOcclusion()); this(FabricBlockSettings.copyOf(source).strength(3F, 3F).noOcclusion());
}
public BaseDoorBlock(BlockBehaviour.Properties properties) {
super(properties);
} }
@Override @Override

View file

@ -37,28 +37,32 @@ import ru.bclib.util.BlocksHelper;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
@SuppressWarnings("deprecation")
public abstract class BaseDoublePlantBlock extends BaseBlockNotFull implements RenderLayerProvider, BonemealableBlock { public abstract class BaseDoublePlantBlock extends BaseBlockNotFull implements RenderLayerProvider, BonemealableBlock {
private static final VoxelShape SHAPE = Block.box(4, 2, 4, 12, 16, 12); private static final VoxelShape SHAPE = Block.box(4, 2, 4, 12, 16, 12);
public static final IntegerProperty ROTATION = BlockProperties.ROTATION; public static final IntegerProperty ROTATION = BlockProperties.ROTATION;
public static final BooleanProperty TOP = BooleanProperty.create("top"); public static final BooleanProperty TOP = BooleanProperty.create("top");
public BaseDoublePlantBlock() { public BaseDoublePlantBlock() {
super(FabricBlockSettings.of(Material.PLANT) this(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings.of(Material.PLANT)
.breakByHand(true) .breakByHand(true)
.sound(SoundType.WET_GRASS) .sound(SoundType.GRASS)
.noCollission()); .noCollission()
this.registerDefaultState(this.stateDefinition.any().setValue(TOP, false)); );
} }
public BaseDoublePlantBlock(int light) { public BaseDoublePlantBlock(int light) {
super(FabricBlockSettings.of(Material.PLANT) this(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings.of(Material.PLANT)
.breakByHand(true) .breakByHand(true)
.sound(SoundType.WET_GRASS) .sound(SoundType.GRASS)
.lightLevel((state) -> state.getValue(TOP) ? light : 0) .lightLevel((state) -> state.getValue(TOP) ? light : 0)
.noCollission()); .noCollission()
);
}
public BaseDoublePlantBlock(BlockBehaviour.Properties properties) {
super(properties);
this.registerDefaultState(this.stateDefinition.any().setValue(TOP, false)); this.registerDefaultState(this.stateDefinition.any().setValue(TOP, false));
} }
@ -68,6 +72,7 @@ public abstract class BaseDoublePlantBlock extends BaseBlockNotFull implements R
} }
@Override @Override
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
Vec3 vec3d = state.getOffset(view, pos); Vec3 vec3d = state.getOffset(view, pos);
return SHAPE.move(vec3d.x, vec3d.y, vec3d.z); return SHAPE.move(vec3d.x, vec3d.y, vec3d.z);
@ -79,6 +84,7 @@ public abstract class BaseDoublePlantBlock extends BaseBlockNotFull implements R
} }
@Override @Override
@SuppressWarnings("deprecation")
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockState down = world.getBlockState(pos.below()); BlockState down = world.getBlockState(pos.below());
BlockState up = world.getBlockState(pos.above()); BlockState up = world.getBlockState(pos.above());
@ -94,6 +100,7 @@ public abstract class BaseDoublePlantBlock extends BaseBlockNotFull implements R
protected abstract boolean isTerrain(BlockState state); protected abstract boolean isTerrain(BlockState state);
@Override @Override
@SuppressWarnings("deprecation")
public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
if (!canStayAt(state, world, pos)) { if (!canStayAt(state, world, pos)) {
return Blocks.AIR.defaultBlockState(); return Blocks.AIR.defaultBlockState();

View file

@ -20,6 +20,7 @@ import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker; import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
@ -39,7 +40,11 @@ import java.util.Optional;
public class BaseFurnaceBlock extends FurnaceBlock implements BlockModelProvider, RenderLayerProvider { public class BaseFurnaceBlock extends FurnaceBlock implements BlockModelProvider, RenderLayerProvider {
public BaseFurnaceBlock(Block source) { public BaseFurnaceBlock(Block source) {
super(FabricBlockSettings.copyOf(source).luminance(state -> state.getValue(LIT) ? 13 : 0)); this(FabricBlockSettings.copyOf(source).lightLevel(state -> state.getValue(LIT) ? 13 : 0));
}
public BaseFurnaceBlock(BlockBehaviour.Properties properties) {
super(properties);
} }
@Override @Override

View file

@ -9,6 +9,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.LadderBlock; import net.minecraft.world.level.block.LadderBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -26,7 +27,11 @@ import java.util.Optional;
public class BaseLadderBlock extends LadderBlock implements RenderLayerProvider, BlockModelProvider { public class BaseLadderBlock extends LadderBlock implements RenderLayerProvider, BlockModelProvider {
public BaseLadderBlock(Block block) { public BaseLadderBlock(Block block) {
super(FabricBlockSettings.copyOf(block).noOcclusion()); this(FabricBlockSettings.copyOf(block).noOcclusion());
}
public BaseLadderBlock(BlockBehaviour.Properties properties) {
super(properties);
} }
@Override @Override

View file

@ -1,10 +1,13 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.mininglevel.v1.FabricMineableTags;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.Tag.Named;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
@ -15,34 +18,35 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.MaterialColor; import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import ru.bclib.api.TagAPI;
import ru.bclib.client.render.BCLRenderLayer; import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.BlockModelProvider; import ru.bclib.interfaces.BlockModelProvider;
import ru.bclib.interfaces.RenderLayerProvider; import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider;
import ru.bclib.util.MHelper; import ru.bclib.util.MHelper;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
public class BaseLeavesBlock extends LeavesBlock implements BlockModelProvider, RenderLayerProvider { public class BaseLeavesBlock extends LeavesBlock implements BlockModelProvider, RenderLayerProvider, TagProvider {
protected final Block sapling; protected final Block sapling;
private static FabricBlockSettings makeLeaves(MaterialColor color) { private static FabricBlockSettings makeLeaves(MaterialColor color) {
return FabricBlockSettings.copyOf(Blocks.OAK_LEAVES) return FabricBlockSettings
.mapColor(color) .copyOf(Blocks.OAK_LEAVES)
.breakByTool(FabricToolTags.HOES) .mapColor(color)
.breakByTool(FabricToolTags.SHEARS) .requiresTool()
.breakByHand(true) .allowsSpawning((state, world, pos, type) -> false)
.allowsSpawning((state, world, pos, type) -> false) .suffocates((state, world, pos) -> false)
.suffocates((state, world, pos) -> false) .blockVision((state, world, pos) -> false);
.blockVision((state, world, pos) -> false);
} }
public BaseLeavesBlock(Block sapling, MaterialColor color, Consumer<FabricBlockSettings> customizeProperties) { public BaseLeavesBlock(Block sapling, MaterialColor color, Consumer<FabricBlockSettings> customizeProperties) {
super(BaseBlock.acceptAndReturn(customizeProperties, makeLeaves(color))); super(BaseBlock.acceptAndReturn(customizeProperties, makeLeaves(color)));
this.sapling = sapling; this.sapling = sapling;
} }
public BaseLeavesBlock(Block sapling, MaterialColor color, int light, Consumer<FabricBlockSettings> customizeProperties) { public BaseLeavesBlock(Block sapling, MaterialColor color, int light, Consumer<FabricBlockSettings> customizeProperties) {
super(BaseBlock.acceptAndReturn(customizeProperties, makeLeaves(color).luminance(light))); super(BaseBlock.acceptAndReturn(customizeProperties, makeLeaves(color).luminance(light)));
this.sapling = sapling; this.sapling = sapling;
@ -68,7 +72,7 @@ public class BaseLeavesBlock extends LeavesBlock implements BlockModelProvider,
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) { public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
ItemStack tool = builder.getParameter(LootContextParams.TOOL); ItemStack tool = builder.getParameter(LootContextParams.TOOL);
if (tool != null) { if (tool != null) {
if (FabricToolTags.SHEARS.contains(tool.getItem()) || EnchantmentHelper.getItemEnchantmentLevel( if (tool.isCorrectToolForDrops(state) || EnchantmentHelper.getItemEnchantmentLevel(
Enchantments.SILK_TOUCH, Enchantments.SILK_TOUCH,
tool tool
) > 0) { ) > 0) {
@ -87,4 +91,11 @@ public class BaseLeavesBlock extends LeavesBlock implements BlockModelProvider,
public BlockModel getItemModel(ResourceLocation resourceLocation) { public BlockModel getItemModel(ResourceLocation resourceLocation) {
return getBlockModel(resourceLocation, defaultBlockState()); return getBlockModel(resourceLocation, defaultBlockState());
} }
@Override
public void addTags(List<Named<Block>> blockTags, List<Named<Item>> itemTags) {
blockTags.add(FabricMineableTags.SHEARS_MINEABLE);
blockTags.add(TagAPI.MINEABLE_HOE);
blockTags.add(BlockTags.LEAVES);
}
} }

View file

@ -12,6 +12,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.IronBarsBlock; import net.minecraft.world.level.block.IronBarsBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -29,7 +30,11 @@ import java.util.Optional;
public class BaseMetalBarsBlock extends IronBarsBlock implements BlockModelProvider, RenderLayerProvider { public class BaseMetalBarsBlock extends IronBarsBlock implements BlockModelProvider, RenderLayerProvider {
public BaseMetalBarsBlock(Block source) { public BaseMetalBarsBlock(Block source) {
super(FabricBlockSettings.copyOf(source).strength(5.0F, 6.0F).noOcclusion()); this(FabricBlockSettings.copyOf(source).strength(5.0F, 6.0F).noOcclusion());
}
public BaseMetalBarsBlock(BlockBehaviour.Properties properties) {
super(properties);
} }
@Override @Override

View file

@ -1,6 +1,8 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.fabricmc.fabric.impl.object.builder.FabricBlockInternals;
import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
@ -22,32 +24,49 @@ import ru.bclib.util.MHelper;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Supplier;
public class BaseOreBlock extends OreBlock implements BlockModelProvider { public class BaseOreBlock extends OreBlock implements BlockModelProvider {
private final Item dropItem; private final Supplier<Item> dropItem;
private final int minCount; private final int minCount;
private final int maxCount; private final int maxCount;
public BaseOreBlock(Item drop, int minCount, int maxCount, int experience) { public BaseOreBlock(Supplier<Item> drop, int minCount, int maxCount, int experience) {
this(drop, minCount, maxCount, experience, FabricBlockSettings.of(Material.STONE, MaterialColor.SAND) this(drop, minCount, maxCount, experience, 0);
.hardness(3F)
.resistance(9F)
.requiresCorrectToolForDrops()
.sound(SoundType.STONE));
} }
public BaseOreBlock(Item drop, int minCount, int maxCount, int experience, Properties properties) { public BaseOreBlock(Supplier<Item> drop, int minCount, int maxCount, int experience, int miningLevel) {
super(properties, UniformInt.of(experience>0?1:0, experience)); this(
FabricBlockSettings
.of(Material.STONE, MaterialColor.SAND)
.requiresTool()
.destroyTime(3F)
.explosionResistance(9F)
.sound(SoundType.STONE),
drop, minCount, maxCount, experience, miningLevel
);
}
public BaseOreBlock(Properties properties, Supplier<Item> drop, int minCount, int maxCount, int experience) {
this(properties, drop, minCount, maxCount, experience, 0);
}
public BaseOreBlock(Properties properties, Supplier<Item> drop, int minCount, int maxCount, int experience, int miningLevel) {
super(makeProps(properties, miningLevel), UniformInt.of(experience>0?1:0, experience));
this.dropItem = drop; this.dropItem = drop;
this.minCount = minCount; this.minCount = minCount;
this.maxCount = maxCount; this.maxCount = maxCount;
} }
private static Properties makeProps(Properties properties, int level){
FabricBlockInternals.computeExtraData(properties).addMiningLevel(FabricToolTags.PICKAXES, level);
return properties;
}
@Override @Override
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) { public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
return getDroppedItems(this, dropItem, maxCount, minCount, state, builder); return getDroppedItems(this, dropItem.get(), maxCount, minCount, state, builder);
} }
public static List<ItemStack> getDroppedItems(ItemLike block, Item dropItem, int maxCount, int minCount, BlockState state, LootContext.Builder builder) { public static List<ItemStack> getDroppedItems(ItemLike block, Item dropItem, int maxCount, int minCount, BlockState state, LootContext.Builder builder) {

View file

@ -30,7 +30,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@SuppressWarnings("deprecation")
public class BasePathBlock extends BaseBlockNotFull { public class BasePathBlock extends BaseBlockNotFull {
private static final VoxelShape SHAPE = Block.box(0, 0, 0, 16, 15, 16); private static final VoxelShape SHAPE = Block.box(0, 0, 0, 16, 15, 16);
@ -56,11 +55,13 @@ public class BasePathBlock extends BaseBlockNotFull {
} }
@Override @Override
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE; return SHAPE;
} }
@Override @Override
@SuppressWarnings("deprecation")
public VoxelShape getCollisionShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { public VoxelShape getCollisionShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE; return SHAPE;
} }

View file

@ -3,6 +3,7 @@ package ru.bclib.blocks;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.mininglevel.v1.FabricMineableTags;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags; import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.renderer.block.model.BlockModel;
@ -10,7 +11,9 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.Tag.Named;
import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
@ -31,18 +34,19 @@ import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import ru.bclib.api.TagAPI;
import ru.bclib.client.models.BasePatterns; import ru.bclib.client.models.BasePatterns;
import ru.bclib.client.models.ModelsHelper; import ru.bclib.client.models.ModelsHelper;
import ru.bclib.client.models.PatternsHelper; import ru.bclib.client.models.PatternsHelper;
import ru.bclib.client.render.BCLRenderLayer; import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider; import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
@SuppressWarnings("deprecation") public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderLayerProvider, BonemealableBlock, TagProvider {
public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderLayerProvider, BonemealableBlock {
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12); private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12);
public BasePlantBlock() { public BasePlantBlock() {
@ -54,20 +58,24 @@ public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderL
} }
public BasePlantBlock(boolean replaceable) { public BasePlantBlock(boolean replaceable) {
super(FabricBlockSettings.of(replaceable ? Material.REPLACEABLE_PLANT : Material.PLANT) this(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings
.breakByHand(true) .of(replaceable ? Material.REPLACEABLE_PLANT : Material.PLANT)
.sound(SoundType.GRASS) .breakByHand(true)
.noCollission()); .sound(SoundType.GRASS)
.noCollission()
);
} }
public BasePlantBlock(boolean replaceable, int light) { public BasePlantBlock(boolean replaceable, int light) {
super(FabricBlockSettings.of(replaceable ? Material.REPLACEABLE_PLANT : Material.PLANT) this(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings
.breakByHand(true) .of(replaceable ? Material.REPLACEABLE_PLANT : Material.PLANT)
.luminance(light) .breakByHand(true)
.sound(SoundType.GRASS) .luminance(light)
.noCollission()); .sound(SoundType.GRASS)
.noCollission()
);
} }
public BasePlantBlock(Properties settings) { public BasePlantBlock(Properties settings) {
@ -77,6 +85,7 @@ public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderL
protected abstract boolean isTerrain(BlockState state); protected abstract boolean isTerrain(BlockState state);
@Override @Override
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
Vec3 vec3d = state.getOffset(view, pos); Vec3 vec3d = state.getOffset(view, pos);
return SHAPE.move(vec3d.x, vec3d.y, vec3d.z); return SHAPE.move(vec3d.x, vec3d.y, vec3d.z);
@ -88,12 +97,14 @@ public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderL
} }
@Override @Override
@SuppressWarnings("deprecation")
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockState down = world.getBlockState(pos.below()); BlockState down = world.getBlockState(pos.below());
return isTerrain(down); return isTerrain(down);
} }
@Override @Override
@SuppressWarnings("deprecation")
public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
if (!canSurvive(state, world, pos)) { if (!canSurvive(state, world, pos)) {
return Blocks.AIR.defaultBlockState(); return Blocks.AIR.defaultBlockState();
@ -157,4 +168,10 @@ public abstract class BasePlantBlock extends BaseBlockNotFull implements RenderL
Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_CROSS, resourceLocation); Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_CROSS, resourceLocation);
return ModelsHelper.fromPattern(pattern); return ModelsHelper.fromPattern(pattern);
} }
@Override
public void addTags(List<Named<Block>> blockTags, List<Named<Item>> itemTags) {
blockTags.add(FabricMineableTags.SHEARS_MINEABLE);
blockTags.add(TagAPI.MINEABLE_HOE);
}
} }

View file

@ -1,7 +1,6 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
@ -19,12 +18,13 @@ public abstract class BasePlantWithAgeBlock extends BasePlantBlock {
public static final IntegerProperty AGE = BlockProperties.AGE; public static final IntegerProperty AGE = BlockProperties.AGE;
public BasePlantWithAgeBlock() { public BasePlantWithAgeBlock() {
this(FabricBlockSettings.of(Material.PLANT) this(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings.of(Material.PLANT)
.breakByHand(true) .breakByHand(true)
.sound(SoundType.GRASS) .sound(SoundType.GRASS)
.randomTicks() .randomTicks()
.noCollission()); .noCollission()
);
} }
public BasePlantWithAgeBlock(Properties settings) { public BasePlantWithAgeBlock(Properties settings) {

View file

@ -27,7 +27,7 @@ public class BaseRotatedPillarBlock extends RotatedPillarBlock implements BlockM
} }
public BaseRotatedPillarBlock(Block block) { public BaseRotatedPillarBlock(Block block) {
super(FabricBlockSettings.copyOf(block)); this(FabricBlockSettings.copyOf(block));
} }
@Override @Override

View file

@ -64,10 +64,7 @@ public class BaseSignBlock extends SignBlock implements BlockModelProvider, Cust
public BaseSignBlock(Block source) { public BaseSignBlock(Block source) {
super(FabricBlockSettings.copyOf(source).strength(1.0F, 1.0F).noCollission().noOcclusion(), WoodType.OAK); super(FabricBlockSettings.copyOf(source).strength(1.0F, 1.0F).noCollission().noOcclusion(), WoodType.OAK);
this.registerDefaultState(this.stateDefinition.any() this.registerDefaultState(this.stateDefinition.any().setValue(ROTATION, 0).setValue(FLOOR, false).setValue(WATERLOGGED, false));
.setValue(ROTATION, 0)
.setValue(FLOOR, false)
.setValue(WATERLOGGED, false));
this.parent = source; this.parent = source;
} }
@ -105,7 +102,7 @@ public class BaseSignBlock extends SignBlock implements BlockModelProvider, Cust
@Override @Override
public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
if (state.getValue(WATERLOGGED)) { if (state.getValue(WATERLOGGED)) {
world.getLiquidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world));
} }
if (!canSurvive(state, world, pos)) { if (!canSurvive(state, world, pos)) {
return state.getValue(WATERLOGGED) ? state.getFluidState() return state.getValue(WATERLOGGED) ? state.getFluidState()
@ -181,18 +178,16 @@ public class BaseSignBlock extends SignBlock implements BlockModelProvider, Cust
@Override @Override
public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) { public boolean canPlaceLiquid(BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) {
// TODO Auto-generated method stub
return super.canPlaceLiquid(world, pos, state, fluid); return super.canPlaceLiquid(world, pos, state, fluid);
} }
@Override @Override
public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) { public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) {
// TODO Auto-generated method stub
return super.placeLiquid(world, pos, state, fluidState); return super.placeLiquid(world, pos, state, fluidState);
} }
@Override @Override
public BlockItem getCustomItem(ResourceLocation blockID, FabricItemSettings settings) { public BlockItem getCustomItem(ResourceLocation blockID, FabricItemSettings settings) {
return new BlockItem(this, settings.maxCount(16)); return new BlockItem(this, settings.stacksTo(16));
} }
} }

View file

@ -27,7 +27,6 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
public class BaseStairsBlock extends StairBlock implements BlockModelProvider { public class BaseStairsBlock extends StairBlock implements BlockModelProvider {
private final Block parent; private final Block parent;
public BaseStairsBlock(Block source) { public BaseStairsBlock(Block source) {

View file

@ -6,7 +6,6 @@ import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
public class BaseStoneButtonBlock extends BaseButtonBlock { public class BaseStoneButtonBlock extends BaseButtonBlock {
public BaseStoneButtonBlock(Block source) { public BaseStoneButtonBlock(Block source) {
super(source, FabricBlockSettings.copyOf(source).noOcclusion(), false); super(source, FabricBlockSettings.copyOf(source).noOcclusion(), false);
} }

View file

@ -20,7 +20,7 @@ public class BaseStripableLogBlock extends BaseRotatedPillarBlock {
private final Block striped; private final Block striped;
public BaseStripableLogBlock(MaterialColor color, Block striped) { public BaseStripableLogBlock(MaterialColor color, Block striped) {
super(FabricBlockSettings.copyOf(striped).mapColor(color)); super(FabricBlockSettings.copyOf(striped).color(color));
this.striped = striped; this.striped = striped;
} }

View file

@ -10,6 +10,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.TrapDoorBlock; import net.minecraft.world.level.block.TrapDoorBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.Half; import net.minecraft.world.level.block.state.properties.Half;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
@ -29,7 +30,11 @@ import java.util.Optional;
public class BaseTrapdoorBlock extends TrapDoorBlock implements RenderLayerProvider, BlockModelProvider { public class BaseTrapdoorBlock extends TrapDoorBlock implements RenderLayerProvider, BlockModelProvider {
public BaseTrapdoorBlock(Block source) { public BaseTrapdoorBlock(Block source) {
super(FabricBlockSettings.copyOf(source).strength(3.0F, 3.0F).noOcclusion()); this(FabricBlockSettings.copyOf(source).strength(3.0F, 3.0F).noOcclusion());
}
public BaseTrapdoorBlock(BlockBehaviour.Properties properties) {
super(properties);
} }
@Override @Override

View file

@ -1,7 +1,6 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
@ -15,22 +14,25 @@ import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.Material;
public abstract class BaseUnderwaterWallPlantBlock extends BaseWallPlantBlock implements LiquidBlockContainer { public abstract class BaseUnderwaterWallPlantBlock extends BaseWallPlantBlock implements LiquidBlockContainer {
public BaseUnderwaterWallPlantBlock() { public BaseUnderwaterWallPlantBlock() {
super(FabricBlockSettings.of(Material.WATER_PLANT) this(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings
.breakByHand(true) .of(Material.WATER_PLANT)
.sound(SoundType.WET_GRASS) .breakByHand(true)
.noCollission()); .sound(SoundType.WET_GRASS)
.noCollission()
);
} }
public BaseUnderwaterWallPlantBlock(int light) { public BaseUnderwaterWallPlantBlock(int light) {
super(FabricBlockSettings.of(Material.WATER_PLANT) this(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings
.breakByHand(true) .of(Material.WATER_PLANT)
.luminance(light) .breakByHand(true)
.sound(SoundType.WET_GRASS) .luminance(light)
.noCollission()); .sound(SoundType.WET_GRASS)
.noCollission()
);
} }
public BaseUnderwaterWallPlantBlock(Properties settings) { public BaseUnderwaterWallPlantBlock(Properties settings) {

View file

@ -50,12 +50,18 @@ public class BaseVineBlock extends BaseBlockNotFull implements RenderLayerProvid
} }
public BaseVineBlock(int light, boolean bottomOnly) { public BaseVineBlock(int light, boolean bottomOnly) {
super(FabricBlockSettings.of(Material.PLANT) this(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings
.breakByHand(true) .of(Material.PLANT)
.sound(SoundType.GRASS) .breakByHand(true)
.lightLevel((state) -> bottomOnly ? state.getValue(SHAPE) == TripleShape.BOTTOM ? light : 0 : light) .sound(SoundType.GRASS)
.noCollission()); .lightLevel((state) -> bottomOnly ? state.getValue(SHAPE) == TripleShape.BOTTOM ? light : 0 : light)
.noCollission()
);
}
public BaseVineBlock(BlockBehaviour.Properties properties) {
super(properties);
this.registerDefaultState(this.stateDefinition.any().setValue(SHAPE, TripleShape.BOTTOM)); this.registerDefaultState(this.stateDefinition.any().setValue(SHAPE, TripleShape.BOTTOM));
} }

View file

@ -26,7 +26,6 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
public class BaseWallBlock extends WallBlock implements BlockModelProvider { public class BaseWallBlock extends WallBlock implements BlockModelProvider {
private final Block parent; private final Block parent;
public BaseWallBlock(Block source) { public BaseWallBlock(Block source) {

View file

@ -3,7 +3,6 @@ package ru.bclib.blocks;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
@ -29,32 +28,32 @@ import java.util.EnumMap;
public abstract class BaseWallPlantBlock extends BasePlantBlock { public abstract class BaseWallPlantBlock extends BasePlantBlock {
private static final EnumMap<Direction, VoxelShape> SHAPES = Maps.newEnumMap(ImmutableMap.of( private static final EnumMap<Direction, VoxelShape> SHAPES = Maps.newEnumMap(ImmutableMap.of(
Direction.NORTH, Direction.NORTH, Block.box(1, 1, 8, 15, 15, 16),
Block.box(1, 1, 8, 15, 15, 16), Direction.SOUTH, Block.box(1, 1, 0, 15, 15, 8),
Direction.SOUTH, Direction.WEST, Block.box(8, 1, 1, 16, 15, 15),
Block.box(1, 1, 0, 15, 15, 8), Direction.EAST, Block.box(0, 1, 1, 8, 15, 15)
Direction.WEST,
Block.box(8, 1, 1, 16, 15, 15),
Direction.EAST,
Block.box(0, 1, 1, 8, 15, 15)
)); ));
public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING;
public BaseWallPlantBlock() { public BaseWallPlantBlock() {
this(FabricBlockSettings.of(Material.PLANT) this(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings
.breakByHand(true) .of(Material.PLANT)
.sound(SoundType.GRASS) .breakByHand(true)
.noCollission()); .sound(SoundType.GRASS)
.noCollission()
);
} }
public BaseWallPlantBlock(int light) { public BaseWallPlantBlock(int light) {
this(FabricBlockSettings.of(Material.PLANT) this(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings
.breakByHand(true) .of(Material.PLANT)
.luminance(light) .breakByHand(true)
.sound(SoundType.GRASS) .luminance(light)
.noCollission()); .sound(SoundType.GRASS)
.noCollission()
);
} }
public BaseWallPlantBlock(Properties settings) { public BaseWallPlantBlock(Properties settings) {

View file

@ -6,7 +6,6 @@ import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
public class BaseWoodenButtonBlock extends BaseButtonBlock { public class BaseWoodenButtonBlock extends BaseButtonBlock {
public BaseWoodenButtonBlock(Block source) { public BaseWoodenButtonBlock(Block source) {
super(source, FabricBlockSettings.copyOf(source).strength(0.5F, 0.5F).noOcclusion(), true); super(source, FabricBlockSettings.copyOf(source).strength(0.5F, 0.5F).noOcclusion(), true);
} }

View file

@ -4,18 +4,27 @@ import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
public abstract class FeatureHangingSaplingBlock extends FeatureSaplingBlockCommon{ import java.util.function.Function;
public abstract class FeatureHangingSaplingBlock extends FeatureSaplingBlock {
private static final VoxelShape SHAPE = Block.box(4, 2, 4, 12, 16, 12); private static final VoxelShape SHAPE = Block.box(4, 2, 4, 12, 16, 12);
public FeatureHangingSaplingBlock() {
super(); public FeatureHangingSaplingBlock(Function<BlockState, Feature<?>> featureSupplier) {
super(featureSupplier);
} }
public FeatureHangingSaplingBlock(int light) { public FeatureHangingSaplingBlock(Function<BlockState, Feature<?>> featureSupplier, int light) {
super(light); super(light, featureSupplier);
}
public FeatureHangingSaplingBlock(BlockBehaviour.Properties properties, Function<BlockState, Feature<?>> featureSupplier) {
super(properties, featureSupplier);
} }
@Override @Override

View file

@ -1,22 +1,137 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SaplingBlock;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
import ru.bclib.client.models.BasePatterns;
import ru.bclib.client.models.ModelsHelper;
import ru.bclib.client.models.PatternsHelper;
import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.BlockModelProvider;
import ru.bclib.interfaces.RenderLayerProvider;
@SuppressWarnings("deprecation") import java.util.Collections;
public abstract class FeatureSaplingBlock extends FeatureSaplingBlockCommon { import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.function.Function;
public class FeatureSaplingBlock extends SaplingBlock implements RenderLayerProvider, BlockModelProvider {
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12); private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12);
private final Function<BlockState, Feature<?>> feature;
public FeatureSaplingBlock() { public FeatureSaplingBlock(Function<BlockState, Feature<?>> featureSupplier) {
super(); this(FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.collidable(false)
.instabreak()
.sound(SoundType.GRASS)
.randomTicks(),
featureSupplier
);
} }
public FeatureSaplingBlock(int light) { public FeatureSaplingBlock(int light, Function<BlockState, Feature<?>> featureSupplier) {
super(light); this(FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.collidable(false)
.luminance(light)
.instabreak()
.sound(SoundType.GRASS)
.randomTicks(),
featureSupplier
);
}
public FeatureSaplingBlock(BlockBehaviour.Properties properties, Function<BlockState, Feature<?>> featureSupplier) {
super(null, properties);
this.feature = featureSupplier;
}
protected Feature<?> getFeature(BlockState state) {
return feature.apply(state);
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
return Collections.singletonList(new ItemStack(this));
}
@Override
public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
if (!canSurvive(state, world, pos)) return Blocks.AIR.defaultBlockState();
else return state;
}
@Override
public boolean isBonemealSuccess(Level world, Random random, BlockPos pos, BlockState state) {
return random.nextInt(16) == 0;
}
@Override
public void advanceTree(ServerLevel world, BlockPos pos, BlockState blockState, Random random) {
FeaturePlaceContext context = new FeaturePlaceContext(
Optional.empty(),
world,
world.getChunkSource().getGenerator(),
random,
pos,
null
);
getFeature(blockState).place(context);
}
@Override
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) {
this.tick(state, world, pos, random);
}
@Override
public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) {
super.tick(state, world, pos, random);
if (isBonemealSuccess(world, random, pos, state)) {
performBonemeal(world, random, pos, state);
}
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
@Override
@Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation resourceLocation) {
return ModelsHelper.createBlockItem(resourceLocation);
}
@Override
@Environment(EnvType.CLIENT)
public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) {
Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_CROSS, resourceLocation);
return ModelsHelper.fromPattern(pattern);
} }
@Override @Override

View file

@ -1,129 +0,0 @@
package ru.bclib.blocks;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SaplingBlock;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.storage.loot.LootContext;
import org.jetbrains.annotations.Nullable;
import ru.bclib.client.models.BasePatterns;
import ru.bclib.client.models.ModelsHelper;
import ru.bclib.client.models.PatternsHelper;
import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.BlockModelProvider;
import ru.bclib.interfaces.RenderLayerProvider;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Random;
abstract class FeatureSaplingBlockCommon extends SaplingBlock implements RenderLayerProvider, BlockModelProvider {
public FeatureSaplingBlockCommon() {
super(
null,
FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.collidable(false)
.instabreak()
.sound(SoundType.GRASS)
.randomTicks()
);
}
public FeatureSaplingBlockCommon(int light) {
super(
null,
FabricBlockSettings.of(Material.PLANT)
.breakByHand(true)
.collidable(false)
.luminance(light)
.instabreak()
.sound(SoundType.GRASS)
.randomTicks()
);
}
@Deprecated
/**
* Override {@link #getFeature(BlockState)} directly. Will be removed in 5.x
*/
protected Feature<?> getFeature() { return null; }
protected Feature<?> getFeature(BlockState state){
return getFeature();
}
@Override
public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
return Collections.singletonList(new ItemStack(this));
}
@Override
public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
if (!canSurvive(state, world, pos)) return Blocks.AIR.defaultBlockState();
else return state;
}
@Override
public boolean isBonemealSuccess(Level world, Random random, BlockPos pos, BlockState state) {
return random.nextInt(16) == 0;
}
@Override
public void advanceTree(ServerLevel world, BlockPos pos, BlockState blockState, Random random) {
FeaturePlaceContext context = new FeaturePlaceContext(
world,
world.getChunkSource().getGenerator(),
random,
pos,
null
);
getFeature(blockState).place(context);
}
@Override
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) {
this.tick(state, world, pos, random);
}
@Override
public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) {
super.tick(state, world, pos, random);
if (isBonemealSuccess(world, random, pos, state)) {
performBonemeal(world, random, pos, state);
}
}
@Override
public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT;
}
@Override
@Environment(EnvType.CLIENT)
public BlockModel getItemModel(ResourceLocation resourceLocation) {
return ModelsHelper.createBlockItem(resourceLocation);
}
@Override
@Environment(EnvType.CLIENT)
public @Nullable BlockModel getBlockModel(ResourceLocation resourceLocation, BlockState blockState) {
Optional<String> pattern = PatternsHelper.createJson(BasePatterns.BLOCK_CROSS, resourceLocation);
return ModelsHelper.fromPattern(pattern);
}
}

View file

@ -1,38 +1,55 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import net.fabricmc.fabric.api.mininglevel.v1.FabricMineableTags;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.Tag.Named;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor; import net.minecraft.world.level.material.MaterialColor;
import ru.bclib.api.TagAPI; import ru.bclib.api.TagAPI;
import ru.bclib.client.render.BCLRenderLayer; import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider; import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider;
public class SimpleLeavesBlock extends BaseBlockNotFull implements RenderLayerProvider { import java.util.List;
public class SimpleLeavesBlock extends BaseBlockNotFull implements RenderLayerProvider, TagProvider {
public SimpleLeavesBlock(MaterialColor color) { public SimpleLeavesBlock(MaterialColor color) {
super(FabricBlockSettings.of(Material.LEAVES) this(
.strength(0.2F) FabricBlockSettings
.mapColor(color) .of(Material.LEAVES)
.sound(SoundType.GRASS) .strength(0.2F)
.noOcclusion() .color(color)
.isValidSpawn((state, world, pos, type) -> false) .sound(SoundType.GRASS)
.isSuffocating((state, world, pos) -> false) .noOcclusion()
.isViewBlocking((state, world, pos) -> false)); .isValidSpawn((state, world, pos, type) -> false)
.isSuffocating((state, world, pos) -> false)
TagAPI.addTags(this, TagAPI.BLOCK_LEAVES); .isViewBlocking((state, world, pos) -> false)
);
} }
public SimpleLeavesBlock(MaterialColor color, int light) { public SimpleLeavesBlock(MaterialColor color, int light) {
super(FabricBlockSettings.of(Material.LEAVES) this(
.luminance(light) FabricBlockSettings
.mapColor(color) .of(Material.LEAVES)
.strength(0.2F) .luminance(light)
.sound(SoundType.GRASS) .color(color)
.noOcclusion() .strength(0.2F)
.isValidSpawn((state, world, pos, type) -> false) .sound(SoundType.GRASS)
.isSuffocating((state, world, pos) -> false) .noOcclusion()
.isViewBlocking((state, world, pos) -> false)); .isValidSpawn((state, world, pos, type) -> false)
.isSuffocating((state, world, pos) -> false)
.isViewBlocking((state, world, pos) -> false)
);
}
public SimpleLeavesBlock(BlockBehaviour.Properties properties) {
super(properties);
// TODO handle all tags instead of adding them like this
TagAPI.addTags(this, TagAPI.BLOCK_LEAVES); TagAPI.addTags(this, TagAPI.BLOCK_LEAVES);
} }
@ -40,4 +57,11 @@ public class SimpleLeavesBlock extends BaseBlockNotFull implements RenderLayerPr
public BCLRenderLayer getRenderLayer() { public BCLRenderLayer getRenderLayer() {
return BCLRenderLayer.CUTOUT; return BCLRenderLayer.CUTOUT;
} }
@Override
public void addTags(List<Named<Block>> blockTags, List<Named<Item>> itemTags) {
blockTags.add(FabricMineableTags.SHEARS_MINEABLE);
blockTags.add(TagAPI.MINEABLE_HOE);
blockTags.add(BlockTags.LEAVES);
}
} }

View file

@ -22,6 +22,7 @@ import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlockContainer; import net.minecraft.world.level.block.LiquidBlockContainer;
import net.minecraft.world.level.block.SimpleWaterloggedBlock; import net.minecraft.world.level.block.SimpleWaterloggedBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BlockStateProperties;
@ -50,11 +51,12 @@ public class StalactiteBlock extends BaseBlockNotFull implements SimpleWaterlogg
private static final VoxelShape[] SHAPES; private static final VoxelShape[] SHAPES;
public StalactiteBlock(Block source) { public StalactiteBlock(Block source) {
super(FabricBlockSettings.copy(source).noOcclusion()); this(FabricBlockSettings.copy(source).noOcclusion());
this.registerDefaultState(getStateDefinition().any() }
.setValue(SIZE, 0)
.setValue(IS_FLOOR, true) public StalactiteBlock(BlockBehaviour.Properties properties) {
.setValue(WATERLOGGED, false)); super(properties);
this.registerDefaultState(getStateDefinition().any().setValue(SIZE, 0).setValue(IS_FLOOR, true).setValue(WATERLOGGED, false));
} }
@Override @Override

View file

@ -20,7 +20,7 @@ public class StripableBarkBlock extends BaseBarkBlock {
private final Block striped; private final Block striped;
public StripableBarkBlock(MaterialColor color, Block striped) { public StripableBarkBlock(MaterialColor color, Block striped) {
super(FabricBlockSettings.copyOf(striped).mapColor(color)); super(FabricBlockSettings.copyOf(striped).color(color));
this.striped = striped; this.striped = striped;
} }

View file

@ -1,12 +1,15 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.mininglevel.v1.FabricMineableTags;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags; import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.Tag.Named;
import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
@ -30,31 +33,36 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import ru.bclib.api.TagAPI;
import ru.bclib.client.render.BCLRenderLayer; import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider; import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
@SuppressWarnings("deprecation") public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements RenderLayerProvider, BonemealableBlock, LiquidBlockContainer, TagProvider {
public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements RenderLayerProvider, BonemealableBlock, LiquidBlockContainer {
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12); private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 14, 12);
public UnderwaterPlantBlock() { public UnderwaterPlantBlock() {
super(FabricBlockSettings.of(Material.WATER_PLANT) this(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings
.breakByHand(true) .of(Material.WATER_PLANT)
.sound(SoundType.WET_GRASS) .breakByHand(true)
.noCollission()); .sound(SoundType.WET_GRASS)
.noCollission()
);
} }
public UnderwaterPlantBlock(int light) { public UnderwaterPlantBlock(int light) {
super(FabricBlockSettings.of(Material.WATER_PLANT) this(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings
.breakByHand(true) .of(Material.WATER_PLANT)
.luminance(light) .breakByHand(true)
.sound(SoundType.WET_GRASS) .luminance(light)
.noCollission()); .sound(SoundType.WET_GRASS)
.noCollission()
);
} }
public UnderwaterPlantBlock(Properties settings) { public UnderwaterPlantBlock(Properties settings) {
@ -62,6 +70,7 @@ public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements R
} }
@Override @Override
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
Vec3 vec3d = state.getOffset(view, pos); Vec3 vec3d = state.getOffset(view, pos);
return SHAPE.move(vec3d.x, vec3d.y, vec3d.z); return SHAPE.move(vec3d.x, vec3d.y, vec3d.z);
@ -73,6 +82,7 @@ public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements R
} }
@Override @Override
@SuppressWarnings("deprecation")
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockState down = world.getBlockState(pos.below()); BlockState down = world.getBlockState(pos.below());
state = world.getBlockState(pos); state = world.getBlockState(pos);
@ -82,6 +92,7 @@ public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements R
protected abstract boolean isTerrain(BlockState state); protected abstract boolean isTerrain(BlockState state);
@Override @Override
@SuppressWarnings("deprecation")
public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
if (!canSurvive(state, world, pos)) { if (!canSurvive(state, world, pos)) {
world.destroyBlock(pos, true); world.destroyBlock(pos, true);
@ -144,7 +155,14 @@ public abstract class UnderwaterPlantBlock extends BaseBlockNotFull implements R
} }
@Override @Override
@SuppressWarnings("deprecation")
public FluidState getFluidState(BlockState state) { public FluidState getFluidState(BlockState state) {
return Fluids.WATER.getSource(false); return Fluids.WATER.getSource(false);
} }
@Override
public void addTags(List<Named<Block>> blockTags, List<Named<Item>> itemTags) {
blockTags.add(FabricMineableTags.SHEARS_MINEABLE);
blockTags.add(TagAPI.MINEABLE_HOE);
}
} }

View file

@ -1,7 +1,6 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.WorldGenLevel;
@ -18,12 +17,14 @@ public abstract class UnderwaterPlantWithAgeBlock extends UnderwaterPlantBlock {
public static final IntegerProperty AGE = BlockProperties.AGE; public static final IntegerProperty AGE = BlockProperties.AGE;
public UnderwaterPlantWithAgeBlock() { public UnderwaterPlantWithAgeBlock() {
super(FabricBlockSettings.of(Material.WATER_PLANT) super(
.breakByTool(FabricToolTags.SHEARS) FabricBlockSettings
.breakByHand(true) .of(Material.WATER_PLANT)
.sound(SoundType.WET_GRASS) .breakByHand(true)
.randomTicks() .sound(SoundType.WET_GRASS)
.noCollission()); .randomTicks()
.noCollission()
);
} }
@Override @Override

View file

@ -1,11 +1,14 @@
package ru.bclib.blocks; package ru.bclib.blocks;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.mininglevel.v1.FabricMineableTags;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags; import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.tags.Tag.Named;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.item.enchantment.Enchantments;
@ -17,37 +20,46 @@ import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import ru.bclib.api.TagAPI;
import ru.bclib.client.render.BCLRenderLayer; import ru.bclib.client.render.BCLRenderLayer;
import ru.bclib.interfaces.RenderLayerProvider; import ru.bclib.interfaces.RenderLayerProvider;
import ru.bclib.interfaces.TagProvider;
import java.util.List; import java.util.List;
@SuppressWarnings("deprecation") public abstract class UpDownPlantBlock extends BaseBlockNotFull implements RenderLayerProvider, TagProvider {
public abstract class UpDownPlantBlock extends BaseBlockNotFull implements RenderLayerProvider {
private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 16, 12); private static final VoxelShape SHAPE = Block.box(4, 0, 4, 12, 16, 12);
public UpDownPlantBlock() { public UpDownPlantBlock() {
super(FabricBlockSettings.of(Material.PLANT) this(FabricBlockSettings
.breakByTool(FabricToolTags.SHEARS) .of(Material.PLANT)
.breakByHand(true) .breakByHand(true)
.sound(SoundType.GRASS) .sound(SoundType.GRASS)
.noCollission()); .noCollission()
);
}
public UpDownPlantBlock(BlockBehaviour.Properties properties) {
super(properties);
} }
protected abstract boolean isTerrain(BlockState state); protected abstract boolean isTerrain(BlockState state);
@Override @Override
@SuppressWarnings("deprecation")
public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) { public VoxelShape getShape(BlockState state, BlockGetter view, BlockPos pos, CollisionContext ePos) {
return SHAPE; return SHAPE;
} }
@Override @Override
@SuppressWarnings("deprecation")
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
BlockState down = world.getBlockState(pos.below()); BlockState down = world.getBlockState(pos.below());
BlockState up = world.getBlockState(pos.above()); BlockState up = world.getBlockState(pos.above());
@ -59,6 +71,7 @@ public abstract class UpDownPlantBlock extends BaseBlockNotFull implements Rende
} }
@Override @Override
@SuppressWarnings("deprecation")
public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { public BlockState updateShape(BlockState state, Direction facing, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
if (!canSurvive(state, world, pos)) { if (!canSurvive(state, world, pos)) {
return Blocks.AIR.defaultBlockState(); return Blocks.AIR.defaultBlockState();
@ -92,4 +105,10 @@ public abstract class UpDownPlantBlock extends BaseBlockNotFull implements Rende
super.playerDestroy(world, player, pos, state, blockEntity, stack); super.playerDestroy(world, player, pos, state, blockEntity, stack);
world.neighborChanged(pos, Blocks.AIR, pos.below()); world.neighborChanged(pos, Blocks.AIR, pos.below());
} }
@Override
public void addTags(List<Named<Block>> blockTags, List<Named<Item>> itemTags) {
blockTags.add(FabricMineableTags.SHEARS_MINEABLE);
blockTags.add(TagAPI.MINEABLE_HOE);
}
} }

View file

@ -2,12 +2,12 @@ package ru.bclib.blocks;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material; import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootContext;
@ -16,14 +16,20 @@ import java.util.List;
public abstract class WallMushroomBlock extends BaseWallPlantBlock { public abstract class WallMushroomBlock extends BaseWallPlantBlock {
public WallMushroomBlock(int light) { public WallMushroomBlock(int light) {
super(FabricBlockSettings.of(Material.PLANT) this(
.breakByTool(FabricToolTags.AXES) FabricBlockSettings
.breakByHand(true) .of(Material.PLANT)
.luminance(light) .breakByHand(true)
.hardness(0.2F) .luminance(light)
.sound(SoundType.GRASS) .destroyTime(0.2F)
.sound(SoundType.WOOD) .sound(SoundType.GRASS)
.noCollission()); .sound(SoundType.WOOD)
.noCollission()
);
}
public WallMushroomBlock(BlockBehaviour.Properties properties) {
super(properties);
} }
@Override @Override

View file

@ -1,61 +0,0 @@
package ru.bclib.blocks.properties;
import com.google.common.collect.Sets;
import net.minecraft.world.level.block.state.properties.Property;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@Deprecated
public class StringProperty extends Property<String> {
private final Set<String> values;
public static StringProperty create(String name, String... values) {
return new StringProperty(name, values);
}
protected StringProperty(String string, String... values) {
super(string, String.class);
this.values = Sets.newHashSet(values);
}
public void addValue(String name) {
values.add(name);
}
@Override
public Collection<String> getPossibleValues() {
return Collections.unmodifiableSet(values);
}
@Override
public String getName(String comparable) {
return comparable;
}
@Override
public Optional<String> getValue(String string) {
if (values.contains(string)) {
return Optional.of(string);
}
else {
return Optional.empty();
}
}
@Override
public int generateHashCode() {
return super.generateHashCode() + Objects.hashCode(values);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof StringProperty that)) return false;
if (!super.equals(o)) return false;
return values.equals(that.values);
}
}

View file

@ -13,7 +13,7 @@ import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.material.FogType; import net.minecraft.world.level.material.FogType;
import ru.bclib.api.BiomeAPI; import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.util.BackgroundInfo; import ru.bclib.util.BackgroundInfo;
import ru.bclib.util.MHelper; import ru.bclib.util.MHelper;
import ru.bclib.world.biomes.BCLBiome; import ru.bclib.world.biomes.BCLBiome;

View file

@ -26,12 +26,12 @@ public class Configs {
MAIN_CONFIG.saveChanges(); MAIN_CONFIG.saveChanges();
RECIPE_CONFIG.saveChanges(); RECIPE_CONFIG.saveChanges();
GENERATOR_CONFIG.saveChanges(); GENERATOR_CONFIG.saveChanges();
initForcedConfig();
}
private static void initForcedConfig() {
BIOMES_CONFIG.keeper.registerEntry(new ConfigKey("end_biomes", "force_include"), new StringArrayEntry(Collections.EMPTY_LIST));
BIOMES_CONFIG.keeper.registerEntry(new ConfigKey("nether_biomes", "force_include"), new StringArrayEntry(Collections.EMPTY_LIST));
BIOMES_CONFIG.saveChanges(); BIOMES_CONFIG.saveChanges();
} }
static {
BIOMES_CONFIG.keeper.registerEntry(new ConfigKey("end_land_biomes", "force_include"), new StringArrayEntry(Collections.EMPTY_LIST));
BIOMES_CONFIG.keeper.registerEntry(new ConfigKey("end_void_biomes", "force_include"), new StringArrayEntry(Collections.EMPTY_LIST));
BIOMES_CONFIG.keeper.registerEntry(new ConfigKey("nether_biomes", "force_include"), new StringArrayEntry(Collections.EMPTY_LIST));
}
} }

View file

@ -1,6 +1,6 @@
package ru.bclib.integration; package ru.bclib.integration;
import net.fabricmc.fabric.api.tag.TagRegistry; import net.fabricmc.fabric.api.tag.TagFactory;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries; import net.minecraft.data.BuiltinRegistries;
@ -17,6 +17,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.GenerationStep; import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.Feature; import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import ru.bclib.BCLib; import ru.bclib.BCLib;
import ru.bclib.world.features.BCLFeature; import ru.bclib.world.features.BCLFeature;
@ -58,9 +59,9 @@ public abstract class ModIntegration {
return FabricLoader.getInstance().isModLoaded(modID); return FabricLoader.getInstance().isModLoaded(modID);
} }
public BCLFeature getFeature(String featureID, String configuredFeatureID, GenerationStep.Decoration featureStep) { public BCLFeature getFeature(String featureID, String placedFeatureID, GenerationStep.Decoration featureStep) {
Feature<?> feature = Registry.FEATURE.get(getID(featureID)); Feature<?> feature = Registry.FEATURE.get(getID(featureID));
ConfiguredFeature<?, ?> featureConfigured = BuiltinRegistries.CONFIGURED_FEATURE.get(getID(configuredFeatureID)); PlacedFeature featureConfigured = BuiltinRegistries.PLACED_FEATURE.get(getID(placedFeatureID));
return new BCLFeature(feature, featureConfigured, featureStep); return new BCLFeature(feature, featureConfigured, featureStep);
} }
@ -198,12 +199,15 @@ public abstract class ModIntegration {
public Tag.Named<Item> getItemTag(String name) { public Tag.Named<Item> getItemTag(String name) {
ResourceLocation id = getID(name); ResourceLocation id = getID(name);
Tag<Item> tag = ItemTags.getAllTags().getTag(id); Tag<Item> tag = ItemTags.getAllTags().getTag(id);
return tag == null ? (Named<Item>) TagRegistry.item(id) : (Named<Item>) tag;
//return tag == null ? (Named<Item>) TagRegistry.item(id) : (Named<Item>) tag;
return tag == null ? (Named<Item>) TagFactory.ITEM.create(id) : (Named<Item>) tag;
} }
public Tag.Named<Block> getBlockTag(String name) { public Tag.Named<Block> getBlockTag(String name) {
ResourceLocation id = getID(name); ResourceLocation id = getID(name);
Tag<Block> tag = BlockTags.getAllTags().getTag(id); Tag<Block> tag = BlockTags.getAllTags().getTag(id);
return tag == null ? (Named<Block>) TagRegistry.block(id) : (Named<Block>) tag; //return tag == null ? (Named<Block>) TagRegistry.block(id) : (Named<Block>) tag;
return tag == null ? (Named<Block>) TagFactory.BLOCK.create(id) : (Named<Block>) tag;
} }
} }

View file

@ -0,0 +1,9 @@
package ru.bclib.interfaces;
import ru.bclib.world.biomes.BCLBiome;
public interface BiomeMap {
void clearCache();
BCLBiome getBiome(double x, double z);
}

View file

@ -0,0 +1,9 @@
package ru.bclib.interfaces;
import net.minecraft.world.level.levelgen.SurfaceRules;
public interface SurfaceRuleProvider {
void setSurfaceRule(SurfaceRules.RuleSource surfaceRule);
SurfaceRules.RuleSource getSurfaceRule();
}

View file

@ -0,0 +1,12 @@
package ru.bclib.interfaces;
import net.minecraft.tags.Tag;
import net.minecraft.tags.Tag.Named;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import java.util.List;
public interface TagProvider {
void addTags(List<Named<Block>> blockTags, List<Tag.Named<Item>> itemTags);
}

View file

@ -22,6 +22,7 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.bclib.api.LifeCycleAPI;
import ru.bclib.api.dataexchange.DataExchangeAPI; import ru.bclib.api.dataexchange.DataExchangeAPI;
import ru.bclib.api.datafixer.DataFixerAPI; import ru.bclib.api.datafixer.DataFixerAPI;
import ru.bclib.interfaces.CustomColorProvider; import ru.bclib.interfaces.CustomColorProvider;
@ -61,14 +62,18 @@ public abstract class MinecraftMixin {
DataExchangeAPI.prepareServerside(); DataExchangeAPI.prepareServerside();
if (DataFixerAPI.fixData(this.levelSource, levelID, true, (appliedFixes) -> { if (DataFixerAPI.fixData(this.levelSource, levelID, true, (appliedFixes) -> {
LifeCycleAPI._runBeforeLevelLoad();
this.doLoadLevel(levelID, RegistryAccess.builtin(), Minecraft::loadDataPacks, Minecraft::loadWorldData, false, appliedFixes?ExperimentalDialogType.NONE:ExperimentalDialogType.BACKUP); this.doLoadLevel(levelID, RegistryAccess.builtin(), Minecraft::loadDataPacks, Minecraft::loadWorldData, false, appliedFixes?ExperimentalDialogType.NONE:ExperimentalDialogType.BACKUP);
})) { })) {
ci.cancel(); ci.cancel();
} else {
LifeCycleAPI._runBeforeLevelLoad();
} }
} }
@Inject(method = "createLevel", at = @At("HEAD")) @Inject(method = "createLevel", at = @At("HEAD"))
private void bclib_initPatchData(String levelID, LevelSettings levelSettings, RegistryHolder registryHolder, WorldGenSettings worldGenSettings, CallbackInfo ci) { private void bclib_initPatchData(String levelID, LevelSettings levelSettings, RegistryHolder registryHolder, WorldGenSettings worldGenSettings, CallbackInfo ci) {
DataFixerAPI.initializeWorldData(this.levelSource, levelID, true); DataFixerAPI.initializeWorldData(this.levelSource, levelID, true);
LifeCycleAPI._runBeforeLevelLoad();
} }
} }

View file

@ -0,0 +1,37 @@
package ru.bclib.mixin.common;
import net.minecraft.world.level.biome.BiomeGenerationSettings;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.GenerationStep.Carving;
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
@Mixin(BiomeGenerationSettings.class)
public interface BiomeGenerationSettingsAccessor {
@Accessor("features")
List<List<Supplier<PlacedFeature>>> bclib_getFeatures();
@Accessor("features")
@Mutable
void bclib_setFeatures(List<List<Supplier<PlacedFeature>>> value);
@Accessor("featureSet")
Set<PlacedFeature> bclib_getFeatureSet();
@Accessor("featureSet")
void bclib_setFeatureSet(Set<PlacedFeature> features);
@Accessor("carvers")
Map<Carving, List<Supplier<ConfiguredWorldCarver<?>>>> bclib_getCarvers();
@Accessor("carvers")
void bclib_setCarvers(Map<GenerationStep.Carving, List<Supplier<ConfiguredWorldCarver<?>>>> features);
}

View file

@ -1,28 +0,0 @@
package ru.bclib.mixin.common;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.WorldgenRandom;
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.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Biome.class)
public class BiomeMixin {
private int bclib_featureIteratorSeed;
@ModifyArg(method = "generate", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/WorldgenRandom;setFeatureSeed(JII)J"))
private long bclib_updateFeatureSeed(long seed) {
return Long.rotateRight(seed, bclib_featureIteratorSeed++);
}
@Inject(method = "generate", at = @At("HEAD"))
private void bclib_obBiomeGenerate(StructureFeatureManager structureFeatureManager, ChunkGenerator chunkGenerator, WorldGenRegion worldGenRegion, long l, WorldgenRandom worldgenRandom, BlockPos blockPos, CallbackInfo info) {
bclib_featureIteratorSeed = 0;
}
}

View file

@ -15,8 +15,8 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import ru.bclib.api.BiomeAPI;
import ru.bclib.api.BonemealAPI; import ru.bclib.api.BonemealAPI;
import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.util.BlocksHelper; import ru.bclib.util.BlocksHelper;
import ru.bclib.util.MHelper; import ru.bclib.util.MHelper;

View file

@ -1,134 +0,0 @@
package ru.bclib.mixin.common;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.core.BlockPos;
import net.minecraft.util.BitStorage;
import net.minecraft.util.Mth;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.ChunkBiomeContainer;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import ru.bclib.BCLib;
import ru.bclib.interfaces.BiomeSetter;
import java.lang.reflect.Field;
@Mixin(ChunkBiomeContainer.class)
public class ChunkBiomeContainerMixin implements BiomeSetter {
private static boolean bclib_hasHydrogen = FabricLoader.getInstance().isModLoaded("hydrogen");
@Final
@Shadow
private Biome[] biomes;
@Final
@Shadow
private static int WIDTH_BITS;
@Final
@Shadow
private static int HORIZONTAL_MASK;
@Override
public void bclib_setBiome(Biome biome, BlockPos pos) {
int biomeX = pos.getX() >> 2;
int biomeY = pos.getY() >> 2;
int biomeZ = pos.getZ() >> 2;
int index = be_getArrayIndex(biomeX, biomeY, biomeZ);
if (bclib_hasHydrogen && be_shouldWriteToHydrogen()) {
try {
ChunkBiomeContainer self = (ChunkBiomeContainer) (Object) this;
BitStorage storage = be_getHydrogenStorage(self);
Biome[] palette = be_getHydrogenPalette(self);
int paletteIndex = be_getHydrogenPaletteIndex(biome, palette);
if (paletteIndex == -1) {
Biome[] newPalette = new Biome[palette.length + 1];
System.arraycopy(palette, 0, newPalette, 0, palette.length);
paletteIndex = palette.length;
palette = newPalette;
palette[paletteIndex] = biome;
be_setHydrogenPalette(self, palette);
}
try {
storage.set(index, paletteIndex);
}
catch (Exception e) {
int size = storage.getSize();
int bits = Mth.ceillog2(palette.length);
BitStorage newStorage = new BitStorage(bits, size);
for (int i = 0; i < size; i++) {
newStorage.set(i, storage.get(i));
}
storage = newStorage;
storage.set(index, paletteIndex);
be_setHydrogenStorage(self, storage);
}
}
catch (Exception e) {
BCLib.LOGGER.warning(e.getLocalizedMessage());
}
return;
}
biomes[index] = biome;
}
@Shadow
@Final
private int quartMinY;
@Shadow
@Final
private int quartHeight;
private boolean be_shouldWriteToHydrogen() {
try {
Field field = ChunkBiomeContainer.class.getDeclaredField("intArray");
return field != null;
}
catch (NoSuchFieldException e) {
return false;
}
}
private int be_getArrayIndex(int biomeX, int biomeY, int biomeZ) {
int i = biomeX & HORIZONTAL_MASK;
int j = Mth.clamp(biomeY - this.quartMinY, 0, this.quartHeight);
int k = biomeZ & HORIZONTAL_MASK;
return j << WIDTH_BITS + WIDTH_BITS | k << WIDTH_BITS | i;
}
private Field be_getField(String name) throws Exception {
Field field = ChunkBiomeContainer.class.getDeclaredField(name);
field.setAccessible(true);
return field;
}
private BitStorage be_getHydrogenStorage(ChunkBiomeContainer container) throws Exception {
return (BitStorage) be_getField("intArray").get(container);
}
private Biome[] be_getHydrogenPalette(ChunkBiomeContainer container) throws Exception {
return (Biome[]) be_getField("palette").get(container);
}
private int be_getHydrogenPaletteIndex(Biome biome, Biome[] palette) {
int index = -1;
for (int i = 0; i < palette.length; i++) {
if (palette[i] == biome) {
index = i;
break;
}
}
return index;
}
private void be_setHydrogenPalette(ChunkBiomeContainer container, Biome[] palette) throws Exception {
be_getField("palette").set(container, palette);
}
private void be_setHydrogenStorage(ChunkBiomeContainer container, BitStorage storage) throws Exception {
be_getField("intArray").set(container, storage);
}
}

View file

@ -0,0 +1,26 @@
package ru.bclib.mixin.common;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
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.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ChunkGenerator.class)
public class ChunkGeneratorMixin {
private int bclib_featureIteratorSeed;
@ModifyArg(method = "applyBiomeDecoration", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/WorldgenRandom;setFeatureSeed(JII)V"))
private long bclib_updateFeatureSeed(long seed) {
return Long.rotateRight(seed, bclib_featureIteratorSeed++);
}
@Inject(method = "applyBiomeDecoration", at = @At("HEAD"))
private void bclib_obBiomeGenerate(WorldGenLevel worldGenLevel, ChunkAccess chunkAccess, StructureFeatureManager structureFeatureManager, CallbackInfo ci) {
bclib_featureIteratorSeed = 0;
}
}

View file

@ -1,40 +1,63 @@
package ru.bclib.mixin.common; package ru.bclib.mixin.common;
import com.mojang.serialization.Lifecycle;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.synth.NormalNoise;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import ru.bclib.world.generator.BCLibEndBiomeSource; import ru.bclib.world.generator.BCLibEndBiomeSource;
import ru.bclib.world.generator.BCLibNetherBiomeSource; import ru.bclib.world.generator.BCLibNetherBiomeSource;
import ru.bclib.world.generator.GeneratorOptions;
@Mixin(value = DimensionType.class, priority = 10) import java.util.OptionalInt;
@Mixin(DimensionType.class)
public class DimensionTypeMixin { public class DimensionTypeMixin {
@Inject(method = "defaultNetherGenerator", at = @At("HEAD"), cancellable = true) @Inject(
private static void be_replaceNetherBiomeSource(Registry<Biome> biomeRegistry, Registry<NoiseGeneratorSettings> chunkGeneratorSettingsRegistry, long seed, CallbackInfoReturnable<ChunkGenerator> info) { method = "defaultDimensions(Lnet/minecraft/core/RegistryAccess;JZ)Lnet/minecraft/core/MappedRegistry;",
if (GeneratorOptions.customNetherBiomeSource()) { locals = LocalCapture.CAPTURE_FAILHARD,
info.setReturnValue(new NoiseBasedChunkGenerator( at = @At("TAIL")
new BCLibNetherBiomeSource(biomeRegistry, seed), )
seed, private static void bclib_updateDimensions(RegistryAccess registryAccess, long seed, boolean bl, CallbackInfoReturnable<MappedRegistry<LevelStem>> info, MappedRegistry<LevelStem> mappedRegistry, Registry<DimensionType> registry, Registry<Biome> biomeRegistry, Registry<NoiseGeneratorSettings> noiseSettingsRegistry, Registry<NormalNoise.NoiseParameters> noiseParamRegistry) {
() -> chunkGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.NETHER) int id = mappedRegistry.getId(mappedRegistry.get(LevelStem.NETHER));
)); mappedRegistry.registerOrOverride(
} OptionalInt.of(id),
LevelStem.NETHER,
new LevelStem(
() -> registry.getOrThrow(DimensionType.NETHER_LOCATION),
new NoiseBasedChunkGenerator(
noiseParamRegistry,
new BCLibNetherBiomeSource(biomeRegistry, seed),
seed,
() -> noiseSettingsRegistry.getOrThrow(NoiseGeneratorSettings.NETHER)
)
),
Lifecycle.stable()
);
id = mappedRegistry.getId(mappedRegistry.get(LevelStem.END));
mappedRegistry.registerOrOverride(
OptionalInt.of(id),
LevelStem.END,
new LevelStem(
() -> registry.getOrThrow(DimensionType.END_LOCATION),
new NoiseBasedChunkGenerator(
noiseParamRegistry,
new BCLibEndBiomeSource(biomeRegistry, seed),
seed,
() -> noiseSettingsRegistry.getOrThrow(NoiseGeneratorSettings.END)
)
),
Lifecycle.stable()
);
} }
}
@Inject(method = "defaultEndGenerator", at = @At("HEAD"), cancellable = true)
private static void be_replaceEndBiomeSource(Registry<Biome> biomeRegistry, Registry<NoiseGeneratorSettings> chunkGeneratorSettingsRegistry, long seed, CallbackInfoReturnable<ChunkGenerator> info) {
if (GeneratorOptions.customEndBiomeSource()) {
info.setReturnValue(new NoiseBasedChunkGenerator(
new BCLibEndBiomeSource(biomeRegistry, seed),
seed,
() -> chunkGeneratorSettingsRegistry.getOrThrow(NoiseGeneratorSettings.END)
));
}
}
}

View file

@ -1,11 +0,0 @@
package ru.bclib.mixin.common;
import net.minecraft.world.level.levelgen.placement.ConfiguredDecorator;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(targets = "net.minecraft.data.worldgen.Features$Decorators")
public interface FeatureDecoratorsAccessor {
@Accessor("HEIGHTMAP_SQUARE")
ConfiguredDecorator<?> bclib_getHeightmapSquare();
}

View file

@ -1,40 +0,0 @@
package ru.bclib.mixin.common;
import net.fabricmc.fabric.impl.biome.InternalBiomeData;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biomes;
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 ru.bclib.world.biomes.FabricBiomesData;
@Mixin(value = InternalBiomeData.class, remap = false)
public class InternalBiomeDataMixin {
@Inject(method = "addEndBiomeReplacement", at = @At(value = "HEAD"))
private static void bclib_addEndBiomeReplacement(ResourceKey<Biome> replaced, ResourceKey<Biome> variant, double weight, CallbackInfo info) {
if (replaced == Biomes.END_BARRENS || replaced == Biomes.SMALL_END_ISLANDS) {
FabricBiomesData.END_VOID_BIOMES.put(variant, (float) weight);
}
else {
FabricBiomesData.END_LAND_BIOMES.put(variant, (float) weight);
}
}
@Inject(method = "addEndMidlandsReplacement", at = @At(value = "HEAD"))
private static void bclib_addEndMidlandsReplacement(ResourceKey<Biome> highlands, ResourceKey<Biome> midlands, double weight, CallbackInfo info) {
FabricBiomesData.END_LAND_BIOMES.put(midlands, (float) weight);
}
@Inject(method = "addEndBarrensReplacement", at = @At(value = "HEAD"))
private static void bclib_addEndBarrensReplacement(ResourceKey<Biome> highlands, ResourceKey<Biome> barrens, double weight, CallbackInfo info) {
FabricBiomesData.END_LAND_BIOMES.put(barrens, (float) weight);
FabricBiomesData.END_VOID_BIOMES.put(barrens, (float) weight);
}
@Inject(method = "addNetherBiome", at = @At(value = "HEAD"))
private static void bclib_addNetherBiome(ResourceKey<Biome> biome, Biome.ClimateParameters spawnNoisePoint, CallbackInfo info) {
FabricBiomesData.NETHER_BIOMES.add(biome);
}
}

View file

@ -5,13 +5,15 @@ import net.minecraft.world.level.storage.LevelStorageSource;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyArg;
import ru.bclib.api.LifeCycleAPI;
import ru.bclib.api.datafixer.DataFixerAPI; import ru.bclib.api.datafixer.DataFixerAPI;
@Mixin(Main.class) @Mixin(Main.class)
abstract public class MainMixin { abstract public class MainMixin {
@ModifyArg(method="main", at=@At(value="INVOKE", target="Lnet/minecraft/server/MinecraftServer;convertFromRegionFormatIfNeeded(Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;)V")) @ModifyArg(method="main", at=@At(value="INVOKE_ASSIGN", target="Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;getSummary()Lnet/minecraft/world/level/storage/LevelSummary;"))
private static LevelStorageSource.LevelStorageAccess bclib_callServerFix(LevelStorageSource.LevelStorageAccess session){ private static LevelStorageSource.LevelStorageAccess bclib_callServerFix(LevelStorageSource.LevelStorageAccess session){
DataFixerAPI.fixData(session, false, (didFix)->{/* not called when showUI==false */}); DataFixerAPI.fixData(session, false, (didFix)->{/* not called when showUI==false */});
LifeCycleAPI._runBeforeLevelLoad();
return session; return session;
} }
} }

View file

@ -12,7 +12,6 @@ import net.minecraft.server.level.progress.ChunkProgressListenerFactory;
import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.server.players.GameProfileCache; import net.minecraft.server.players.GameProfileCache;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess; import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess;
import net.minecraft.world.level.storage.WorldData; import net.minecraft.world.level.storage.WorldData;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
@ -22,7 +21,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import ru.bclib.api.BiomeAPI;
import ru.bclib.api.dataexchange.DataExchangeAPI; import ru.bclib.api.dataexchange.DataExchangeAPI;
import ru.bclib.recipes.BCLRecipeManager; import ru.bclib.recipes.BCLRecipeManager;
@ -49,15 +47,6 @@ public class MinecraftServerMixin {
DataExchangeAPI.prepareServerside(); DataExchangeAPI.prepareServerside();
} }
@Inject(method = "convertFromRegionFormatIfNeeded", at = @At("HEAD"))
private static void bclib_applyPatches(LevelStorageSource.LevelStorageAccess session, CallbackInfo ci) {
/*File levelPath = session.getLevelPath(LevelResource.ROOT).toFile();
WorldDataAPI.load(new File(levelPath, "data"));
DataFixerAPI.fixData(levelPath, session.getLevelId());*/
}
@Inject(method = "reloadResources", at = @At(value = "RETURN"), cancellable = true) @Inject(method = "reloadResources", at = @At(value = "RETURN"), cancellable = true)
private void bclib_reloadResources(Collection<String> collection, CallbackInfoReturnable<CompletableFuture<Void>> info) { private void bclib_reloadResources(Collection<String> collection, CallbackInfoReturnable<CompletableFuture<Void>> info) {
bclib_injectRecipes(); bclib_injectRecipes();
@ -66,7 +55,7 @@ public class MinecraftServerMixin {
@Inject(method = "loadLevel", at = @At(value = "RETURN"), cancellable = true) @Inject(method = "loadLevel", at = @At(value = "RETURN"), cancellable = true)
private void bclib_loadLevel(CallbackInfo info) { private void bclib_loadLevel(CallbackInfo info) {
bclib_injectRecipes(); bclib_injectRecipes();
BiomeAPI.initRegistry(MinecraftServer.class.cast(this)); //BiomeAPI.initRegistry(MinecraftServer.class.cast(this));
} }
private void bclib_injectRecipes() { private void bclib_injectRecipes() {

View file

@ -0,0 +1,21 @@
package ru.bclib.mixin.common;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.Map;
@Mixin(MobSpawnSettings.class)
public interface MobSpawnSettingsAccessor {
@Accessor("spawners")
Map<MobCategory, WeightedRandomList<SpawnerData>> bcl_getSpawners();
@Accessor("spawners")
@Mutable
void bcl_setSpawners(Map<MobCategory, WeightedRandomList<SpawnerData>> spawners);
}

View file

@ -0,0 +1,19 @@
package ru.bclib.mixin.common;
import net.fabricmc.fabric.impl.biome.NetherBiomeData;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Climate;
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 ru.bclib.world.biomes.FabricBiomesData;
@Mixin(value = NetherBiomeData.class, remap = false)
public class NetherBiomeDataMixin {
@Inject(method = "addNetherBiome", at = @At(value = "HEAD"))
private static void bclib_addNetherBiome(ResourceKey<Biome> biome, Climate.ParameterPoint spawnNoisePoint, CallbackInfo info) {
FabricBiomesData.NETHER_BIOMES.add(biome);
}
}

View file

@ -0,0 +1,38 @@
package ru.bclib.mixin.common;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource;
import org.spongepowered.asm.mixin.Final;
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.CallbackInfoReturnable;
import ru.bclib.interfaces.SurfaceRuleProvider;
@Mixin(NoiseGeneratorSettings.class)
public class NoiseGeneratorSettingsMixin implements SurfaceRuleProvider {
@Final
@Shadow
private SurfaceRules.RuleSource surfaceRule;
private SurfaceRules.RuleSource bclib_surfaceRule;
@Override
public void setSurfaceRule(SurfaceRules.RuleSource surfaceRule) {
bclib_surfaceRule = surfaceRule;
}
@Override
public RuleSource getSurfaceRule() {
return surfaceRule;
}
@Inject(method = "surfaceRule", at = @At("HEAD"), cancellable = true)
private void bclib_surfaceRule(CallbackInfoReturnable<SurfaceRules.RuleSource> info) {
if (bclib_surfaceRule != null) {
info.setReturnValue(bclib_surfaceRule);
}
}
}

View file

@ -1,9 +1,5 @@
package ru.bclib.mixin.common; package ru.bclib.mixin.common;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@ -13,15 +9,19 @@ import net.minecraft.world.level.CustomSpawner;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess;
import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.level.storage.WritableLevelData; import net.minecraft.world.level.storage.WritableLevelData;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.bclib.api.BiomeAPI;
import ru.bclib.api.LifeCycleAPI; import ru.bclib.api.LifeCycleAPI;
import ru.bclib.api.biomes.BiomeAPI;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
@Mixin(ServerLevel.class) @Mixin(ServerLevel.class)
public abstract class ServerLevelMixin extends Level { public abstract class ServerLevelMixin extends Level {
@ -32,18 +32,18 @@ public abstract class ServerLevelMixin extends Level {
} }
@Inject(method = "<init>*", at = @At("TAIL")) @Inject(method = "<init>*", at = @At("TAIL"))
private void bclib_onServerWorldInit(MinecraftServer server, Executor workerExecutor, LevelStorageSource.LevelStorageAccess session, ServerLevelData properties, ResourceKey<Level> registryKey, DimensionType dimensionType, ChunkProgressListener worldGenerationProgressListener, ChunkGenerator chunkGenerator, boolean debugWorld, long l, List<CustomSpawner> list, boolean bl, CallbackInfo info) { private void bclib_onServerWorldInit(MinecraftServer server, Executor executor, LevelStorageAccess levelStorageAccess, ServerLevelData serverLevelData, ResourceKey<Level> resourceKey, DimensionType dimensionType, ChunkProgressListener chunkProgressListener, ChunkGenerator chunkGenerator, boolean bl, long l, List<CustomSpawner> list, boolean bl2, CallbackInfo info) {
ServerLevel world = ServerLevel.class.cast(this); ServerLevel world = ServerLevel.class.cast(this);
LifeCycleAPI._runLevelLoad(world, server, workerExecutor, session, properties, registryKey, dimensionType, worldGenerationProgressListener, chunkGenerator, debugWorld, l, list, bl); LifeCycleAPI._runLevelLoad(world, server, executor, levelStorageAccess, serverLevelData, resourceKey, dimensionType, chunkProgressListener, chunkGenerator, bl, l, list, bl2);
BiomeAPI.initRegistry(server); //BiomeAPI.initRegistry(server);
BiomeAPI.applyModifications(ServerLevel.class.cast(this)); BiomeAPI.applyModifications(ServerLevel.class.cast(this));
if (bclib_lastWorld != null && bclib_lastWorld.equals(session.getLevelId())) { if (bclib_lastWorld != null && bclib_lastWorld.equals(levelStorageAccess.getLevelId())) {
return; return;
} }
bclib_lastWorld = session.getLevelId(); bclib_lastWorld = levelStorageAccess.getLevelId();
} }

View file

@ -0,0 +1,22 @@
package ru.bclib.mixin.common;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.StructureSettings;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(StructureSettings.class)
public interface StructureSettingsAccessor {
@Accessor("configuredStructures")
ImmutableMap<StructureFeature<?>, ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> bcl_getStructureConfig();
@Accessor("configuredStructures")
@Mutable
void bcl_setStructureConfig(ImmutableMap<StructureFeature<?>, ImmutableMultimap<ConfiguredStructureFeature<?, ?>, ResourceKey<Biome>>> structureConfig);
}

View file

@ -0,0 +1,35 @@
package ru.bclib.mixin.common;
import net.fabricmc.fabric.impl.biome.TheEndBiomeData;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biomes;
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 ru.bclib.world.biomes.FabricBiomesData;
@Mixin(value = TheEndBiomeData.class, remap = false)
public class TheEndBiomeDataMixin {
@Inject(method = "addEndBiomeReplacement", at = @At(value = "HEAD"))
private static void bclib_addEndBiomeReplacement(ResourceKey<Biome> replaced, ResourceKey<Biome> variant, double weight, CallbackInfo info) {
if (replaced == Biomes.END_BARRENS || replaced == Biomes.SMALL_END_ISLANDS) {
FabricBiomesData.END_VOID_BIOMES.put(variant, (float) weight);
}
else {
FabricBiomesData.END_LAND_BIOMES.put(variant, (float) weight);
}
}
@Inject(method = "addEndMidlandsReplacement", at = @At(value = "HEAD"))
private static void bclib_addEndMidlandsReplacement(ResourceKey<Biome> highlands, ResourceKey<Biome> midlands, double weight, CallbackInfo info) {
FabricBiomesData.END_LAND_BIOMES.put(midlands, (float) weight);
}
@Inject(method = "addEndBarrensReplacement", at = @At(value = "HEAD"))
private static void bclib_addEndBarrensReplacement(ResourceKey<Biome> highlands, ResourceKey<Biome> barrens, double weight, CallbackInfo info) {
FabricBiomesData.END_LAND_BIOMES.put(barrens, (float) weight);
FabricBiomesData.END_VOID_BIOMES.put(barrens, (float) weight);
}
}

View file

@ -2,7 +2,7 @@ package ru.bclib.mixin.common;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.WorldGenRegion; import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkAccess;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -14,13 +14,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
public class WorldGenRegionMixin { public class WorldGenRegionMixin {
@Final @Final
@Shadow @Shadow
private ChunkPos center; private ChunkAccess center;
@Inject(method = "ensureCanWrite", at = @At("HEAD"), cancellable = true) @Inject(method = "ensureCanWrite", at = @At("HEAD"), cancellable = true)
private void be_alterBlockCheck(BlockPos blockPos, CallbackInfoReturnable<Boolean> info) { private void be_alterBlockCheck(BlockPos blockPos, CallbackInfoReturnable<Boolean> info) {
int x = blockPos.getX() >> 4; int x = blockPos.getX() >> 4;
int z = blockPos.getZ() >> 4; int z = blockPos.getZ() >> 4;
WorldGenRegion region = (WorldGenRegion) (Object) this; WorldGenRegion region = (WorldGenRegion) (Object) this;
info.setReturnValue(Math.abs(x - center.x) < 2 && Math.abs(z - center.z) < 2); info.setReturnValue(Math.abs(x - center.getPos().x) < 2 && Math.abs(z - center.getPos().z) < 2);
} }
} }

View file

@ -0,0 +1,19 @@
package ru.bclib.mixin.common;
import net.minecraft.client.gui.screens.worldselection.WorldPreset;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.world.level.levelgen.WorldGenSettings;
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;
import ru.bclib.api.biomes.BiomeAPI;
@Mixin(WorldPreset.class)
public class WorldPresetMixin {
@Inject(method = "create", at = @At("HEAD"))
private void create(RegistryAccess.RegistryHolder registryHolder, long l, boolean bl, boolean bl2, CallbackInfoReturnable<WorldGenSettings> info) {
BiomeAPI.initRegistry(registryHolder.registryOrThrow(Registry.BIOME_REGISTRY));
}
}

View file

@ -2,14 +2,14 @@ package ru.bclib.registry;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry; import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry;
import ru.bclib.client.render.BaseChestBlockEntityRenderer; import ru.bclib.client.render.BaseChestBlockEntityRenderer;
import ru.bclib.client.render.BaseSignBlockEntityRenderer; import ru.bclib.client.render.BaseSignBlockEntityRenderer;
@Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
public class BaseBlockEntityRenders { public class BaseBlockEntityRenders {
public static void register() { public static void register() {
BlockEntityRendererRegistry.INSTANCE.register(BaseBlockEntities.CHEST, BaseChestBlockEntityRenderer::new); BlockEntityRendererRegistry.register(BaseBlockEntities.CHEST, BaseChestBlockEntityRenderer::new);
BlockEntityRendererRegistry.INSTANCE.register(BaseBlockEntities.SIGN, BaseSignBlockEntityRenderer::new); BlockEntityRendererRegistry.register(BaseBlockEntities.SIGN, BaseSignBlockEntityRenderer::new);
} }
} }

View file

@ -1,5 +1,6 @@
package ru.bclib.registry; package ru.bclib.registry;
import net.fabricmc.fabric.api.mininglevel.v1.FabricMineableTags;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry; import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -10,6 +11,7 @@ import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import ru.bclib.api.TagAPI; import ru.bclib.api.TagAPI;
import ru.bclib.blocks.BaseLeavesBlock; import ru.bclib.blocks.BaseLeavesBlock;
import ru.bclib.blocks.BaseOreBlock;
import ru.bclib.blocks.FeatureSaplingBlock; import ru.bclib.blocks.FeatureSaplingBlock;
import ru.bclib.config.PathConfig; import ru.bclib.config.PathConfig;
import ru.bclib.interfaces.CustomItemProvider; import ru.bclib.interfaces.CustomItemProvider;
@ -41,10 +43,12 @@ public class BlockRegistry extends BaseRegistry<Block> {
getModBlocks(id.getNamespace()).add(block); getModBlocks(id.getNamespace()).add(block);
if (block instanceof BaseLeavesBlock){ if (block instanceof BaseLeavesBlock){
TagAPI.addTags(block, TagAPI.BLOCK_LEAVES); TagAPI.addTags(block, TagAPI.BLOCK_LEAVES, TagAPI.MINEABLE_HOE, FabricMineableTags.SHEARS_MINEABLE);
if (item != null){ if (item != null){
TagAPI.addTags(item, TagAPI.ITEM_LEAVES); TagAPI.addTags(item, TagAPI.ITEM_LEAVES);
} }
} else if (block instanceof BaseOreBlock){
TagAPI.addTags(block, TagAPI.MINEABLE_PICKAXE);
} else if (block instanceof FeatureSaplingBlock){ } else if (block instanceof FeatureSaplingBlock){
TagAPI.addTags(block, TagAPI.BLOCK_SAPLINGS); TagAPI.addTags(block, TagAPI.BLOCK_SAPLINGS);
if (item != null){ if (item != null){

View file

@ -0,0 +1,46 @@
package ru.bclib.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class CollectionsUtil {
/**
* Will return mutable copy of list.
* @param list {@link List} to make mutable.
* @return {@link ArrayList} or original {@link List} if it is mutable.
*/
public static <E> List<E> getMutable(List<E> list) {
if (list instanceof ArrayList) {
return list;
}
return new ArrayList<>(list);
}
/**
* Will return mutable copy of set.
* @param set {@link Set} to make mutable.
* @return {@link HashSet} or original {@link Set} if it is mutable.
*/
public static <E> Set<E> getMutable(Set<E> set) {
if (set instanceof HashSet) {
return set;
}
return new HashSet<>(set);
}
/**
* Will return mutable copy of map.
* @param map {@link Map} to make mutable.
* @return {@link HashMap} or original {@link Map} if it is mutable.
*/
public static <K, V> Map<K, V> getMutable(Map<K, V> map) {
if (map instanceof HashMap) {
return map;
}
return new HashMap<>(map);
}
}

View file

@ -378,7 +378,9 @@ public class StructureHelper {
mut.setX(x); mut.setX(x);
for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) { for (int z = bounds.minZ(); z <= bounds.maxZ(); z++) {
mut.setZ(z); mut.setZ(z);
BlockState top = world.getBiome(mut).getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); BlockState top = Blocks.PURPLE_CONCRETE.defaultBlockState();
//TODO: 1.18 find another way to get the Top Materiel
//world.getBiome(mut).getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial();
for (int y = bounds.maxY(); y >= bounds.minY(); y--) { for (int y = bounds.maxY(); y >= bounds.minY(); y--) {
mut.setY(y); mut.setY(y);
BlockState state = world.getBlockState(mut); BlockState state = world.getBlockState(mut);

View file

@ -2,178 +2,218 @@ package ru.bclib.world.biomes;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biomes; import net.minecraft.world.level.levelgen.SurfaceRules;
import ru.bclib.config.Configs; import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import ru.bclib.util.JsonFactory; import org.jetbrains.annotations.Nullable;
import ru.bclib.util.StructureHelper; import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.util.WeightedList; import ru.bclib.util.WeightedList;
import ru.bclib.world.features.BCLFeature;
import ru.bclib.world.features.ListFeature;
import ru.bclib.world.features.ListFeature.StructureInfo;
import ru.bclib.world.features.NBTStructureFeature.TerrainMerge;
import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
public class BCLBiome { public class BCLBiome {
protected WeightedList<BCLBiome> subbiomes = new WeightedList<BCLBiome>(); private final List<ConfiguredStructureFeature> structures = Lists.newArrayList();
private final WeightedList<BCLBiome> subbiomes = new WeightedList<>();
private final Map<String, Object> customData = Maps.newHashMap();
private final ResourceLocation biomeID;
private final Biome biome;
protected final Biome biome; private SurfaceRules.RuleSource surface;
protected final ResourceLocation mcID; private BCLBiome biomeParent;
protected BCLBiome edge;
protected int edgeSize;
protected BCLBiome biomeParent;
protected float maxSubBiomeChance = 1;
protected final float genChance;
private final Map<String, Object> customData;
private final float fogDensity;
private BCLFeature structuresFeature;
private Biome actualBiome; private Biome actualBiome;
private BCLBiome edge;
public BCLBiome(BCLBiomeDef definition) { private float terrainHeight = 0.1F;
definition.loadConfigValues(Configs.BIOMES_CONFIG); private float fogDensity = 1.0F;
this.mcID = definition.getID(); private float genChance = 1.0F;
this.readStructureList(); private float edgeSize = 0.0F;
if (structuresFeature != null) {
definition.addFeature(structuresFeature); /**
} * Create wrapper for existing biome using its {@link ResourceLocation} identifier.
this.biome = definition.build(); * @param biomeKey {@link ResourceKey} for the {@link Biome}.
this.genChance = definition.getGenChance(); */
this.fogDensity = definition.getFodDensity(); public BCLBiome(ResourceKey<Biome> biomeKey) {
this.customData = definition.getCustomData(); this(biomeKey.location());
subbiomes.add(this, 1);
} }
public BCLBiome(ResourceLocation id, Biome biome, float fogDensity, float genChance) { /**
this.mcID = id; * Create wrapper for existing biome using its {@link ResourceLocation} identifier.
* @param biomeID {@link ResourceLocation} biome ID.
*/
public BCLBiome(ResourceLocation biomeID) {
this(biomeID, BuiltinRegistries.BIOME.get(biomeID));
}
/**
* Create wrapper for existing biome using biome instance from {@link BuiltinRegistries}.
* @param biome {@link Biome} to wrap.
*/
public BCLBiome(Biome biome) {
this(BuiltinRegistries.BIOME.getKey(biome), biome);
}
public BCLBiome(ResourceLocation biomeID, Biome biome) {
this.subbiomes.add(this, 1.0F);
this.biomeID = biomeID;
this.biome = biome; this.biome = biome;
if (id.equals(Biomes.THE_VOID.location())) {
this.genChance = fogDensity;
this.fogDensity = genChance;
}
else {
String biomePath = id.getNamespace() + "." + id.getPath();
this.genChance = Configs.BIOMES_CONFIG.getFloat(biomePath, "generation_chance", genChance);
this.fogDensity = Configs.BIOMES_CONFIG.getFloat(biomePath, "fog_density", fogDensity);
}
this.readStructureList();
this.customData = Maps.newHashMap();
subbiomes.add(this, 1);
} }
/**
* Get current biome edge.
* @return {@link BCLBiome} edge.
*/
@Nullable
public BCLBiome getEdge() { public BCLBiome getEdge() {
return edge == null ? this : edge; return edge;
} }
public void setEdge(BCLBiome edge) { /**
* Set biome edge for this biome instance.
* @param edge {@link BCLBiome} as the edge biome.
* @return same {@link BCLBiome}.
*/
public BCLBiome setEdge(BCLBiome edge) {
this.edge = edge; this.edge = edge;
edge.biomeParent = this; edge.biomeParent = this;
return this;
} }
public int getEdgeSize() { /**
* Getter for biome edge size.
* @return edge size.
*/
public float getEdgeSize() {
return edgeSize; return edgeSize;
} }
public void setEdgeSize(int size) { /**
* Set edges size for this biome. Size is in relative units to work fine with biome scale.
* @param size as a float value.
* @return same {@link BCLBiome}.
*/
public BCLBiome setEdgeSize(float size) {
edgeSize = size; edgeSize = size;
return this;
} }
public void addSubBiome(BCLBiome biome) { /**
* Adds sub-biome into this biome instance. Biome chance will be interpreted as a sub-biome generation chance.
* Biome itself has chance 1.0 compared to all its sub-biomes.
* @param biome {@link Random} to be added.
* @return same {@link BCLBiome}.
*/
public BCLBiome addSubBiome(BCLBiome biome) {
biome.biomeParent = this; biome.biomeParent = this;
subbiomes.add(biome, biome.getGenChance()); subbiomes.add(biome, biome.getGenChance());
return this;
} }
/**
* Checks if specified biome is a sub-biome of this one.
* @param biome {@link Random}.
* @return true if this instance contains specified biome as a sub-biome.
*/
public boolean containsSubBiome(BCLBiome biome) { public boolean containsSubBiome(BCLBiome biome) {
return subbiomes.contains(biome); return subbiomes.contains(biome);
} }
/**
* Getter for a random sub-biome from all existing sub-biomes. Will return biome itself if there are no sub-biomes.
* @param random {@link Random}.
* @return {@link BCLBiome}.
*/
public BCLBiome getSubBiome(Random random) { public BCLBiome getSubBiome(Random random) {
return subbiomes.get(random); return subbiomes.get(random);
} }
/**
* Getter for parent {@link BCLBiome} or null if there are no parent biome.
* @return {@link BCLBiome} or null.
*/
@Nullable
public BCLBiome getParentBiome() { public BCLBiome getParentBiome() {
return this.biomeParent; return this.biomeParent;
} }
public boolean hasEdge() { /**
return edge != null; * Compares biome instances (directly) and their parents. Used in custom world generator.
} * @param biome {@link BCLBiome}
* @return true if biome or its parent is same.
public boolean hasParentBiome() { */
return biomeParent != null;
}
public boolean isSame(BCLBiome biome) { public boolean isSame(BCLBiome biome) {
return biome == this || (biome.hasParentBiome() && biome.getParentBiome() == this); return biome == this || (biome.biomeParent != null && biome.biomeParent == this);
}
public Biome getBiome() {
return biome;
}
@Override
public String toString() {
return mcID.toString();
} }
/**
* Getter for biome identifier.
* @return {@link ResourceLocation}
*/
public ResourceLocation getID() { public ResourceLocation getID() {
return mcID; return biomeID;
} }
/**
* Getter for fog density, used in custom for renderer.
* @return fog density as a float.
*/
public float getFogDensity() { public float getFogDensity() {
return fogDensity; return fogDensity;
} }
protected void readStructureList() { /**
String ns = mcID.getNamespace(); * Sets fog density for this biome.
String nm = mcID.getPath(); * @param fogDensity
* @return same {@link BCLBiome}.
String path = "/data/" + ns + "/structures/biome/" + nm + "/"; */
InputStream inputstream = StructureHelper.class.getResourceAsStream(path + "structures.json"); public BCLBiome setFogDensity(float fogDensity) {
if (inputstream != null) { this.fogDensity = fogDensity;
JsonObject obj = JsonFactory.getJsonObject(inputstream); return this;
JsonArray enties = obj.getAsJsonArray("structures");
if (enties != null) {
List<StructureInfo> list = Lists.newArrayList();
enties.forEach((entry) -> {
JsonObject e = entry.getAsJsonObject();
String structure = path + e.get("nbt").getAsString() + ".nbt";
TerrainMerge terrainMerge = TerrainMerge.getFromString(e.get("terrainMerge").getAsString());
int offsetY = e.get("offsetY").getAsInt();
list.add(new StructureInfo(structure, offsetY, terrainMerge));
});
if (!list.isEmpty()) {
structuresFeature = BCLFeature.makeChansedFeature(
new ResourceLocation(ns, nm + "_structures"),
new ListFeature(list),
10
);
}
}
}
} }
public BCLFeature getStructuresFeature() { /**
return structuresFeature; * Getter for biome from buil-in registry. For datapack biomes will be same as actual biome.
* @return {@link Biome}.
*/
public Biome getBiome() {
return biome;
} }
/**
* Getter for actual biome (biome from current world registry with same {@link ResourceLocation} id).
* @return {@link Biome}.
*/
public Biome getActualBiome() { public Biome getActualBiome() {
return this.actualBiome; return this.actualBiome;
} }
/**
* Getter for biome generation chance, used in {@link ru.bclib.world.generator.BiomePicker} and in custom generators.
* @return biome generation chance as float.
*/
public float getGenChance() { public float getGenChance() {
return this.genChance; return this.genChance;
} }
/**
* Set gen chance for this biome, default value is 1.0.
* @param genChance chance of this biome to be generated.
* @return same {@link BCLBiome}.
*/
public BCLBiome setGenChance(float genChance) {
this.genChance = genChance;
return this;
}
/**
* Recursively update biomes to correct world biome registry instances, for internal usage only.
* @param biomeRegistry {@link Registry} for {@link Biome}.
*/
public void updateActualBiomes(Registry<Biome> biomeRegistry) { public void updateActualBiomes(Registry<Biome> biomeRegistry) {
subbiomes.forEach((sub) -> { subbiomes.forEach((sub) -> {
if (sub != this) { if (sub != this) {
@ -183,7 +223,62 @@ public class BCLBiome {
if (edge != null && edge != this) { if (edge != null && edge != this) {
edge.updateActualBiomes(biomeRegistry); edge.updateActualBiomes(biomeRegistry);
} }
this.actualBiome = biomeRegistry.get(mcID); this.actualBiome = biomeRegistry.get(biomeID);
if (!this.structures.isEmpty()) {
structures.forEach(s -> BiomeAPI.addBiomeStructure(BiomeAPI.getBiomeKey(actualBiome), s));
}
}
/**
* Getter for custom data. Will get custom data object or null if object doesn't exists.
* @param name {@link String} name of data object.
* @return object value or null.
*/
@Nullable
@SuppressWarnings("unchecked")
public <T> T getCustomData(String name) {
return (T) customData.get(name);
}
/**
* Getter for custom data. Will get custom data object or default value if object doesn't exists.
* @param name {@link String} name of data object.
* @param defaultValue object default value.
* @return object value or default value.
*/
@SuppressWarnings("unchecked")
public <T> T getCustomData(String name, T defaultValue) {
return (T) customData.getOrDefault(name, defaultValue);
}
/**
* Adds custom data object to this biome instance.
* @param name {@link String} name of data object.
* @param obj any data to add.
* @return same {@link BCLBiome}.
*/
public BCLBiome addCustomData(String name, Object obj) {
customData.put(name, obj);
return this;
}
/**
* Adds custom data object to this biome instance.
* @param data a {@link Map} with custom data.
* @return same {@link BCLBiome}.
*/
public BCLBiome addCustomData(Map<String, Object> data) {
customData.putAll(data);
return this;
}
/**
* Getter for terrain height, can be used in custom terrain generator.
* @return terrain height.
*/
public float getTerrainHeight() {
return terrainHeight;
} }
@Override @Override
@ -192,20 +287,34 @@ public class BCLBiome {
return true; return true;
} }
BCLBiome biome = (BCLBiome) obj; BCLBiome biome = (BCLBiome) obj;
return biome == null ? false : biome.mcID.equals(mcID); return biome == null ? false : biomeID.equals(biome.biomeID);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return mcID.hashCode(); return biomeID.hashCode();
} }
@SuppressWarnings("unchecked") @Override
public <T> T getCustomData(String name, T defaultValue) { public String toString() {
return (T) customData.getOrDefault(name, defaultValue); return biomeID.toString();
} }
public void addCustomData(String name, Object obj) { /**
customData.put(name, obj); * Adds structures to this biome. For internal use only.
* Used inside {@link ru.bclib.api.biomes.BCLBiomeBuilder}.
*/
public void attachStructures(List<ConfiguredStructureFeature> structures) {
this.structures.addAll(structures);
}
/**
* Sets biome surface rule.
* @param surface {@link SurfaceRules.RuleSource} rule.
*/
public void setSurface(SurfaceRules.RuleSource surface) {
ResourceKey key = BiomeAPI.getBiomeKey(biome);
BiomeAPI.addSurfaceRule(biomeID, SurfaceRules.ifTrue(SurfaceRules.isBiome(key), surface));
this.surface = surface;
} }
} }

View file

@ -1,435 +0,0 @@
package ru.bclib.world.biomes;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.minecraft.core.Registry;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.Music;
import net.minecraft.sounds.Musics;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.AmbientAdditionsSettings;
import net.minecraft.world.level.biome.AmbientMoodSettings;
import net.minecraft.world.level.biome.AmbientParticleSettings;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biome.BiomeCategory;
import net.minecraft.world.level.biome.Biome.Precipitation;
import net.minecraft.world.level.biome.BiomeGenerationSettings;
import net.minecraft.world.level.biome.BiomeSpecialEffects.Builder;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.levelgen.GenerationStep.Carving;
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.carver.CarverConfiguration;
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder;
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilder;
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilderBaseConfiguration;
import ru.bclib.config.IdConfig;
import ru.bclib.config.PathConfig;
import ru.bclib.util.ColorUtil;
import ru.bclib.world.features.BCLFeature;
import ru.bclib.world.structures.BCLStructureFeature;
import ru.bclib.world.surface.DoubleBlockSurfaceBuilder;
import java.util.List;
import java.util.Map;
public class BCLBiomeDef {
public static final int DEF_FOLIAGE_OVERWORLD = ColorUtil.color(110, 143, 64);
public static final int DEF_FOLIAGE_NETHER = ColorUtil.color(117, 10, 10);
public static final int DEF_FOLIAGE_END = ColorUtil.color(197, 210, 112);
private final List<ConfiguredStructureFeature<?, ?>> structures = Lists.newArrayList();
private final List<FeatureInfo> features = Lists.newArrayList();
private final List<CarverInfo> carvers = Lists.newArrayList();
private final List<SpawnInfo> mobs = Lists.newArrayList();
private final List<SpawnerData> spawns = Lists.newArrayList();
private final Map<String, Object> customData = Maps.newHashMap();
private final ResourceLocation id;
private AmbientParticleSettings particleConfig;
private AmbientAdditionsSettings additions;
private AmbientMoodSettings mood;
private SoundEvent music;
private SoundEvent loop;
private int foliageColor = DEF_FOLIAGE_OVERWORLD;
private int grassColor = DEF_FOLIAGE_OVERWORLD;
private int waterFogColor = 329011;
private int waterColor = 4159204;
private int fogColor = 10518688;
private int skyColor = 0;
private float fogDensity = 1F;
private float depth = 0.1F;
private Precipitation precipitation = Precipitation.NONE;
private BiomeCategory category = BiomeCategory.NONE;
private float temperature = 1F;
private float genChance = 1F;
private float downfall = 0F;
private int edgeSize = 32;
private ConfiguredSurfaceBuilder<?> surface;
/**
* Custom biome definition. Can be extended with new parameters.
*
* @param id - Biome {@link ResourceLocation} (identifier).
*/
public BCLBiomeDef(ResourceLocation id) {
this.id = id;
}
/**
* Create default definition for The Nether biome.
*
* @return {@link BCLBiomeDef}.
*/
public BCLBiomeDef netherBiome() {
this.foliageColor = DEF_FOLIAGE_NETHER;
this.grassColor = DEF_FOLIAGE_NETHER;
this.setCategory(BiomeCategory.NETHER);
return this;
}
/**
* Create default definition for The End biome.
*
* @return {@link BCLBiomeDef}.
*/
public BCLBiomeDef endBiome() {
this.foliageColor = DEF_FOLIAGE_END;
this.grassColor = DEF_FOLIAGE_END;
this.setCategory(BiomeCategory.THEEND);
return this;
}
/**
* Used to load biome settings from config.
* @param config - {@link IdConfig}.
* @return this {@link BCLBiomeDef}.
*/
public BCLBiomeDef loadConfigValues(IdConfig config) {
this.fogDensity = config.getFloat(id, "fog_density", this.fogDensity);
this.genChance = config.getFloat(id, "generation_chance", this.genChance);
this.edgeSize = config.getInt(id, "edge_size", this.edgeSize);
return this;
}
/**
* Used to load biome settings from config.
* @param config - {@link PathConfig}.
* @return this {@link BCLBiomeDef}.
*/
public BCLBiomeDef loadConfigValues(PathConfig config) {
String biomePath = id.getNamespace() + "." + id.getPath();
this.fogDensity = config.getFloat(biomePath, "fog_density", this.fogDensity);
this.genChance = config.getFloat(biomePath, "generation_chance", this.genChance);
this.edgeSize = config.getInt(biomePath, "edge_size", this.edgeSize);
return this;
}
/**
* Set category of the biome.
* @param category - {@link BiomeCategory}.
* @return this {@link BCLBiomeDef}.
*/
public BCLBiomeDef setCategory(BiomeCategory category) {
this.category = category;
return this;
}
public BCLBiomeDef setPrecipitation(Precipitation precipitation) {
this.precipitation = precipitation;
return this;
}
public BCLBiomeDef setSurface(Block block) {
setSurface(SurfaceBuilder.DEFAULT.configured(new SurfaceBuilderBaseConfiguration(
block.defaultBlockState(),
Blocks.END_STONE.defaultBlockState(),
Blocks.END_STONE.defaultBlockState()
)));
return this;
}
public BCLBiomeDef setSurface(Block block1, Block block2) {
setSurface(DoubleBlockSurfaceBuilder.register("bclib_" + id.getPath() + "_surface")
.setBlock1(block1)
.setBlock2(block2)
.configured());
return this;
}
public BCLBiomeDef setSurface(ConfiguredSurfaceBuilder<?> builder) {
this.surface = builder;
return this;
}
public BCLBiomeDef setParticles(ParticleOptions particle, float probability) {
this.particleConfig = new AmbientParticleSettings(particle, probability);
return this;
}
public BCLBiomeDef setGenChance(float genChance) {
this.genChance = genChance;
return this;
}
public BCLBiomeDef setDepth(float depth) {
this.depth = depth;
return this;
}
public BCLBiomeDef setTemperature(float temperature) {
this.temperature = temperature;
return this;
}
public BCLBiomeDef setDownfall(float downfall) {
this.downfall = downfall;
return this;
}
public BCLBiomeDef setEdgeSize(int edgeSize) {
this.edgeSize = edgeSize;
return this;
}
public BCLBiomeDef addMobSpawn(EntityType<?> type, int weight, int minGroupSize, int maxGroupSize) {
ResourceLocation eID = Registry.ENTITY_TYPE.getKey(type);
if (eID != Registry.ENTITY_TYPE.getDefaultKey()) {
SpawnInfo info = new SpawnInfo();
info.type = type;
info.weight = weight;
info.minGroupSize = minGroupSize;
info.maxGroupSize = maxGroupSize;
mobs.add(info);
}
return this;
}
public BCLBiomeDef addMobSpawn(SpawnerData entry) {
spawns.add(entry);
return this;
}
public BCLBiomeDef addStructureFeature(ConfiguredStructureFeature<?, ?> feature) {
structures.add(feature);
return this;
}
public BCLBiomeDef addStructureFeature(BCLStructureFeature feature) {
structures.add(feature.getFeatureConfigured());
return this;
}
public BCLBiomeDef addFeature(BCLFeature feature) {
FeatureInfo info = new FeatureInfo();
info.featureStep = feature.getFeatureStep();
info.feature = feature.getFeatureConfigured();
features.add(info);
return this;
}
public BCLBiomeDef addFeature(Decoration featureStep, ConfiguredFeature<?, ?> feature) {
FeatureInfo info = new FeatureInfo();
info.featureStep = featureStep;
info.feature = feature;
features.add(info);
return this;
}
private int getColor(int r, int g, int b) {
r = Mth.clamp(r, 0, 255);
g = Mth.clamp(g, 0, 255);
b = Mth.clamp(b, 0, 255);
return ColorUtil.color(r, g, b);
}
public BCLBiomeDef setSkyColor(int rgb) {
this.skyColor = rgb;
return this;
}
public BCLBiomeDef setSkyColor(int r, int g, int b) {
return setSkyColor(getColor(r, g, b));
}
public BCLBiomeDef setFogColor(int rgb) {
this.fogColor = rgb;
return this;
}
public BCLBiomeDef setFogColor(int r, int g, int b) {
return setFogColor(getColor(r, g, b));
}
public BCLBiomeDef setFogDensity(float density) {
this.fogDensity = density;
return this;
}
public BCLBiomeDef setWaterColor(int r, int g, int b) {
this.waterColor = getColor(r, g, b);
return this;
}
public BCLBiomeDef setWaterFogColor(int r, int g, int b) {
this.waterFogColor = getColor(r, g, b);
return this;
}
public BCLBiomeDef setWaterAndFogColor(int r, int g, int b) {
return setWaterColor(r, g, b).setWaterFogColor(r, g, b);
}
public BCLBiomeDef setFoliageColor(int r, int g, int b) {
this.foliageColor = getColor(r, g, b);
return this;
}
public BCLBiomeDef setGrassColor(int r, int g, int b) {
this.grassColor = getColor(r, g, b);
return this;
}
public BCLBiomeDef setPlantsColor(int r, int g, int b) {
return this.setFoliageColor(r, g, b).setGrassColor(r, g, b);
}
public BCLBiomeDef setLoop(SoundEvent loop) {
this.loop = loop;
return this;
}
public BCLBiomeDef setMood(SoundEvent mood) {
this.mood = new AmbientMoodSettings(mood, 6000, 8, 2.0D);
return this;
}
public BCLBiomeDef setAdditions(SoundEvent additions) {
this.additions = new AmbientAdditionsSettings(additions, 0.0111);
return this;
}
public BCLBiomeDef setMusic(SoundEvent music) {
this.music = music;
return this;
}
protected void addCustomToBuild(BiomeGenerationSettings.Builder generationSettings){
}
public Biome build() {
MobSpawnSettings.Builder spawnSettings = new MobSpawnSettings.Builder();
BiomeGenerationSettings.Builder generationSettings = new BiomeGenerationSettings.Builder();
Builder effects = new Builder();
mobs.forEach((spawn) -> {
spawnSettings.addSpawn(
spawn.type.getCategory(),
new MobSpawnSettings.SpawnerData(spawn.type, spawn.weight, spawn.minGroupSize, spawn.maxGroupSize)
);
});
spawns.forEach((entry) -> {
spawnSettings.addSpawn(entry.type.getCategory(), entry);
});
generationSettings.surfaceBuilder(surface == null ? net.minecraft.data.worldgen.SurfaceBuilders.END : surface);
structures.forEach((structure) -> generationSettings.addStructureStart(structure));
features.forEach((info) -> generationSettings.addFeature(info.featureStep, info.feature));
carvers.forEach((info) -> generationSettings.addCarver(info.carverStep, info.carver));
addCustomToBuild(generationSettings);
effects.skyColor(skyColor)
.waterColor(waterColor)
.waterFogColor(waterFogColor)
.fogColor(fogColor)
.foliageColorOverride(foliageColor)
.grassColorOverride(grassColor);
if (loop != null) effects.ambientLoopSound(loop);
if (mood != null) effects.ambientMoodSound(mood);
if (additions != null) effects.ambientAdditionsSound(additions);
if (particleConfig != null) effects.ambientParticle(particleConfig);
effects.backgroundMusic(music != null ? new Music(music, 600, 2400, true) : Musics.END);
return new Biome.BiomeBuilder()
.precipitation(precipitation)
.biomeCategory(category)
.depth(depth)
.scale(0.2F)
.temperature(temperature)
.downfall(downfall)
.specialEffects(effects.build())
.mobSpawnSettings(spawnSettings.build())
.generationSettings(generationSettings.build())
.build();
}
private static final class SpawnInfo {
EntityType<?> type;
int weight;
int minGroupSize;
int maxGroupSize;
}
private static final class FeatureInfo {
Decoration featureStep;
ConfiguredFeature<?, ?> feature;
}
private static final class CarverInfo <C extends CarverConfiguration> {
Carving carverStep;
ConfiguredWorldCarver<C> carver;
}
public ResourceLocation getID() {
return id;
}
public float getFodDensity() {
return fogDensity;
}
public float getGenChance() {
return genChance;
}
public int getEdgeSize() {
return edgeSize;
}
public <C extends CarverConfiguration> BCLBiomeDef addCarver(Carving carverStep, ConfiguredWorldCarver<C> carver) {
CarverInfo info = new CarverInfo();
info.carverStep = carverStep;
info.carver = carver;
carvers.add(info);
return this;
}
public BCLBiomeDef addCustomData(String name, Object value) {
customData.put(name, value);
return this;
}
@SuppressWarnings("unchecked")
public <T> T getCustomData(String name, Object defaultValue) {
return (T) customData.getOrDefault(name, defaultValue);
}
protected Map<String, Object> getCustomData() {
return customData;
}
}

View file

@ -1,13 +1,7 @@
package ru.bclib.world.features; package ru.bclib.world.features;
import net.minecraft.data.worldgen.Features;
import net.minecraft.world.level.levelgen.placement.ConfiguredDecorator;
import ru.bclib.BCLib;
import java.lang.reflect.Field;
public class BCLDecorators { public class BCLDecorators {
public static final ConfiguredDecorator<?> HEIGHTMAP_SQUARE; /*public static final ConfiguredDecorator<?> HEIGHTMAP_SQUARE;
private static final ConfiguredDecorator<?> getDecorator(Field[] fields, int index) { private static final ConfiguredDecorator<?> getDecorator(Field[] fields, int index) {
try { try {
@ -23,5 +17,5 @@ public class BCLDecorators {
Class<?>[] classes = Features.class.getDeclaredClasses(); Class<?>[] classes = Features.class.getDeclaredClasses();
Field[] fields = classes[1].getDeclaredFields(); // Decorators class Field[] fields = classes[1].getDeclaredFields(); // Decorators class
HEIGHTMAP_SQUARE = getDecorator(fields, 17); HEIGHTMAP_SQUARE = getDecorator(fields, 17);
} }*/
} }

View file

@ -2,33 +2,38 @@ package ru.bclib.world.features;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries; import net.minecraft.data.BuiltinRegistries;
import net.minecraft.data.worldgen.placement.PlacementUtils;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.levelgen.GenerationStep.Decoration; import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.VerticalAnchor; import net.minecraft.world.level.levelgen.VerticalAnchor;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.Feature; import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.CountConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration;
import net.minecraft.world.level.levelgen.placement.ChanceDecoratorConfiguration; import net.minecraft.world.level.levelgen.heightproviders.UniformHeight;
import net.minecraft.world.level.levelgen.placement.FeatureDecorator; import net.minecraft.world.level.levelgen.placement.BiomeFilter;
import net.minecraft.world.level.levelgen.placement.CountPlacement;
import net.minecraft.world.level.levelgen.placement.HeightRangePlacement;
import net.minecraft.world.level.levelgen.placement.InSquarePlacement;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.placement.RarityFilter;
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockMatchTest; import net.minecraft.world.level.levelgen.structure.templatesystem.BlockMatchTest;
public class BCLFeature { public class BCLFeature {
private ConfiguredFeature<?, ?> featureConfigured; private PlacedFeature placedFeature;
private Decoration featureStep; private Decoration featureStep;
private Feature<?> feature; private Feature<?> feature;
public BCLFeature(Feature<?> feature, ConfiguredFeature<?, ?> configuredFeature, Decoration featureStep) { public BCLFeature(Feature<?> feature, PlacedFeature placedFeature, Decoration featureStep) {
this.featureConfigured = configuredFeature; this.placedFeature = placedFeature;
this.featureStep = featureStep; this.featureStep = featureStep;
this.feature = feature; this.feature = feature;
} }
public BCLFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, Decoration featureStep, ConfiguredFeature<?, ?> configuredFeature) { public BCLFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, Decoration featureStep, PlacedFeature placedFeature) {
this.featureConfigured = Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, id, configuredFeature); this.placedFeature = Registry.register(BuiltinRegistries.PLACED_FEATURE, id, placedFeature);
this.feature = Registry.register(Registry.FEATURE, id, feature); this.feature = Registry.register(Registry.FEATURE, id, feature);
this.featureStep = featureStep; this.featureStep = featureStep;
} }
@ -43,20 +48,19 @@ public class BCLFeature {
/** /**
* Get configured feature. * Get configured feature.
* @return {@link ConfiguredFeature}. * @return {@link PlacedFeature}.
*/ */
public ConfiguredFeature<?, ?> getFeatureConfigured() { public PlacedFeature getPlacedFeature() {
return featureConfigured; return placedFeature;
} }
/** /**
* Get feature decoration step. * Get feature decoration step.
* @return {@link Decoration}. * @return {@link Decoration}.
*/ */
public Decoration getFeatureStep() { public Decoration getDecoration() {
return featureStep; return featureStep;
} }
/** /**
* Will create a basic plant feature. * Will create a basic plant feature.
* @param id {@link ResourceLocation} feature ID. * @param id {@link ResourceLocation} feature ID.
@ -65,13 +69,16 @@ public class BCLFeature {
* @return new BCLFeature instance. * @return new BCLFeature instance.
*/ */
public static BCLFeature makeVegetationFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, int density) { public static BCLFeature makeVegetationFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, int density) {
ConfiguredFeature<?, ?> configured = feature PlacedFeature configured = feature
.configured(FeatureConfiguration.NONE) .configured(FeatureConfiguration.NONE)
.decorated(BCLDecorators.HEIGHTMAP_SQUARE) .placed(
.countRandom(density); CountPlacement.of(UniformInt.of(0, 4)),
InSquarePlacement.spread(),
PlacementUtils.HEIGHTMAP,
BiomeFilter.biome()
);
return new BCLFeature(id, feature, Decoration.VEGETAL_DECORATION, configured); return new BCLFeature(id, feature, Decoration.VEGETAL_DECORATION, configured);
} }
/** /**
* Will create a basic ore feature. * Will create a basic ore feature.
* @param id {@link ResourceLocation} feature ID. * @param id {@link ResourceLocation} feature ID.
@ -84,22 +91,45 @@ public class BCLFeature {
* @return new BCLFeature instance. * @return new BCLFeature instance.
*/ */
public static BCLFeature makeOreFeature(ResourceLocation id, Block blockOre, Block hostBlock, int veins, int veinSize, int minY, int maxY) { public static BCLFeature makeOreFeature(ResourceLocation id, Block blockOre, Block hostBlock, int veins, int veinSize, int minY, int maxY) {
//TODO: 1.18 See if this still works
return makeOreFeature(id, blockOre, hostBlock, veins, veinSize, minY, maxY, false);
}
/**
* Will create a basic ore feature.
*
* @param id {@link ResourceLocation} feature ID.
* @param blockOre {@link Decoration} feature step.
* @param hostBlock {@link Block} to generate feature in.
* @param veins iterations per chunk.
* @param veinSize size of ore vein.
* @param minY minimum height.
* @param maxY maximum height.
* @param rare when true, this is placed as a rare resource
* @return new BCLFeature instance.
*/
public static BCLFeature makeOreFeature(ResourceLocation id, Block blockOre, Block hostBlock, int veins, int veinSize, int minY, int maxY, boolean rare) {
OreConfiguration featureConfig = new OreConfiguration( OreConfiguration featureConfig = new OreConfiguration(
new BlockMatchTest(hostBlock), new BlockMatchTest(hostBlock),
blockOre.defaultBlockState(), blockOre.defaultBlockState(),
veinSize veinSize
); );
ConfiguredFeature<?, ?> oreFeature = Feature.ORE
PlacedFeature oreFeature = Feature.ORE
.configured(featureConfig) .configured(featureConfig)
.rangeUniform( .placed(
VerticalAnchor.absolute(minY), InSquarePlacement.spread(),
VerticalAnchor.absolute(maxY) rare ? RarityFilter.onAverageOnceEvery(veins) : CountPlacement.of(veins),
) HeightRangePlacement.of(
.squared() UniformHeight.of(
.count(veins); VerticalAnchor.absolute(minY),
VerticalAnchor.absolute(maxY)
)
),
BiomeFilter.biome());
return new BCLFeature( return new BCLFeature(
Feature.ORE, net.minecraft.world.level.levelgen.feature.Feature.ORE,
Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, id, oreFeature), Registry.register(BuiltinRegistries.PLACED_FEATURE, id, oreFeature),
Decoration.UNDERGROUND_ORES Decoration.UNDERGROUND_ORES
); );
} }
@ -112,9 +142,9 @@ public class BCLFeature {
* @return new BCLFeature instance. * @return new BCLFeature instance.
*/ */
public static BCLFeature makeChunkFeature(ResourceLocation id, Decoration step, Feature<NoneFeatureConfiguration> feature) { public static BCLFeature makeChunkFeature(ResourceLocation id, Decoration step, Feature<NoneFeatureConfiguration> feature) {
ConfiguredFeature<?, ?> configured = feature PlacedFeature configured = feature
.configured(FeatureConfiguration.NONE) .configured(FeatureConfiguration.NONE)
.decorated(FeatureDecorator.COUNT.configured(new CountConfiguration(1))); .placed(CountPlacement.of(1));
return new BCLFeature(id, feature, step, configured); return new BCLFeature(id, feature, step, configured);
} }
@ -127,9 +157,9 @@ public class BCLFeature {
* @return new BCLFeature instance. * @return new BCLFeature instance.
*/ */
public static BCLFeature makeChancedFeature(ResourceLocation id, Decoration step, Feature<NoneFeatureConfiguration> feature, int chance) { public static BCLFeature makeChancedFeature(ResourceLocation id, Decoration step, Feature<NoneFeatureConfiguration> feature, int chance) {
ConfiguredFeature<?, ?> configured = feature PlacedFeature configured = feature
.configured(FeatureConfiguration.NONE) .configured(FeatureConfiguration.NONE)
.decorated(FeatureDecorator.CHANCE.configured(new ChanceDecoratorConfiguration(chance))); .placed(RarityFilter.onAverageOnceEvery(chance));
return new BCLFeature(id, feature, step, configured); return new BCLFeature(id, feature, step, configured);
} }
@ -142,9 +172,10 @@ public class BCLFeature {
* @return new BCLFeature instance. * @return new BCLFeature instance.
*/ */
public static BCLFeature makeCountFeature(ResourceLocation id, Decoration step, Feature<NoneFeatureConfiguration> feature, int count) { public static BCLFeature makeCountFeature(ResourceLocation id, Decoration step, Feature<NoneFeatureConfiguration> feature, int count) {
ConfiguredFeature<?, ?> configured = feature PlacedFeature configured = feature
.configured(FeatureConfiguration.NONE) .configured(FeatureConfiguration.NONE)
.decorated(FeatureDecorator.COUNT.configured(new CountConfiguration(count))); .placed(CountPlacement.of(count));
//.decorated(FeatureDecorator.COUNT.configured(new CountConfiguration(count)));
return new BCLFeature(id, feature, step, configured); return new BCLFeature(id, feature, step, configured);
} }
@ -156,37 +187,7 @@ public class BCLFeature {
* @return new BCLFeature instance. * @return new BCLFeature instance.
*/ */
public static BCLFeature makeFeatureConfigured(ResourceLocation id, Decoration step, Feature<NoneFeatureConfiguration> feature) { public static BCLFeature makeFeatureConfigured(ResourceLocation id, Decoration step, Feature<NoneFeatureConfiguration> feature) {
ConfiguredFeature<?, ?> configured = feature.configured(FeatureConfiguration.NONE); PlacedFeature configured = feature.configured(FeatureConfiguration.NONE).placed();
return new BCLFeature(id, feature, step, configured); return new BCLFeature(id, feature, step, configured);
} }
@Deprecated(forRemoval = true)
public static BCLFeature makeOreFeature(ResourceLocation id, Block blockOre, Block hostBlock, int veins, int veinSize, int offset, int minY, int maxY) {
return makeOreFeature(id, blockOre, hostBlock, veins, veinSize, minY, maxY);
}
@Deprecated(forRemoval = true)
public static BCLFeature makeRawGenFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, int chance) {
return makeChancedFeature(id, Decoration.RAW_GENERATION, feature, chance);
}
@Deprecated(forRemoval = true)
public static BCLFeature makeChunkFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature) {
return makeChunkFeature(id, Decoration.LOCAL_MODIFICATIONS, feature);
}
@Deprecated(forRemoval = true)
public static BCLFeature makeChansedFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, int chance) {
return makeChancedFeature(id, Decoration.SURFACE_STRUCTURES, feature, chance);
}
@Deprecated(forRemoval = true)
public static BCLFeature makeCountRawFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, int chance) {
return makeCountFeature(id, Decoration.RAW_GENERATION, feature, chance);
}
@Deprecated(forRemoval = true)
public static BCLFeature makeFeatureConfigured(ResourceLocation id, Feature<NoneFeatureConfiguration> feature) {
return makeFeatureConfigured(id, Decoration.RAW_GENERATION, feature);
}
} }

View file

@ -10,6 +10,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
@ -18,9 +19,8 @@ import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConf
import net.minecraft.world.level.levelgen.structure.BoundingBox; import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilderConfiguration;
import ru.bclib.api.BiomeAPI;
import ru.bclib.api.TagAPI; import ru.bclib.api.TagAPI;
import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.util.BlocksHelper; import ru.bclib.util.BlocksHelper;
import ru.bclib.world.processors.DestructionStructureProcessor; import ru.bclib.world.processors.DestructionStructureProcessor;
@ -142,11 +142,14 @@ public abstract class NBTStructureFeature extends DefaultFeature {
BlockState stateSt = world.getBlockState(mut); BlockState stateSt = world.getBlockState(mut);
if (!stateSt.is(TagAPI.BLOCK_GEN_TERRAIN)) { if (!stateSt.is(TagAPI.BLOCK_GEN_TERRAIN)) {
if (merge == TerrainMerge.SURFACE) { if (merge == TerrainMerge.SURFACE) {
SurfaceBuilderConfiguration config = world.getBiome(mut) // SurfaceBuilderConfiguration config = world.getBiome(mut)
.getGenerationSettings() // .getGenerationSettings()
.getSurfaceBuilderConfig(); // .getSurfaceBuilderConfig();
boolean isTop = mut.getY() == surfMax && state.getMaterial().isSolidBlocking(); boolean isTop = mut.getY() == surfMax && state.getMaterial().isSolidBlocking();
BlockState top = isTop ? config.getTopMaterial() : config.getUnderMaterial(); BlockState top =
Blocks.PURPLE_CONCRETE.defaultBlockState();
//TODO: 1.18 find another way to get the Top/Bottom Materiel
//isTop ? config.getTopMaterial() : config.getUnderMaterial();
BlocksHelper.setWithoutUpdate(world, mut, top); BlocksHelper.setWithoutUpdate(world, mut, top);
} }
else { else {
@ -156,10 +159,13 @@ public abstract class NBTStructureFeature extends DefaultFeature {
else { else {
if (stateSt.is(TagAPI.BLOCK_END_GROUND) && state.getMaterial().isSolidBlocking()) { if (stateSt.is(TagAPI.BLOCK_END_GROUND) && state.getMaterial().isSolidBlocking()) {
if (merge == TerrainMerge.SURFACE) { if (merge == TerrainMerge.SURFACE) {
SurfaceBuilderConfiguration config = world.getBiome(mut) // SurfaceBuilderConfiguration config = world.getBiome(mut)
.getGenerationSettings() // .getGenerationSettings()
.getSurfaceBuilderConfig(); // .getSurfaceBuilderConfig();
BlocksHelper.setWithoutUpdate(world, mut, config.getUnderMaterial()); BlockState bottom = Blocks.PURPLE_CONCRETE.defaultBlockState();
//TODO: 1.18 find another way to get the Top Material
//config.getUnderMaterial()
BlocksHelper.setWithoutUpdate(world, mut, bottom);
} }
else { else {
BlocksHelper.setWithoutUpdate(world, mut, state); BlocksHelper.setWithoutUpdate(world, mut, state);

View file

@ -9,15 +9,20 @@ import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biome.BiomeCategory; import net.minecraft.world.level.biome.Biome.BiomeCategory;
import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Biomes; import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.biome.TheEndBiomeSource; import net.minecraft.world.level.biome.TheEndBiomeSource;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
import net.minecraft.world.level.levelgen.WorldgenRandom; import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.synth.SimplexNoise; import net.minecraft.world.level.levelgen.synth.SimplexNoise;
import ru.bclib.BCLib; import ru.bclib.BCLib;
import ru.bclib.api.BiomeAPI; import ru.bclib.api.biomes.BiomeAPI;
import ru.bclib.config.ConfigKeeper.StringArrayEntry; import ru.bclib.config.ConfigKeeper.StringArrayEntry;
import ru.bclib.config.Configs; import ru.bclib.config.Configs;
import ru.bclib.interfaces.BiomeMap;
import ru.bclib.noise.OpenSimplexNoise; import ru.bclib.noise.OpenSimplexNoise;
import ru.bclib.world.biomes.BCLBiome; import ru.bclib.world.biomes.BCLBiome;
import ru.bclib.world.generator.map.hex.HexBiomeMap;
import ru.bclib.world.generator.map.square.SquareBiomeMap;
import java.awt.Point; import java.awt.Point;
import java.util.List; import java.util.List;
@ -45,20 +50,35 @@ public class BCLibEndBiomeSource extends BiomeSource {
public BCLibEndBiomeSource(Registry<Biome> biomeRegistry, long seed) { public BCLibEndBiomeSource(Registry<Biome> biomeRegistry, long seed) {
super(getBiomes(biomeRegistry)); super(getBiomes(biomeRegistry));
BiomeAPI.initRegistry(biomeRegistry);
BiomeAPI.END_LAND_BIOME_PICKER.clearMutables(); BiomeAPI.END_LAND_BIOME_PICKER.clearMutables();
BiomeAPI.END_VOID_BIOME_PICKER.clearMutables(); BiomeAPI.END_VOID_BIOME_PICKER.clearMutables();
this.possibleBiomes.forEach(biome -> { List<String> includeVoid = Configs.BIOMES_CONFIG.getEntry("force_include", "end_void_biomes", StringArrayEntry.class).getValue();
this.possibleBiomes().forEach(biome -> {
ResourceLocation key = biomeRegistry.getKey(biome); ResourceLocation key = biomeRegistry.getKey(biome);
if (!BiomeAPI.hasBiome(key)) { if (!BiomeAPI.hasBiome(key)) {
BCLBiome bclBiome = new BCLBiome(key, biome, 1, 1); String group = key.getNamespace() + "." + key.getPath();
BiomeAPI.END_LAND_BIOME_PICKER.addBiomeMutable(bclBiome); float chance = Configs.BIOMES_CONFIG.getFloat(group, "generation_chance", 1.0F);
float fog = Configs.BIOMES_CONFIG.getFloat(group, "fog_density", 1.0F);
BCLBiome bclBiome = new BCLBiome(key, biome).setGenChance(chance).setFogDensity(fog);
if (includeVoid.contains(key.toString())) {
BiomeAPI.END_VOID_BIOME_PICKER.addBiomeMutable(bclBiome);
}
else {
BiomeAPI.END_LAND_BIOME_PICKER.addBiomeMutable(bclBiome);
}
} }
else { else {
BCLBiome bclBiome = BiomeAPI.getBiome(key); BCLBiome bclBiome = BiomeAPI.getBiome(key);
if (bclBiome != BiomeAPI.EMPTY_BIOME && !bclBiome.hasParentBiome()) { if (bclBiome != BiomeAPI.EMPTY_BIOME && bclBiome.getParentBiome() == null) {
if (!BiomeAPI.END_LAND_BIOME_PICKER.containsImmutable(key) && !BiomeAPI.END_VOID_BIOME_PICKER.containsImmutable(key)) { if (!BiomeAPI.END_LAND_BIOME_PICKER.containsImmutable(key) && !BiomeAPI.END_VOID_BIOME_PICKER.containsImmutable(key)) {
BiomeAPI.END_LAND_BIOME_PICKER.addBiomeMutable(bclBiome); if (includeVoid.contains(key.toString())) {
BiomeAPI.END_VOID_BIOME_PICKER.addBiomeMutable(bclBiome);
}
else {
BiomeAPI.END_LAND_BIOME_PICKER.addBiomeMutable(bclBiome);
}
} }
} }
} }
@ -72,14 +92,21 @@ public class BCLibEndBiomeSource extends BiomeSource {
BiomeAPI.END_LAND_BIOME_PICKER.rebuild(); BiomeAPI.END_LAND_BIOME_PICKER.rebuild();
BiomeAPI.END_VOID_BIOME_PICKER.rebuild(); BiomeAPI.END_VOID_BIOME_PICKER.rebuild();
this.mapLand = new BiomeMap(seed, GeneratorOptions.getBiomeSizeEndLand(), BiomeAPI.END_LAND_BIOME_PICKER); if (GeneratorOptions.useOldBiomeGenerator()) {
this.mapVoid = new BiomeMap(seed, GeneratorOptions.getBiomeSizeEndVoid(), BiomeAPI.END_VOID_BIOME_PICKER); this.mapLand = new SquareBiomeMap(seed, GeneratorOptions.getBiomeSizeEndLand(), BiomeAPI.END_LAND_BIOME_PICKER);
this.mapVoid = new SquareBiomeMap(seed, GeneratorOptions.getBiomeSizeEndVoid(), BiomeAPI.END_VOID_BIOME_PICKER);
}
else {
this.mapLand = new HexBiomeMap(seed, GeneratorOptions.getBiomeSizeEndLand(), BiomeAPI.END_LAND_BIOME_PICKER);
this.mapVoid = new HexBiomeMap(seed, GeneratorOptions.getBiomeSizeEndVoid(), BiomeAPI.END_VOID_BIOME_PICKER);
}
this.centerBiome = biomeRegistry.getOrThrow(Biomes.THE_END); this.centerBiome = biomeRegistry.getOrThrow(Biomes.THE_END);
this.barrens = biomeRegistry.getOrThrow(Biomes.END_BARRENS); this.barrens = biomeRegistry.getOrThrow(Biomes.END_BARRENS);
this.biomeRegistry = biomeRegistry; this.biomeRegistry = biomeRegistry;
this.seed = seed; this.seed = seed;
WorldgenRandom chunkRandom = new WorldgenRandom(seed); WorldgenRandom chunkRandom = new WorldgenRandom(new LegacyRandomSource(seed));
chunkRandom.consumeCount(17292); chunkRandom.consumeCount(17292);
this.noise = new SimplexNoise(chunkRandom); this.noise = new SimplexNoise(chunkRandom);
@ -88,12 +115,13 @@ public class BCLibEndBiomeSource extends BiomeSource {
} }
private static List<Biome> getBiomes(Registry<Biome> biomeRegistry) { private static List<Biome> getBiomes(Registry<Biome> biomeRegistry) {
List<String> include = Configs.BIOMES_CONFIG.getEntry("force_include", "end_biomes", StringArrayEntry.class).getValue(); List<String> includeLand = Configs.BIOMES_CONFIG.getEntry("force_include", "end_land_biomes", StringArrayEntry.class).getValue();
List<String> includeVoid = Configs.BIOMES_CONFIG.getEntry("force_include", "end_void_biomes", StringArrayEntry.class).getValue();
return biomeRegistry.stream().filter(biome -> { return biomeRegistry.stream().filter(biome -> {
ResourceLocation key = biomeRegistry.getKey(biome); ResourceLocation key = biomeRegistry.getKey(biome);
if (include.contains(key.toString())) { if (includeLand.contains(key.toString()) || includeVoid.contains(key.toString())) {
return true; return true;
} }
@ -103,7 +131,7 @@ public class BCLibEndBiomeSource extends BiomeSource {
BCLBiome bclBiome = BiomeAPI.getBiome(key); BCLBiome bclBiome = BiomeAPI.getBiome(key);
if (bclBiome != BiomeAPI.EMPTY_BIOME) { if (bclBiome != BiomeAPI.EMPTY_BIOME) {
if (bclBiome.hasParentBiome()) { if (bclBiome.getParentBiome() != null) {
bclBiome = bclBiome.getParentBiome(); bclBiome = bclBiome.getParentBiome();
} }
key = bclBiome.getID(); key = bclBiome.getID();
@ -113,7 +141,7 @@ public class BCLibEndBiomeSource extends BiomeSource {
} }
@Override @Override
public Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ) { public Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler sampler) {
long i = (long) biomeX * (long) biomeX; long i = (long) biomeX * (long) biomeX;
long j = (long) biomeZ * (long) biomeZ; long j = (long) biomeZ * (long) biomeZ;
long check = GeneratorOptions.isFarEndBiomes() ? 65536L : 625L; long check = GeneratorOptions.isFarEndBiomes() ? 65536L : 625L;

Some files were not shown because too many files have changed in this diff Show more